├── .gitignore ├── .jshintrc ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser" : false, 3 | "curly" : true, 4 | "devel" : false, 5 | "eqeqeq" : true, 6 | "eqnull" : true, 7 | "es5" : true, 8 | "esnext" : true, 9 | "expr" : true, 10 | "forin" : false, 11 | "immed" : false, 12 | "indent" : 4, 13 | "latedef" : false, 14 | "laxcomma" : true, 15 | "maxcomplexity" : 39, 16 | "maxdepth" : 5, 17 | "maxparams" : 7, 18 | "maxstatements" : 100, 19 | "multistr" : true, 20 | "newcap" : true, 21 | "noarg" : true, 22 | "noempty" : true, 23 | "nonew" : false, 24 | "node" : true, 25 | "plusplus" : false, 26 | "regexp" : false, 27 | "undef" : true, 28 | "unused" : true, 29 | "strict" : false, 30 | "swindent" : true, 31 | "sub" : true, 32 | "trailing" : false, 33 | "undef" : true, 34 | "unused" : true, 35 | 36 | "globals" : { 37 | "before" : true, 38 | "after" : true, 39 | "it" : true, 40 | "console" : true, 41 | "should" : true, 42 | "describe" : true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 jut-io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tcp-port-used 2 | ============= 3 | 4 | A simple Node.js module to check if a TCP port is currently in use. It returns a 5 | deferred promise from the q library. 6 | 7 | ## Installation 8 | 9 | npm install tcp-port-used 10 | 11 | ## Examples 12 | To check a port's state: 13 | 14 | var tcpPortUsed = require('tcp-port-used'); 15 | 16 | tcpPortUsed.check(44201, '127.0.0.1') 17 | .then(function(inUse) { 18 | console.log('Port 44201 usage: '+inUse); 19 | }, function(err) { 20 | console.error('Error on check:', err.message); 21 | }); 22 | 23 | To wait until a port on localhost is available: 24 | 25 | tcpPortUsed.waitUntilFree(44203, 500, 4000) 26 | .then(function() { 27 | console.log('Port 44203 is now free.'); 28 | }, function(err) { 29 | console.log('Error:', err.message); 30 | }); 31 | 32 | To wait until a port on a host is available: 33 | 34 | tcpPortUsed.waitUntilFreeOnHost(44203, 'some.host.com', 500, 4000) 35 | .then(function() { 36 | console.log('Port 44203 on some.host.com is now free.'); 37 | }, function(err) { 38 | console.log('Error:', err.message); 39 | }); 40 | 41 | To wait until a port on localhost is accepting connections: 42 | 43 | tcpPortUsed.waitUntilUsed(44204, 500, 4000) 44 | .then(function() { 45 | console.log('Port 44204 is now in use.'); 46 | }, function(err) { 47 | console.log('Error:', err.message); 48 | }); 49 | 50 | To wait until a port on a host is accepting connections: 51 | 52 | tcpPortUsed.waitUntilUsedOnHost(44204, 'some.host.com', 500, 4000) 53 | .then(function() { 54 | console.log('Port 44204 on some.host.com is now in use.'); 55 | }, function(err) { 56 | console.log('Error:', err.message); 57 | }); 58 | 59 | To wait until a port on a host is in specific state: 60 | 61 | var inUse = true; // wait until the port is in use 62 | tcpPortUsed.waitForStatus(44204, 'some.host.com', inUse, 500, 4000) 63 | .then(function() { 64 | console.log('Port 44204 on some.host.com is now in use.'); 65 | }, function(err) { 66 | console.log('Error:', err.message); 67 | }); 68 | 69 | 70 | ## API 71 | 72 | ### check(port [, host]) 73 | Checks if a TCP port is in use by attempting to connect to the port on host. 74 | If no host is specified, the module uses '127.0.0.1' (localhost). When the 75 | promise is resolved, there is a parameter `inUse`, when true means the port is 76 | in use and false means the port is free. 77 | 78 | **Parameters:** 79 | 80 | * **Number|Object** *port* The port you are curious to see if available. If an 81 | object, must contain all the parameters as properties. 82 | * **String** *host* The host name or IP address of the host. Default, if not defined: '127.0.0.1' 83 | 84 | **Returns:** 85 | 86 | **Object** A deferred promise from the q module. 87 | 88 | ### waitUntilFree(port [, retryTimeMs] [, timeOutMs]) 89 | Returns a deferred promise and fulfills it only when the localhost socket is 90 | free. Will retry on an interval specified in retryTimeMs until the timeout. If 91 | not defined the retryTime is 200 ms and the timeout is 2000 ms. 92 | 93 | **Parameters:** 94 | 95 | * **Number|Object** *port* a valid TCP port number. If an object must contain 96 | all the parameters as properties. 97 | * **Number** *[retryTimeMs]* the retry interval in milliseconds - defaultis is 100ms. 98 | * **Number** *[timeOutMs]* the amount of time to wait until port is free. Default 300ms. 99 | 100 | **Returns:** 101 | 102 | **Object** A deferred promise from the q module. 103 | 104 | 105 | ### waitUntilFreeOnHost(port [, host] [, retryTimeMs] [, timeOutMs]) 106 | Returns a deferred promise and fulfills it only when the localhost socket is 107 | free. Will retry on an interval specified in retryTimeMs until the timeout. If 108 | not defined the retryTime is 200 ms and the timeout is 2000 ms. If the host is 109 | not defined, the modules uses the default '127.0.0.1'. 110 | 111 | **Parameters:** 112 | 113 | * **Number|Object** *port* a valid TCP port number. If an object, must contain 114 | all the parameters as properties. 115 | * **String** *host* The host name or IP address of the host. Default, if not defined: '127.0.0.1' 116 | * **Number** *[retryTimeMs]* the retry interval in milliseconds - defaultis is 100ms. 117 | * **Number** *[timeOutMs]* the amount of time to wait until port is free. Default 300ms. 118 | 119 | **Returns:** 120 | 121 | **Object** A deferred promise from the q module. 122 | 123 | ### waitUntilUsed(port [, retryTimeMs] [, timeOutMs]) 124 | Returns a deferred promise and fulfills it only when the socket is accepting 125 | connections. Will retry on an interval specified in retryTimeMs until the 126 | timeout. If the host is not defined the retryTime is 200 ms and the timeout is 127 | 2000 ms. 128 | 129 | **Parameters:** 130 | 131 | * **Number|Object** *port* a valid TCP port number. If an object, must contain 132 | all the parameters as properties. 133 | * **Number** *[retryTimeMs]* the retry interval in milliseconds - defaultis is 100ms. 134 | * **Number** *[timeOutMs]* the amount of time to wait until port is free. Default 300ms. 135 | 136 | **Returns:** 137 | 138 | **Object** A deferred promise from the q module. 139 | 140 | ### waitUntilUsedOnHost(port [, host] [, retryTimeMs] [, timeOutMs]) 141 | Returns a deferred promise and fulfills it only when the socket is accepting 142 | connections. Will retry on an interval specified in retryTimeMs until the 143 | timeout. If not defined the retryTime is 200 ms and the timeout is 2000 ms. 144 | If the host is not defined the module uses the default '127.0.0.1'. 145 | 146 | **Parameters:** 147 | 148 | * **Number|Object** *port* a valid TCP port number. If an object, must contain 149 | all the parameters as properties. 150 | * **String** *host* The host name or IP address of the host. Default, if not defined: '127.0.0.1' 151 | * **Number** *[retryTimeMs]* the retry interval in milliseconds - defaultis is 100ms. 152 | * **Number** *[timeOutMs]* the amount of time to wait until port is free. Default 300ms. 153 | 154 | **Returns:** 155 | 156 | **Object** A deferred promise from the q module. 157 | 158 | ### waitForStatus(port, host, status [, retryTimeMs] [, timeOutMs]) 159 | Waits until the port on host matches the boolean status in terms of use. If the 160 | status is true, the promise defers until the port is in use. If the status is 161 | false the promise defers until the port is free. If the host is undefined or 162 | null, the module uses the default '127.0.0.1'. Also, if not defined the 163 | retryTime is 200 ms and the timeout is 2000 ms. 164 | 165 | **Parameters:** 166 | 167 | * **Number** *port* a valid TCP port number. If an object, must contain all the 168 | parameters as properties. 169 | * **String** *host* The host name or IP address of the host. Default, if not defined: '127.0.0.1' 170 | * **Boolean** *status* A boolean describing the condition to wait for in terms of "in use." True indicates wait until the port is in use. False indicates wait until the port is free. 171 | * **Number** *[retryTimeMs]* the retry interval in milliseconds - defaultis is 100ms. 172 | * **Number** *[timeOutMs]* the amount of time to wait until port is free. Default 300ms. 173 | 174 | **Returns:** 175 | 176 | **Object** A deferred promise from the q module. 177 | 178 | ## License 179 | 180 | The MIT License (MIT) 181 | 182 | Copyright (c) 2013 jut-io 183 | 184 | Permission is hereby granted, free of charge, to any person obtaining a copy of 185 | this software and associated documentation files (the "Software"), to deal in 186 | the Software without restriction, including without limitation the rights to 187 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 188 | the Software, and to permit persons to whom the Software is furnished to do so, 189 | subject to the following conditions: 190 | 191 | The above copyright notice and this permission notice shall be included in all 192 | copies or substantial portions of the Software. 193 | 194 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 195 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 196 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 197 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 198 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 199 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 200 | 201 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileOverview 3 | * A simple promises-based check to see if a TCP port is already in use. 4 | */ 5 | 'use strict'; 6 | 7 | // define the exports first to avoid cyclic dependencies. 8 | exports.check = check; 9 | exports.waitUntilFreeOnHost = waitUntilFreeOnHost; 10 | exports.waitUntilFree = waitUntilFree; 11 | exports.waitUntilUsedOnHost = waitUntilUsedOnHost; 12 | exports.waitUntilUsed = waitUntilUsed; 13 | exports.waitForStatus = waitForStatus; 14 | 15 | var is = require('is2'); 16 | var net = require('net'); 17 | var util = require('util'); 18 | var debug = require('debug')('tcp-port-used'); 19 | 20 | // Global Values 21 | var TIMEOUT = 2000; 22 | var RETRYTIME = 250; 23 | 24 | function getDeferred() { 25 | var resolve, reject, promise = new Promise(function(res, rej) { 26 | resolve = res; 27 | reject = rej; 28 | }); 29 | 30 | return { 31 | resolve: resolve, 32 | reject: reject, 33 | promise: promise 34 | }; 35 | } 36 | 37 | /** 38 | * Creates an options object from all the possible arguments 39 | * @private 40 | * @param {Number} port a valid TCP port number 41 | * @param {String} host The DNS name or IP address. 42 | * @param {Boolean} status The desired in use status to wait for: false === not in use, true === in use 43 | * @param {Number} retryTimeMs the retry interval in milliseconds - defaultis is 200ms 44 | * @param {Number} timeOutMs the amount of time to wait until port is free default is 1000ms 45 | * @return {Object} An options object with all the above parameters as properties. 46 | */ 47 | function makeOptionsObj(port, host, inUse, retryTimeMs, timeOutMs) { 48 | var opts = {}; 49 | opts.port = port; 50 | opts.host = host; 51 | opts.inUse = inUse; 52 | opts.retryTimeMs = retryTimeMs; 53 | opts.timeOutMs = timeOutMs; 54 | return opts; 55 | } 56 | 57 | /** 58 | * Checks if a TCP port is in use by creating the socket and binding it to the 59 | * target port. Once bound, successfully, it's assume the port is availble. 60 | * After the socket is closed or in error, the promise is resolved. 61 | * Note: you have to be super user to correctly test system ports (0-1023). 62 | * @param {Number|Object} port The port you are curious to see if available. If an object, must have the parameters as properties. 63 | * @param {String} [host] May be a DNS name or IP address. Default '127.0.0.1' 64 | * @return {Object} A deferred Q promise. 65 | * 66 | * Example usage: 67 | * 68 | * var tcpPortUsed = require('tcp-port-used'); 69 | * tcpPortUsed.check(22, '127.0.0.1') 70 | * .then(function(inUse) { 71 | * debug('Port 22 usage: '+inUse); 72 | * }, function(err) { 73 | * console.error('Error on check: '+util.inspect(err)); 74 | * }); 75 | */ 76 | function check(port, host) { 77 | 78 | var deferred = getDeferred(); 79 | var inUse = true; 80 | var client; 81 | 82 | var opts; 83 | if (!is.obj(port)) { 84 | opts = makeOptionsObj(port, host); 85 | } else { 86 | opts = port; 87 | } 88 | 89 | if (!is.port(opts.port)) { 90 | debug('Error invalid port: '+util.inspect(opts.port)); 91 | deferred.reject(new Error('invalid port: '+util.inspect(opts.port))); 92 | return deferred.promise; 93 | } 94 | 95 | if (is.nullOrUndefined(opts.host)) { 96 | debug('set host address to default 127.0.0.1'); 97 | opts.host = '127.0.0.1'; 98 | } 99 | 100 | function cleanUp() { 101 | if (client) { 102 | client.removeAllListeners('connect'); 103 | client.removeAllListeners('error'); 104 | client.end(); 105 | client.destroy(); 106 | client.unref(); 107 | } 108 | //debug('listeners removed from client socket'); 109 | } 110 | 111 | function onConnectCb() { 112 | //debug('check - promise resolved - in use'); 113 | deferred.resolve(inUse); 114 | cleanUp(); 115 | } 116 | 117 | function onErrorCb(err) { 118 | if (err.code !== 'ECONNREFUSED') { 119 | //debug('check - promise rejected, error: '+err.message); 120 | deferred.reject(err); 121 | } else { 122 | //debug('ECONNREFUSED'); 123 | inUse = false; 124 | //debug('check - promise resolved - not in use'); 125 | deferred.resolve(inUse); 126 | } 127 | cleanUp(); 128 | } 129 | 130 | client = new net.Socket(); 131 | client.once('connect', onConnectCb); 132 | client.once('error', onErrorCb); 133 | client.connect({port: opts.port, host: opts.host}, function() {}); 134 | 135 | return deferred.promise; 136 | } 137 | 138 | /** 139 | * Creates a deferred promise and fulfills it only when the socket's usage 140 | * equals status in terms of 'in use' (false === not in use, true === in use). 141 | * Will retry on an interval specified in retryTimeMs. Note: you have to be 142 | * super user to correctly test system ports (0-1023). 143 | * @param {Number|Object} port a valid TCP port number, if an object, has all the parameters described as properties. 144 | * @param {String} host The DNS name or IP address. 145 | * @param {Boolean} status The desired in use status to wait for false === not in use, true === in use 146 | * @param {Number} [retryTimeMs] the retry interval in milliseconds - defaultis is 200ms 147 | * @param {Number} [timeOutMs] the amount of time to wait until port is free default is 1000ms 148 | * @return {Object} A deferred promise from the Q library. 149 | * 150 | * Example usage: 151 | * 152 | * var tcpPortUsed = require('tcp-port-used'); 153 | * tcpPortUsed.waitForStatus(44204, 'some.host.com', true, 500, 4000) 154 | * .then(function() { 155 | * console.log('Port 44204 is now in use.'); 156 | * }, function(err) { 157 | * console.log('Error: ', error.message); 158 | * }); 159 | */ 160 | function waitForStatus(port, host, inUse, retryTimeMs, timeOutMs) { 161 | 162 | var deferred = getDeferred(); 163 | var timeoutId; 164 | var timedout = false; 165 | var retryId; 166 | 167 | // the first arument may be an object, if it is not, make an object 168 | var opts; 169 | if (is.obj(port)) { 170 | opts = port; 171 | } else { 172 | opts = makeOptionsObj(port, host, inUse, retryTimeMs, timeOutMs); 173 | } 174 | 175 | //debug('opts:'+util.inspect(opts); 176 | 177 | if (!is.bool(opts.inUse)) { 178 | deferred.reject(new Error('inUse must be a boolean')); 179 | return deferred.promise; 180 | } 181 | 182 | if (!is.positiveInt(opts.retryTimeMs)) { 183 | opts.retryTimeMs = RETRYTIME; 184 | debug('set retryTime to default '+RETRYTIME+'ms'); 185 | } 186 | 187 | if (!is.positiveInt(opts.timeOutMs)) { 188 | opts.timeOutMs = TIMEOUT; 189 | debug('set timeOutMs to default '+TIMEOUT+'ms'); 190 | } 191 | 192 | function cleanUp() { 193 | if (timeoutId) { 194 | clearTimeout(timeoutId); 195 | } 196 | if (retryId) { 197 | clearTimeout(retryId); 198 | } 199 | } 200 | 201 | function timeoutFunc() { 202 | timedout = true; 203 | cleanUp(); 204 | deferred.reject(new Error('timeout')); 205 | } 206 | timeoutId = setTimeout(timeoutFunc, opts.timeOutMs); 207 | 208 | function doCheck() { 209 | check(opts.port, opts.host) 210 | .then(function(inUse) { 211 | if (timedout) { 212 | return; 213 | } 214 | //debug('doCheck inUse: '+inUse); 215 | //debug('doCheck opts.inUse: '+opts.inUse); 216 | if (inUse === opts.inUse) { 217 | deferred.resolve(); 218 | cleanUp(); 219 | return; 220 | } else { 221 | retryId = setTimeout(function() { doCheck(); }, opts.retryTimeMs); 222 | return; 223 | } 224 | }, function(err) { 225 | if (timedout) { 226 | return; 227 | } 228 | deferred.reject(err); 229 | cleanUp(); 230 | }); 231 | } 232 | 233 | doCheck(); 234 | return deferred.promise; 235 | } 236 | 237 | /** 238 | * Creates a deferred promise and fulfills it only when the socket is free. 239 | * Will retry on an interval specified in retryTimeMs. 240 | * Note: you have to be super user to correctly test system ports (0-1023). 241 | * @param {Number} port a valid TCP port number 242 | * @param {String} [host] The hostname or IP address of where the socket is. 243 | * @param {Number} [retryTimeMs] the retry interval in milliseconds - defaultis is 100ms. 244 | * @param {Number} [timeOutMs] the amount of time to wait until port is free. Default 300ms. 245 | * @return {Object} A deferred promise from the q library. 246 | * 247 | * Example usage: 248 | * 249 | * var tcpPortUsed = require('tcp-port-used'); 250 | * tcpPortUsed.waitUntilFreeOnHost(44203, 'some.host.com', 500, 4000) 251 | * .then(function() { 252 | * console.log('Port 44203 is now free.'); 253 | * }, function(err) { 254 | * console.loh('Error: ', error.message); 255 | * }); 256 | */ 257 | function waitUntilFreeOnHost(port, host, retryTimeMs, timeOutMs) { 258 | 259 | // the first arument may be an object, if it is not, make an object 260 | var opts; 261 | if (is.obj(port)) { 262 | opts = port; 263 | opts.inUse = false; 264 | } else { 265 | opts = makeOptionsObj(port, host, false, retryTimeMs, timeOutMs); 266 | } 267 | 268 | return waitForStatus(opts); 269 | } 270 | 271 | /** 272 | * For compatibility with previous version of the module, that did not provide 273 | * arguements for hostnames. The host is set to the localhost '127.0.0.1'. 274 | * @param {Number|Object} port a valid TCP port number. If an object, must contain all the parameters as properties. 275 | * @param {Number} [retryTimeMs] the retry interval in milliseconds - defaultis is 100ms. 276 | * @param {Number} [timeOutMs] the amount of time to wait until port is free. Default 300ms. 277 | * @return {Object} A deferred promise from the q library. 278 | * 279 | * Example usage: 280 | * 281 | * var tcpPortUsed = require('tcp-port-used'); 282 | * tcpPortUsed.waitUntilFree(44203, 500, 4000) 283 | * .then(function() { 284 | * console.log('Port 44203 is now free.'); 285 | * }, function(err) { 286 | * console.loh('Error: ', error.message); 287 | * }); 288 | */ 289 | function waitUntilFree(port, retryTimeMs, timeOutMs) { 290 | 291 | // the first arument may be an object, if it is not, make an object 292 | var opts; 293 | if (is.obj(port)) { 294 | opts = port; 295 | opts.host = '127.0.0.1'; 296 | opts.inUse = false; 297 | } else { 298 | opts = makeOptionsObj(port, '127.0.0.1', false, retryTimeMs, timeOutMs); 299 | } 300 | 301 | return waitForStatus(opts); 302 | } 303 | 304 | /** 305 | * Creates a deferred promise and fulfills it only when the socket is used. 306 | * Will retry on an interval specified in retryTimeMs. 307 | * Note: you have to be super user to correctly test system ports (0-1023). 308 | * @param {Number|Object} port a valid TCP port number. If an object, must contain all the parameters as properties. 309 | * @param {Number} [retryTimeMs] the retry interval in milliseconds - defaultis is 500ms 310 | * @param {Number} [timeOutMs] the amount of time to wait until port is free 311 | * @return {Object} A deferred promise from the q library. 312 | * 313 | * Example usage: 314 | * 315 | * var tcpPortUsed = require('tcp-port-used'); 316 | * tcpPortUsed.waitUntilUsedOnHost(44204, 'some.host.com', 500, 4000) 317 | * .then(function() { 318 | * console.log('Port 44204 is now in use.'); 319 | * }, function(err) { 320 | * console.log('Error: ', error.message); 321 | * }); 322 | */ 323 | function waitUntilUsedOnHost(port, host, retryTimeMs, timeOutMs) { 324 | 325 | // the first arument may be an object, if it is not, make an object 326 | var opts; 327 | if (is.obj(port)) { 328 | opts = port; 329 | opts.inUse = true; 330 | } else { 331 | opts = makeOptionsObj(port, host, true, retryTimeMs, timeOutMs); 332 | } 333 | 334 | return waitForStatus(opts); 335 | } 336 | 337 | /** 338 | * For compatibility to previous version of module which did not have support 339 | * for host addresses. This function works only for localhost. 340 | * @param {Number} port a valid TCP port number. If an Object, must contain all the parameters as properties. 341 | * @param {Number} [retryTimeMs] the retry interval in milliseconds - defaultis is 500ms 342 | * @param {Number} [timeOutMs] the amount of time to wait until port is free 343 | * @return {Object} A deferred promise from the q library. 344 | * 345 | * Example usage: 346 | * 347 | * var tcpPortUsed = require('tcp-port-used'); 348 | * tcpPortUsed.waitUntilUsed(44204, 500, 4000) 349 | * .then(function() { 350 | * console.log('Port 44204 is now in use.'); 351 | * }, function(err) { 352 | * console.log('Error: ', error.message); 353 | * }); 354 | */ 355 | function waitUntilUsed(port, retryTimeMs, timeOutMs) { 356 | 357 | // the first arument may be an object, if it is not, make an object 358 | var opts; 359 | if (is.obj(port)) { 360 | opts = port; 361 | opts.host = '127.0.0.1'; 362 | opts.inUse = true; 363 | } else { 364 | opts = makeOptionsObj(port, '127.0.0.1', true, retryTimeMs, timeOutMs); 365 | } 366 | 367 | return waitUntilUsedOnHost(opts); 368 | } 369 | 370 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tcp-port-used", 3 | "version": "1.0.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@ungap/promise-all-settled": { 8 | "version": "1.1.2", 9 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 10 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 11 | "dev": true 12 | }, 13 | "ansi-colors": { 14 | "version": "4.1.1", 15 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 16 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 17 | "dev": true 18 | }, 19 | "ansi-regex": { 20 | "version": "3.0.0", 21 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 22 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 23 | "dev": true 24 | }, 25 | "ansi-styles": { 26 | "version": "4.3.0", 27 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 28 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 29 | "dev": true, 30 | "requires": { 31 | "color-convert": "^2.0.1" 32 | } 33 | }, 34 | "anymatch": { 35 | "version": "3.1.1", 36 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 37 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 38 | "dev": true, 39 | "requires": { 40 | "normalize-path": "^3.0.0", 41 | "picomatch": "^2.0.4" 42 | } 43 | }, 44 | "argparse": { 45 | "version": "1.0.10", 46 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 47 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 48 | "dev": true, 49 | "requires": { 50 | "sprintf-js": "~1.0.2" 51 | } 52 | }, 53 | "balanced-match": { 54 | "version": "1.0.0", 55 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 56 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 57 | "dev": true 58 | }, 59 | "binary-extensions": { 60 | "version": "2.1.0", 61 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 62 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 63 | "dev": true 64 | }, 65 | "brace-expansion": { 66 | "version": "1.1.11", 67 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 68 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 69 | "dev": true, 70 | "requires": { 71 | "balanced-match": "^1.0.0", 72 | "concat-map": "0.0.1" 73 | } 74 | }, 75 | "braces": { 76 | "version": "3.0.2", 77 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 78 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 79 | "dev": true, 80 | "requires": { 81 | "fill-range": "^7.0.1" 82 | } 83 | }, 84 | "browser-stdout": { 85 | "version": "1.3.1", 86 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 87 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 88 | "dev": true 89 | }, 90 | "camelcase": { 91 | "version": "5.3.1", 92 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 93 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 94 | "dev": true 95 | }, 96 | "chalk": { 97 | "version": "4.1.0", 98 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 99 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 100 | "dev": true, 101 | "requires": { 102 | "ansi-styles": "^4.1.0", 103 | "supports-color": "^7.1.0" 104 | } 105 | }, 106 | "chokidar": { 107 | "version": "3.4.3", 108 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 109 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 110 | "dev": true, 111 | "requires": { 112 | "anymatch": "~3.1.1", 113 | "braces": "~3.0.2", 114 | "fsevents": "~2.1.2", 115 | "glob-parent": "~5.1.0", 116 | "is-binary-path": "~2.1.0", 117 | "is-glob": "~4.0.1", 118 | "normalize-path": "~3.0.0", 119 | "readdirp": "~3.5.0" 120 | } 121 | }, 122 | "cliui": { 123 | "version": "5.0.0", 124 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 125 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 126 | "dev": true, 127 | "requires": { 128 | "string-width": "^3.1.0", 129 | "strip-ansi": "^5.2.0", 130 | "wrap-ansi": "^5.1.0" 131 | }, 132 | "dependencies": { 133 | "ansi-regex": { 134 | "version": "4.1.0", 135 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 136 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 137 | "dev": true 138 | }, 139 | "string-width": { 140 | "version": "3.1.0", 141 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 142 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 143 | "dev": true, 144 | "requires": { 145 | "emoji-regex": "^7.0.1", 146 | "is-fullwidth-code-point": "^2.0.0", 147 | "strip-ansi": "^5.1.0" 148 | } 149 | }, 150 | "strip-ansi": { 151 | "version": "5.2.0", 152 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 153 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 154 | "dev": true, 155 | "requires": { 156 | "ansi-regex": "^4.1.0" 157 | } 158 | } 159 | } 160 | }, 161 | "color-convert": { 162 | "version": "2.0.1", 163 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 164 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 165 | "dev": true, 166 | "requires": { 167 | "color-name": "~1.1.4" 168 | } 169 | }, 170 | "color-name": { 171 | "version": "1.1.4", 172 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 173 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 174 | "dev": true 175 | }, 176 | "concat-map": { 177 | "version": "0.0.1", 178 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 179 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 180 | "dev": true 181 | }, 182 | "debug": { 183 | "version": "4.3.1", 184 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 185 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 186 | "requires": { 187 | "ms": "2.1.2" 188 | } 189 | }, 190 | "decamelize": { 191 | "version": "1.2.0", 192 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 193 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 194 | "dev": true 195 | }, 196 | "deep-is": { 197 | "version": "0.1.3", 198 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 199 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" 200 | }, 201 | "diff": { 202 | "version": "4.0.2", 203 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 204 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 205 | "dev": true 206 | }, 207 | "emoji-regex": { 208 | "version": "7.0.3", 209 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 210 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 211 | "dev": true 212 | }, 213 | "escape-string-regexp": { 214 | "version": "4.0.0", 215 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 216 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 217 | "dev": true 218 | }, 219 | "esprima": { 220 | "version": "4.0.1", 221 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 222 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 223 | "dev": true 224 | }, 225 | "fill-range": { 226 | "version": "7.0.1", 227 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 228 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 229 | "dev": true, 230 | "requires": { 231 | "to-regex-range": "^5.0.1" 232 | } 233 | }, 234 | "find-up": { 235 | "version": "5.0.0", 236 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 237 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 238 | "dev": true, 239 | "requires": { 240 | "locate-path": "^6.0.0", 241 | "path-exists": "^4.0.0" 242 | } 243 | }, 244 | "flat": { 245 | "version": "5.0.2", 246 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 247 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 248 | "dev": true 249 | }, 250 | "fs.realpath": { 251 | "version": "1.0.0", 252 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 253 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 254 | "dev": true 255 | }, 256 | "fsevents": { 257 | "version": "2.1.3", 258 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 259 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 260 | "dev": true, 261 | "optional": true 262 | }, 263 | "get-caller-file": { 264 | "version": "2.0.5", 265 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 266 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 267 | "dev": true 268 | }, 269 | "glob": { 270 | "version": "7.1.6", 271 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 272 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 273 | "dev": true, 274 | "requires": { 275 | "fs.realpath": "^1.0.0", 276 | "inflight": "^1.0.4", 277 | "inherits": "2", 278 | "minimatch": "^3.0.4", 279 | "once": "^1.3.0", 280 | "path-is-absolute": "^1.0.0" 281 | } 282 | }, 283 | "glob-parent": { 284 | "version": "5.1.1", 285 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 286 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 287 | "dev": true, 288 | "requires": { 289 | "is-glob": "^4.0.1" 290 | } 291 | }, 292 | "growl": { 293 | "version": "1.10.5", 294 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 295 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 296 | "dev": true 297 | }, 298 | "has-flag": { 299 | "version": "4.0.0", 300 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 301 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 302 | "dev": true 303 | }, 304 | "he": { 305 | "version": "1.2.0", 306 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 307 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 308 | "dev": true 309 | }, 310 | "inflight": { 311 | "version": "1.0.6", 312 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 313 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 314 | "dev": true, 315 | "requires": { 316 | "once": "^1.3.0", 317 | "wrappy": "1" 318 | } 319 | }, 320 | "inherits": { 321 | "version": "2.0.4", 322 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 323 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 324 | "dev": true 325 | }, 326 | "ip-regex": { 327 | "version": "2.1.0", 328 | "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", 329 | "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" 330 | }, 331 | "is-binary-path": { 332 | "version": "2.1.0", 333 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 334 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 335 | "dev": true, 336 | "requires": { 337 | "binary-extensions": "^2.0.0" 338 | } 339 | }, 340 | "is-extglob": { 341 | "version": "2.1.1", 342 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 343 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 344 | "dev": true 345 | }, 346 | "is-fullwidth-code-point": { 347 | "version": "2.0.0", 348 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 349 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 350 | "dev": true 351 | }, 352 | "is-glob": { 353 | "version": "4.0.1", 354 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 355 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 356 | "dev": true, 357 | "requires": { 358 | "is-extglob": "^2.1.1" 359 | } 360 | }, 361 | "is-number": { 362 | "version": "7.0.0", 363 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 364 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 365 | "dev": true 366 | }, 367 | "is-plain-obj": { 368 | "version": "2.1.0", 369 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 370 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 371 | "dev": true 372 | }, 373 | "is-url": { 374 | "version": "1.2.4", 375 | "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", 376 | "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" 377 | }, 378 | "is2": { 379 | "version": "2.0.1", 380 | "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.1.tgz", 381 | "integrity": "sha512-+WaJvnaA7aJySz2q/8sLjMb2Mw14KTplHmSwcSpZ/fWJPkUmqw3YTzSWbPJ7OAwRvdYTWF2Wg+yYJ1AdP5Z8CA==", 382 | "requires": { 383 | "deep-is": "^0.1.3", 384 | "ip-regex": "^2.1.0", 385 | "is-url": "^1.2.2" 386 | } 387 | }, 388 | "isexe": { 389 | "version": "2.0.0", 390 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 391 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 392 | "dev": true 393 | }, 394 | "js-yaml": { 395 | "version": "3.14.0", 396 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 397 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 398 | "dev": true, 399 | "requires": { 400 | "argparse": "^1.0.7", 401 | "esprima": "^4.0.0" 402 | } 403 | }, 404 | "locate-path": { 405 | "version": "6.0.0", 406 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 407 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 408 | "dev": true, 409 | "requires": { 410 | "p-locate": "^5.0.0" 411 | } 412 | }, 413 | "log-symbols": { 414 | "version": "4.0.0", 415 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 416 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 417 | "dev": true, 418 | "requires": { 419 | "chalk": "^4.0.0" 420 | } 421 | }, 422 | "minimatch": { 423 | "version": "3.0.4", 424 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 425 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 426 | "dev": true, 427 | "requires": { 428 | "brace-expansion": "^1.1.7" 429 | } 430 | }, 431 | "mocha": { 432 | "version": "8.2.1", 433 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", 434 | "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", 435 | "dev": true, 436 | "requires": { 437 | "@ungap/promise-all-settled": "1.1.2", 438 | "ansi-colors": "4.1.1", 439 | "browser-stdout": "1.3.1", 440 | "chokidar": "3.4.3", 441 | "debug": "4.2.0", 442 | "diff": "4.0.2", 443 | "escape-string-regexp": "4.0.0", 444 | "find-up": "5.0.0", 445 | "glob": "7.1.6", 446 | "growl": "1.10.5", 447 | "he": "1.2.0", 448 | "js-yaml": "3.14.0", 449 | "log-symbols": "4.0.0", 450 | "minimatch": "3.0.4", 451 | "ms": "2.1.2", 452 | "nanoid": "3.1.12", 453 | "serialize-javascript": "5.0.1", 454 | "strip-json-comments": "3.1.1", 455 | "supports-color": "7.2.0", 456 | "which": "2.0.2", 457 | "wide-align": "1.1.3", 458 | "workerpool": "6.0.2", 459 | "yargs": "13.3.2", 460 | "yargs-parser": "13.1.2", 461 | "yargs-unparser": "2.0.0" 462 | }, 463 | "dependencies": { 464 | "debug": { 465 | "version": "4.2.0", 466 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 467 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 468 | "dev": true, 469 | "requires": { 470 | "ms": "2.1.2" 471 | } 472 | } 473 | } 474 | }, 475 | "ms": { 476 | "version": "2.1.2", 477 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 478 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 479 | }, 480 | "nanoid": { 481 | "version": "3.1.12", 482 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", 483 | "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", 484 | "dev": true 485 | }, 486 | "normalize-path": { 487 | "version": "3.0.0", 488 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 489 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 490 | "dev": true 491 | }, 492 | "once": { 493 | "version": "1.4.0", 494 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 495 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 496 | "dev": true, 497 | "requires": { 498 | "wrappy": "1" 499 | } 500 | }, 501 | "p-limit": { 502 | "version": "3.1.0", 503 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 504 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 505 | "dev": true, 506 | "requires": { 507 | "yocto-queue": "^0.1.0" 508 | } 509 | }, 510 | "p-locate": { 511 | "version": "5.0.0", 512 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 513 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 514 | "dev": true, 515 | "requires": { 516 | "p-limit": "^3.0.2" 517 | } 518 | }, 519 | "p-try": { 520 | "version": "2.2.0", 521 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 522 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 523 | "dev": true 524 | }, 525 | "path-exists": { 526 | "version": "4.0.0", 527 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 528 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 529 | "dev": true 530 | }, 531 | "path-is-absolute": { 532 | "version": "1.0.1", 533 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 534 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 535 | "dev": true 536 | }, 537 | "picomatch": { 538 | "version": "2.2.2", 539 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 540 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 541 | "dev": true 542 | }, 543 | "randombytes": { 544 | "version": "2.1.0", 545 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 546 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 547 | "dev": true, 548 | "requires": { 549 | "safe-buffer": "^5.1.0" 550 | } 551 | }, 552 | "readdirp": { 553 | "version": "3.5.0", 554 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 555 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 556 | "dev": true, 557 | "requires": { 558 | "picomatch": "^2.2.1" 559 | } 560 | }, 561 | "require-directory": { 562 | "version": "2.1.1", 563 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 564 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 565 | "dev": true 566 | }, 567 | "require-main-filename": { 568 | "version": "2.0.0", 569 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 570 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 571 | "dev": true 572 | }, 573 | "safe-buffer": { 574 | "version": "5.2.1", 575 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 576 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 577 | "dev": true 578 | }, 579 | "serialize-javascript": { 580 | "version": "5.0.1", 581 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 582 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 583 | "dev": true, 584 | "requires": { 585 | "randombytes": "^2.1.0" 586 | } 587 | }, 588 | "set-blocking": { 589 | "version": "2.0.0", 590 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 591 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 592 | "dev": true 593 | }, 594 | "sprintf-js": { 595 | "version": "1.0.3", 596 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 597 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 598 | "dev": true 599 | }, 600 | "string-width": { 601 | "version": "2.1.1", 602 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 603 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 604 | "dev": true, 605 | "requires": { 606 | "is-fullwidth-code-point": "^2.0.0", 607 | "strip-ansi": "^4.0.0" 608 | } 609 | }, 610 | "strip-ansi": { 611 | "version": "4.0.0", 612 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 613 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 614 | "dev": true, 615 | "requires": { 616 | "ansi-regex": "^3.0.0" 617 | } 618 | }, 619 | "strip-json-comments": { 620 | "version": "3.1.1", 621 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 622 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 623 | "dev": true 624 | }, 625 | "supports-color": { 626 | "version": "7.2.0", 627 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 628 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 629 | "dev": true, 630 | "requires": { 631 | "has-flag": "^4.0.0" 632 | } 633 | }, 634 | "to-regex-range": { 635 | "version": "5.0.1", 636 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 637 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 638 | "dev": true, 639 | "requires": { 640 | "is-number": "^7.0.0" 641 | } 642 | }, 643 | "which": { 644 | "version": "2.0.2", 645 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 646 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 647 | "dev": true, 648 | "requires": { 649 | "isexe": "^2.0.0" 650 | } 651 | }, 652 | "which-module": { 653 | "version": "2.0.0", 654 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 655 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 656 | "dev": true 657 | }, 658 | "wide-align": { 659 | "version": "1.1.3", 660 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 661 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 662 | "dev": true, 663 | "requires": { 664 | "string-width": "^1.0.2 || 2" 665 | } 666 | }, 667 | "workerpool": { 668 | "version": "6.0.2", 669 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", 670 | "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", 671 | "dev": true 672 | }, 673 | "wrap-ansi": { 674 | "version": "5.1.0", 675 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 676 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 677 | "dev": true, 678 | "requires": { 679 | "ansi-styles": "^3.2.0", 680 | "string-width": "^3.0.0", 681 | "strip-ansi": "^5.0.0" 682 | }, 683 | "dependencies": { 684 | "ansi-regex": { 685 | "version": "4.1.0", 686 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 687 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 688 | "dev": true 689 | }, 690 | "ansi-styles": { 691 | "version": "3.2.1", 692 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 693 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 694 | "dev": true, 695 | "requires": { 696 | "color-convert": "^1.9.0" 697 | } 698 | }, 699 | "color-convert": { 700 | "version": "1.9.3", 701 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 702 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 703 | "dev": true, 704 | "requires": { 705 | "color-name": "1.1.3" 706 | } 707 | }, 708 | "color-name": { 709 | "version": "1.1.3", 710 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 711 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 712 | "dev": true 713 | }, 714 | "string-width": { 715 | "version": "3.1.0", 716 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 717 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 718 | "dev": true, 719 | "requires": { 720 | "emoji-regex": "^7.0.1", 721 | "is-fullwidth-code-point": "^2.0.0", 722 | "strip-ansi": "^5.1.0" 723 | } 724 | }, 725 | "strip-ansi": { 726 | "version": "5.2.0", 727 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 728 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 729 | "dev": true, 730 | "requires": { 731 | "ansi-regex": "^4.1.0" 732 | } 733 | } 734 | } 735 | }, 736 | "wrappy": { 737 | "version": "1.0.2", 738 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 739 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 740 | "dev": true 741 | }, 742 | "y18n": { 743 | "version": "4.0.1", 744 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 745 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", 746 | "dev": true 747 | }, 748 | "yargs": { 749 | "version": "13.3.2", 750 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 751 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 752 | "dev": true, 753 | "requires": { 754 | "cliui": "^5.0.0", 755 | "find-up": "^3.0.0", 756 | "get-caller-file": "^2.0.1", 757 | "require-directory": "^2.1.1", 758 | "require-main-filename": "^2.0.0", 759 | "set-blocking": "^2.0.0", 760 | "string-width": "^3.0.0", 761 | "which-module": "^2.0.0", 762 | "y18n": "^4.0.0", 763 | "yargs-parser": "^13.1.2" 764 | }, 765 | "dependencies": { 766 | "ansi-regex": { 767 | "version": "4.1.0", 768 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 769 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 770 | "dev": true 771 | }, 772 | "find-up": { 773 | "version": "3.0.0", 774 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 775 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 776 | "dev": true, 777 | "requires": { 778 | "locate-path": "^3.0.0" 779 | } 780 | }, 781 | "locate-path": { 782 | "version": "3.0.0", 783 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 784 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 785 | "dev": true, 786 | "requires": { 787 | "p-locate": "^3.0.0", 788 | "path-exists": "^3.0.0" 789 | } 790 | }, 791 | "p-limit": { 792 | "version": "2.3.0", 793 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 794 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 795 | "dev": true, 796 | "requires": { 797 | "p-try": "^2.0.0" 798 | } 799 | }, 800 | "p-locate": { 801 | "version": "3.0.0", 802 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 803 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 804 | "dev": true, 805 | "requires": { 806 | "p-limit": "^2.0.0" 807 | } 808 | }, 809 | "path-exists": { 810 | "version": "3.0.0", 811 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 812 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 813 | "dev": true 814 | }, 815 | "string-width": { 816 | "version": "3.1.0", 817 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 818 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 819 | "dev": true, 820 | "requires": { 821 | "emoji-regex": "^7.0.1", 822 | "is-fullwidth-code-point": "^2.0.0", 823 | "strip-ansi": "^5.1.0" 824 | } 825 | }, 826 | "strip-ansi": { 827 | "version": "5.2.0", 828 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 829 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 830 | "dev": true, 831 | "requires": { 832 | "ansi-regex": "^4.1.0" 833 | } 834 | } 835 | } 836 | }, 837 | "yargs-parser": { 838 | "version": "13.1.2", 839 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 840 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 841 | "dev": true, 842 | "requires": { 843 | "camelcase": "^5.0.0", 844 | "decamelize": "^1.2.0" 845 | } 846 | }, 847 | "yargs-unparser": { 848 | "version": "2.0.0", 849 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 850 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 851 | "dev": true, 852 | "requires": { 853 | "camelcase": "^6.0.0", 854 | "decamelize": "^4.0.0", 855 | "flat": "^5.0.2", 856 | "is-plain-obj": "^2.1.0" 857 | }, 858 | "dependencies": { 859 | "camelcase": { 860 | "version": "6.2.0", 861 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 862 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 863 | "dev": true 864 | }, 865 | "decamelize": { 866 | "version": "4.0.0", 867 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 868 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 869 | "dev": true 870 | } 871 | } 872 | }, 873 | "yocto-queue": { 874 | "version": "0.1.0", 875 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 876 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 877 | "dev": true 878 | } 879 | } 880 | } 881 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tcp-port-used", 3 | "version": "1.0.2", 4 | "description": "A simple Node.js module to check if a TCP port is already bound.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "./node_modules/.bin/mocha --reporter=list ./test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/stdarg/tcp-port-used.git" 12 | }, 13 | "keywords": [ 14 | "tcp", 15 | "port", 16 | "available", 17 | "free", 18 | "check", 19 | "networking" 20 | ], 21 | "author": "Edmond Meinfelder", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/stdargtcp-port-used/issues" 25 | }, 26 | "homepage": "https://github.com/stdarg/tcp-port-used", 27 | "dependencies": { 28 | "debug": "4.3.1", 29 | "is2": "2.0.1" 30 | }, 31 | "devDependencies": { 32 | "mocha": "^8.2.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var assert = require('assert'); 3 | var tcpPortUsed = require('./index'); 4 | var net = require('net'); 5 | //var debug = require('debug')('tcp-port-used-test'); 6 | 7 | var server; 8 | 9 | function freePort(cb) { 10 | if (!server) { 11 | return cb(new Error('Port not in use')); 12 | } 13 | 14 | server.close(); 15 | server.unref(); 16 | server = undefined; 17 | cb(); 18 | } 19 | 20 | function bindPort(port, cb) { 21 | if (server) { 22 | return cb(new Error('Free the server port, first.')); 23 | } 24 | 25 | server = net.createServer(); 26 | server.listen(port); 27 | 28 | function errEventCb(err) { 29 | server.close(); 30 | if (cb) { 31 | rmListeners(); 32 | cb(err); 33 | } 34 | server = undefined; 35 | } 36 | 37 | function listenEventCb() { 38 | if (cb) { 39 | rmListeners(); 40 | cb(); 41 | } 42 | } 43 | 44 | function rmListeners() { 45 | server.removeListener('error', errEventCb); 46 | server.removeListener('listening', listenEventCb); 47 | } 48 | 49 | server.on('error', errEventCb); 50 | server.on('listening', listenEventCb); 51 | } 52 | 53 | describe('check arguments', function() { 54 | it('should not accept negative port numbers in an obj', function(done) { 55 | tcpPortUsed.check({ port: -20, host: '127.0.0.1' }) 56 | .then(function() { 57 | done(new Error('check unexpectedly succeeded')); 58 | }, function(err) { 59 | assert.ok(err && err.message === 'invalid port: -20'); 60 | done(); 61 | }); 62 | }); 63 | 64 | it('should not accept negative port numbers', function(done) { 65 | tcpPortUsed.check(-20, '127.0.0.1') 66 | .then(function() { 67 | done(new Error('check unexpectedly succeeded')); 68 | }, function(err) { 69 | assert.ok(err && err.message === 'invalid port: -20'); 70 | done(); 71 | }); 72 | }); 73 | 74 | it('should not accept invalid types for port numbers in an obj', function(done) { 75 | tcpPortUsed.check({port:'hello', host:'127.0.0.1'}) 76 | .then(function() { 77 | done(new Error('check unexpectedly succeeded')); 78 | }, function(err) { 79 | assert.ok(err && err.message === 'invalid port: \'hello\''); 80 | done(); 81 | }); 82 | }); 83 | 84 | it('should not accept invalid types for port numbers', function(done) { 85 | tcpPortUsed.check('hello', '127.0.0.1') 86 | .then(function() { 87 | done(new Error('check unexpectedly succeeded')); 88 | }, function(err) { 89 | assert.ok(err && err.message === 'invalid port: \'hello\''); 90 | done(); 91 | }); 92 | }); 93 | 94 | it('should require an argument for a port number in an obj', function(done) { 95 | tcpPortUsed.check({}) 96 | .then(function() { 97 | done(new Error('check unexpectedly succeeded')); 98 | }, function(err) { 99 | assert.ok(err && err.message === 'invalid port: undefined'); 100 | done(); 101 | }); 102 | }); 103 | 104 | it('should require an argument for a port number', function(done) { 105 | tcpPortUsed.check() 106 | .then(function() { 107 | done(new Error('check unexpectedly succeeded')); 108 | }, function(err) { 109 | assert.ok(err && err.message === 'invalid port: undefined'); 110 | done(); 111 | }); 112 | }); 113 | 114 | it('should not accept port number > 65535 in an obj', function(done) { 115 | tcpPortUsed.check({port: 65536}) 116 | .then(function() { 117 | done(new Error('check unexpectedly succeeded')); 118 | }, function(err) { 119 | assert.ok(err && err.message === 'invalid port: 65536'); 120 | done(); 121 | }); 122 | }); 123 | 124 | 125 | it('should not accept port number > 65535', function(done) { 126 | tcpPortUsed.check(65536) 127 | .then(function() { 128 | done(new Error('check unexpectedly succeeded')); 129 | }, function(err) { 130 | assert.ok(err && err.message === 'invalid port: 65536'); 131 | done(); 132 | }); 133 | }); 134 | 135 | it('should not accept port number < 0 in an obj', function(done) { 136 | tcpPortUsed.check({port: -1}) 137 | .then(function() { 138 | done(new Error('check unexpectedly succeeded')); 139 | }, function(err) { 140 | assert.ok(err && err.message === 'invalid port: -1'); 141 | done(); 142 | }); 143 | }); 144 | 145 | it('should not accept port number < 0', function(done) { 146 | tcpPortUsed.check(-1) 147 | .then(function() { 148 | done(new Error('check unexpectedly succeeded')); 149 | }, function(err) { 150 | assert.ok(err && err.message === 'invalid port: -1'); 151 | done(); 152 | }); 153 | }); 154 | }); 155 | 156 | describe('check functionality for unused port', function() { 157 | before(function(done) { 158 | bindPort(44202, function(err) { 159 | done(err); 160 | }); 161 | }); 162 | 163 | it('should return true for a used port with default host value in an obj', function(done) { 164 | tcpPortUsed.check({port: 44202}) 165 | .then(function(inUse) { 166 | assert.ok(inUse === true); 167 | done(); 168 | }, function(err) { 169 | done(err); 170 | }); 171 | }); 172 | 173 | 174 | it('should return true for a used port with default host value', function(done) { 175 | tcpPortUsed.check(44202) 176 | .then(function(inUse) { 177 | assert.ok(inUse === true); 178 | done(); 179 | }, function(err) { 180 | done(err); 181 | }); 182 | }); 183 | 184 | it('should return true for a used port with default host value using arg obj', function(done) { 185 | tcpPortUsed.check({ port: 44202 }) 186 | .then(function(inUse) { 187 | assert.ok(inUse === true); 188 | done(); 189 | }, function(err) { 190 | done(err); 191 | }); 192 | }); 193 | 194 | it('should return true for a used port with given host value using arg obj', function(done) { 195 | tcpPortUsed.check({port: 44202, host: '127.0.0.1'}) 196 | .then(function(inUse) { 197 | assert.ok(inUse === true); 198 | done(); 199 | }, function(err) { 200 | assert.ok(false); 201 | done(err); 202 | }); 203 | }); 204 | 205 | 206 | it('should return true for a used port with given host value', function(done) { 207 | tcpPortUsed.check(44202, '127.0.0.1') 208 | .then(function(inUse) { 209 | assert.ok(inUse === true); 210 | done(); 211 | }, function(err) { 212 | assert.ok(false); 213 | done(err); 214 | }); 215 | }); 216 | 217 | it('should return false for an unused port and default host using arg object', function(done) { 218 | tcpPortUsed.check({port: 44201}) 219 | .then(function(inUse) { 220 | assert.ok(inUse === false); 221 | done(); 222 | }, function(err) { 223 | done(err); 224 | }); 225 | }); 226 | 227 | 228 | it('should return false for an unused port and default host', function(done) { 229 | tcpPortUsed.check(44201) 230 | .then(function(inUse) { 231 | assert.ok(inUse === false); 232 | done(); 233 | }, function(err) { 234 | done(err); 235 | }); 236 | }); 237 | 238 | it('should return false for an unused port and given default host using arg object', function(done) { 239 | tcpPortUsed.check({port: 44201, host: '127.0.0.1'}) 240 | .then(function(inUse) { 241 | assert.ok(inUse === false); 242 | done(); 243 | }, function(err) { 244 | done(err); 245 | }); 246 | }); 247 | 248 | it('should return false for an unused port and given default host', function(done) { 249 | tcpPortUsed.check(44201, '127.0.0.1') 250 | .then(function(inUse) { 251 | assert.ok(inUse === false); 252 | done(); 253 | }, function(err) { 254 | done(err); 255 | }); 256 | }); 257 | 258 | after(function(cb) { 259 | freePort(function(err) { 260 | cb(err); 261 | }); 262 | }); 263 | }); 264 | 265 | describe('waitUntilFreeOnHost', function() { 266 | this.slow(3000); 267 | this.timeout(3000); 268 | 269 | before(function(cb) { 270 | bindPort(44203, function(err) { 271 | cb(err); 272 | }); 273 | }); 274 | 275 | it('should reject promise for used port number after timeout using an arg obj', function(done) { 276 | tcpPortUsed.waitUntilFreeOnHost({port:44203, host:'127.0.0.1', retryTimeMs:500, timeOutMs:1000}) 277 | .then(function() { 278 | done(new Error('waitUntilFreeOnHost unexpectedly succeeded')); 279 | }, function(err) { 280 | if (err.message === 'timeout') { 281 | done(); 282 | } else { 283 | done(err); 284 | } 285 | }); 286 | }); 287 | 288 | it('should reject promise for used port number after timeout', function(done) { 289 | tcpPortUsed.waitUntilFreeOnHost(44203, '127.0.0.1', 500, 1000) 290 | .then(function() { 291 | done(new Error('waitUntilFreeOnHost unexpectedly succeeded')); 292 | }, function(err) { 293 | if (err.message === 'timeout') { 294 | done(); 295 | } else { 296 | done(err); 297 | } 298 | }); 299 | }); 300 | 301 | it('should fufill promise for free port number using an arg object', function(done) { 302 | tcpPortUsed.waitUntilFreeOnHost({port:44205, host:'127.0.0.1', retryTimeMs:500, timeOutM:4000}) 303 | .then(function() { 304 | done(); 305 | }, function(err) { 306 | done(err); 307 | }); 308 | }); 309 | 310 | 311 | it('should fufill promise for free port number', function(done) { 312 | tcpPortUsed.waitUntilFreeOnHost(44205, '127.0.0.1', 500, 4000) 313 | .then(function() { 314 | done(); 315 | }, function(err) { 316 | done(err); 317 | }); 318 | }); 319 | 320 | it('should fufill promise for free port number and default retry and timeout using an arg obj', function(done) { 321 | tcpPortUsed.waitUntilFreeOnHost({port:44205}) 322 | .then(function() { 323 | done(); 324 | }, function(err) { 325 | done(err); 326 | }); 327 | }); 328 | 329 | 330 | it('should fufill promise for free port number and default retry and timeout', function(done) { 331 | tcpPortUsed.waitUntilFreeOnHost(44205) 332 | .then(function() { 333 | done(); 334 | }, function(err) { 335 | done(err); 336 | }); 337 | }); 338 | 339 | it('should reject promise for invalid port number using an arg obj', function(done) { 340 | tcpPortUsed.waitUntilFreeOnHost({}) 341 | .then(function() { 342 | done(new Error('waitUntilFreeOnHost unexpectedly succeeded')); 343 | }, function(err) { 344 | if (err.message === 'invalid port: undefined') { 345 | done(); 346 | } else { 347 | done(err); 348 | } 349 | }); 350 | }); 351 | 352 | it('should reject promise for invalid port number', function(done) { 353 | tcpPortUsed.waitUntilFreeOnHost() 354 | .then(function() { 355 | done(new Error('waitUntilFreeOnHost unexpectedly succeeded')); 356 | }, function(err) { 357 | if (err.message === 'invalid port: undefined') { 358 | done(); 359 | } else { 360 | done(err); 361 | } 362 | }); 363 | }); 364 | 365 | after(function(cb) { 366 | freePort(function(err) { 367 | cb(err); 368 | }); 369 | }); 370 | }); 371 | 372 | describe('waitUntilUsedOnHost', function() { 373 | this.timeout(5000); 374 | this.slow(5000); 375 | 376 | before(function() { 377 | setTimeout(function() { 378 | bindPort(44204); 379 | }, 2000); 380 | }); 381 | 382 | it('should wait until the port is listening using an arg object', function(done) { 383 | tcpPortUsed.waitUntilUsedOnHost({port:44204, host:'127.0.0.1', retryTimeMs:500, timeOutMs:4000}) 384 | .then(function() { 385 | done(); 386 | }, function(err) { 387 | done(err); 388 | }); 389 | }); 390 | 391 | it('should wait until the port is listening', function(done) { 392 | tcpPortUsed.waitUntilUsedOnHost(44204, '127.0.0.1', 500, 4000) 393 | .then(function() { 394 | done(); 395 | }, function(err) { 396 | done(err); 397 | }); 398 | }); 399 | 400 | it('should reject promise when given an invalid port using an arg object', function(done) { 401 | tcpPortUsed.waitUntilUsedOnHost({port:'hello', host:'127.0.0.1', retryTimeMs:500, timeOutMs:2000}) 402 | .then(function() { 403 | done(new Error('waitUntil used unexpectedly successful.')); 404 | }, function(err) { 405 | if (err.message === 'invalid port: \'hello\'') { 406 | done(); 407 | } else { 408 | done(err); 409 | } 410 | }); 411 | }); 412 | 413 | it('should reject promise when given an invalid port', function(done) { 414 | tcpPortUsed.waitUntilUsedOnHost('hello', '127.0.0.1', 500, 2000) 415 | .then(function() { 416 | done(new Error('waitUntil used unexpectedly successful.')); 417 | }, function(err) { 418 | if (err.message === 'invalid port: \'hello\'') { 419 | done(); 420 | } else { 421 | done(err); 422 | } 423 | }); 424 | }); 425 | 426 | it('should timeout when no port is listening using an arg obj', function(done) { 427 | tcpPortUsed.waitUntilUsedOnHost({port:44205, host:'127.0.0.1', retryTimeMs:500, tmieOutMs:2000}) 428 | .then(function() { 429 | done(new Error('waitUntil used unexpectedly successful.')); 430 | }, function(err) { 431 | if (err.message === 'timeout') { 432 | done(); 433 | } else { 434 | done(err); 435 | } 436 | }); 437 | }); 438 | 439 | 440 | it('should timeout when no port is listening', function(done) { 441 | tcpPortUsed.waitUntilUsedOnHost(44205, '127.0.0.1', 500, 2000) 442 | .then(function() { 443 | done(new Error('waitUntil used unexpectedly successful.')); 444 | }, function(err) { 445 | if (err.message === 'timeout') { 446 | done(); 447 | } else { 448 | done(err); 449 | } 450 | }); 451 | }); 452 | 453 | after(function(cb) { 454 | freePort(function(err) { 455 | cb(err); 456 | }); 457 | }); 458 | }); 459 | 460 | describe('waitUntilFree', function() { 461 | this.timeout(8000); 462 | this.slow(8000); 463 | 464 | before(function(cb) { 465 | bindPort(44203, function(err) { 466 | cb(err); 467 | }); 468 | }); 469 | 470 | it('should reject promise for used port number after timeout using arg obj', function(done) { 471 | this.slow(18000); 472 | tcpPortUsed.waitUntilFree({port:44203, retryTimeMs:500, timeOutMs:4000}) 473 | .then(function() { 474 | done(new Error('waitUntilFree unexpectedly succeeded')); 475 | }, function(err) { 476 | if (err.message === 'timeout') { 477 | done(); 478 | } else { 479 | done(err); 480 | } 481 | }); 482 | }); 483 | 484 | it('should reject promise for used port number after timeout', function(done) { 485 | this.slow(18000); 486 | tcpPortUsed.waitUntilFree(44203, 500, 4000) 487 | .then(function() { 488 | done(new Error('waitUntilFree unexpectedly succeeded')); 489 | }, function(err) { 490 | if (err.message === 'timeout') { 491 | done(); 492 | } else { 493 | done(err); 494 | } 495 | }); 496 | }); 497 | 498 | it('should fufill promise for free port number using arg object', function(done) { 499 | tcpPortUsed.waitUntilFree({port:44205, retryTimeMs:500, timeOutMs:4000}) 500 | .then(function() { 501 | done(); 502 | }, function(err) { 503 | done(err); 504 | }); 505 | }); 506 | 507 | it('should fufill promise for free port number', function(done) { 508 | tcpPortUsed.waitUntilFree(44205, 500, 4000) 509 | .then(function() { 510 | done(); 511 | }, function(err) { 512 | done(err); 513 | }); 514 | }); 515 | 516 | it('should fufill promise for free port number and default retry and timeout using arg object', function(done) { 517 | tcpPortUsed.waitUntilFree({port: 44205}) 518 | .then(function() { 519 | done(); 520 | }, function(err) { 521 | done(err); 522 | }); 523 | }); 524 | 525 | it('should fufill promise for free port number and default retry and timeout', function(done) { 526 | tcpPortUsed.waitUntilFree(44205) 527 | .then(function() { 528 | done(); 529 | }, function(err) { 530 | done(err); 531 | }); 532 | }); 533 | 534 | it('should reject promise for invalid port number using arg object', function(done) { 535 | tcpPortUsed.waitUntilFree({}) 536 | .then(function() { 537 | done(new Error('waitUntilFreeOnHost: unexpectedly succeeded')); 538 | }, function(err) { 539 | if (err.message === 'invalid port: undefined') { 540 | done(); 541 | } else { 542 | done(err); 543 | } 544 | }); 545 | }); 546 | 547 | it('should reject promise for invalid port number', function(done) { 548 | tcpPortUsed.waitUntilFree() 549 | .then(function() { 550 | done(new Error('waitUntilFreeOnHost: unexpectedly succeeded')); 551 | }, function(err) { 552 | if (err.message === 'invalid port: undefined') { 553 | done(); 554 | } else { 555 | done(err); 556 | } 557 | }); 558 | }); 559 | 560 | after(function(cb) { 561 | freePort(function(err) { 562 | cb(err); 563 | }); 564 | }); 565 | }); 566 | 567 | describe('waitUntilUsed', function() { 568 | this.timeout(5000); 569 | this.slow(5000); 570 | 571 | before(function() { 572 | setTimeout(function() { 573 | bindPort(44204); 574 | }, 2000); 575 | }); 576 | 577 | it('should wait until the port is listening using arg obj', function(done) { 578 | tcpPortUsed.waitUntilUsed({port:44204, retryTimeMs:500, timeOutMs:4000}) 579 | .then(function() { 580 | done(); 581 | }, function(err) { 582 | done(err); 583 | }); 584 | }); 585 | 586 | it('should wait until the port is listening', function(done) { 587 | tcpPortUsed.waitUntilUsed(44204, 500, 4000) 588 | .then(function() { 589 | done(); 590 | }, function(err) { 591 | done(err); 592 | }); 593 | }); 594 | 595 | it('should reject promise when given an invalid port using arg object', function(done) { 596 | tcpPortUsed.waitUntilUsed({port:'hello', retryTimeMs:500, timeOutMs:2000}) 597 | .then(function() { 598 | done(new Error('waitUntil used unexpectedly successful.')); 599 | }, function(err) { 600 | if (err.message === 'invalid port: \'hello\'') { 601 | done(); 602 | } else { 603 | done(err); 604 | } 605 | }); 606 | }); 607 | 608 | it('should reject promise when given an invalid port', function(done) { 609 | tcpPortUsed.waitUntilUsed('hello', 500, 2000) 610 | .then(function() { 611 | done(new Error('waitUntil used unexpectedly successful.')); 612 | }, function(err) { 613 | if (err.message === 'invalid port: \'hello\'') { 614 | done(); 615 | } else { 616 | done(err); 617 | } 618 | }); 619 | }); 620 | 621 | it('should timeout when no port is listening using arg obj', function(done) { 622 | tcpPortUsed.waitUntilUsed({port:44205, retryTimeMs:500, timeOutMs:2000}) 623 | .then(function() { 624 | done(new Error('waitUntil used unexpectedly successful.')); 625 | }, function(err) { 626 | if (err.message === 'timeout') { 627 | done(); 628 | } else { 629 | done(err); 630 | } 631 | }); 632 | }); 633 | 634 | it('should timeout when no port is listening', function(done) { 635 | tcpPortUsed.waitUntilUsed(44205, 500, 2000) 636 | .then(function() { 637 | done(new Error('waitUntil used unexpectedly successful.')); 638 | }, function(err) { 639 | if (err.message === 'timeout') { 640 | done(); 641 | } else { 642 | done(err); 643 | } 644 | }); 645 | }); 646 | 647 | after(function(cb) { 648 | freePort(function(err) { 649 | cb(err); 650 | }); 651 | }); 652 | }); 653 | 654 | describe('waitForStatus', function() { 655 | this.timeout(5000); 656 | this.slow(5000); 657 | 658 | before(function() { 659 | setTimeout(function() { 660 | bindPort(44204); 661 | }, 2000); 662 | }); 663 | 664 | it('should wait until the port is listening using arg obj', function(done) { 665 | tcpPortUsed.waitForStatus({port:44204, host:'127.0.0.1', inUse:true, retryTimeMs:500, timeOutMs:4000}) 666 | .then(function() { 667 | done(); 668 | }, function(err) { 669 | done(err); 670 | }); 671 | }); 672 | 673 | it('should wait until the port is listening', function(done) { 674 | tcpPortUsed.waitForStatus(44204, '127.0.0.1', true, 500, 4000) 675 | .then(function() { 676 | done(); 677 | }, function(err) { 678 | done(err); 679 | }); 680 | }); 681 | 682 | it('should reject promise when given an invalid port using arg object', function(done) { 683 | tcpPortUsed.waitForStatus({port:'hello', host:'127.0.0.1', inUse:false, retryTimeMs:500, timeOutMs:2000}) 684 | .then(function() { 685 | done(new Error('waitUntil used unexpectedly successful.')); 686 | }, function(err) { 687 | if (err.message === 'invalid port: \'hello\'') { 688 | done(); 689 | } else { 690 | done(err); 691 | } 692 | }); 693 | }); 694 | 695 | it('should reject promise when given an invalid port', function(done) { 696 | tcpPortUsed.waitForStatus('hello', '127.0.0.1', false, 500, 2000) 697 | .then(function() { 698 | done(new Error('waitUntil used unexpectedly successful.')); 699 | }, function(err) { 700 | if (err.message === 'invalid port: \'hello\'') { 701 | done(); 702 | } else { 703 | done(err); 704 | } 705 | }); 706 | }); 707 | 708 | it('should timeout when no port is listening using arg obj', function(done) { 709 | tcpPortUsed.waitUntilUsed({port:44205, host:'127.0.0.1', inUse:true, retryTimeMs:500, timeOutMs:2000}) 710 | .then(function() { 711 | done(new Error('waitUntil used unexpectedly successful.')); 712 | }, function(err) { 713 | if (err.message === 'timeout') { 714 | done(); 715 | } else { 716 | done(err); 717 | } 718 | }); 719 | }); 720 | 721 | it('should timeout when no port is listening', function(done) { 722 | tcpPortUsed.waitUntilUsed(44205, '127.0.0.1', true, 500, 2000) 723 | .then(function() { 724 | done(new Error('waitUntil used unexpectedly successful.')); 725 | }, function(err) { 726 | if (err.message === 'timeout') { 727 | done(); 728 | } else { 729 | done(err); 730 | } 731 | }); 732 | }); 733 | 734 | after(function(cb) { 735 | freePort(function(err) { 736 | cb(err); 737 | }); 738 | }); 739 | }); 740 | 741 | --------------------------------------------------------------------------------