From 38b2bd75fb6740cf0e8291951729b2a2e6ac9bd5 Mon Sep 17 00:00:00 2001 From: leibale Date: Wed, 12 May 2021 18:27:35 -0400 Subject: [PATCH] spawn redis-servers for tests, add some tests, fix client auth on connect --- lib/client.spec.ts | 31 ++- lib/client.ts | 8 +- lib/cluster-slots.ts | 4 +- lib/commands-queue.ts | 4 +- lib/commands/AUTH.ts | 2 +- lib/commands/CLUSTER_NODES.spec.ts | 2 +- lib/commands/CLUSTER_NODES.ts | 4 +- lib/commands/COPY.spec.ts | 4 +- lib/commands/DECR.spec.ts | 4 +- lib/commands/DECRBY.spec.ts | 4 +- lib/commands/DEL.spec.ts | 4 +- lib/commands/DUMP.spec.ts | 4 +- lib/commands/KEYS.spec.ts | 4 +- lib/commands/PING.spec.ts | 4 +- lib/commands/SET.spec.ts | 6 +- lib/multi-command.ts | 2 +- lib/socket.ts | 2 +- lib/test-utils.ts | 69 ++++- package-lock.json | 401 ++++++++--------------------- package.json | 2 + 20 files changed, 220 insertions(+), 345 deletions(-) diff --git a/lib/client.spec.ts b/lib/client.spec.ts index f12737ced9..c129f46c01 100644 --- a/lib/client.spec.ts +++ b/lib/client.spec.ts @@ -1,23 +1,32 @@ import { strict as assert } from 'assert'; +import { TestRedisServers, TEST_REDIS_SERVERS, itWithClient } from './test-utils.js'; import RedisClient from './client.js'; describe('Client', () => { - describe.skip('authentication', () => { - it('Should fire auth command', async () => { - const client = RedisClient.create({ - socket: { - password: 'password' - } - }); - - await client.connect(); - + describe('authentication', () => { + itWithClient(TestRedisServers.PASSWORD, 'Client should be authenticated', async client => { assert.equal( await client.ping(), 'PONG' ); + }); - await client.disconnect(); + it('should not retry connecting if failed due to wrong auth', async () => { + const client = RedisClient.create({ + socket: { + ...TEST_REDIS_SERVERS[TestRedisServers.PASSWORD], + password: 'wrongpassword' + } + }); + + await assert.rejects( + () => client.connect(), + { + message: 'WRONGPASS invalid username-password pair or user is disabled.' + } + ); + + // TODO validate state }); }); diff --git a/lib/client.ts b/lib/client.ts index 8e601601fd..d91c4de5b8 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -13,11 +13,11 @@ export interface RedisClientOptions { export type RedisCommandSignature = (...args: Parameters) => Promise>; type WithCommands = { - [P in keyof typeof COMMANDS]: RedisCommandSignature<(typeof COMMANDS)[P]> + [P in keyof typeof COMMANDS]: RedisCommandSignature<(typeof COMMANDS)[P]>; }; type WithModules> = { - [P in keyof M[number]]: RedisCommandSignature + [P in keyof M[number]]: RedisCommandSignature; }; type WithMulti> = { @@ -55,7 +55,7 @@ export default class RedisClient extends EventEmitter { #initiateSocket(socketOptions?: RedisSocketOptions): RedisSocket { const socketInitiator = async (): Promise => { if (socketOptions?.password) { - await (this as any).auth(socketOptions.username, socketOptions.password); + await (this as any).auth(socketOptions); } }; @@ -71,7 +71,7 @@ export default class RedisClient extends EventEmitter { #initiateMulti() { const executor = async (commands: Array): Promise> => { const promise = Promise.all( - commands.map(({ encodedCommand }) => { + commands.map(({encodedCommand}) => { return this.#queue.addEncodedCommand(encodedCommand); }) ); diff --git a/lib/cluster-slots.ts b/lib/cluster-slots.ts index 96ef51dfe0..f4f6515c39 100644 --- a/lib/cluster-slots.ts +++ b/lib/cluster-slots.ts @@ -45,7 +45,7 @@ export default class RedisClusterSlots { // Override this.#slots and add not existing clients to this.#clientByKey const promises = [], clientsInUse = new Set(); - for (const { url, slots } of nodes) { + for (const {url, slots} of nodes) { clientsInUse.add(url); let client = this.#clientByKey.get(url); @@ -87,7 +87,7 @@ export default class RedisClusterSlots { this.#randomClientIterator = this.#clientByKey.values(); } - const { done, value } = this.#randomClientIterator.next(); + const {done, value} = this.#randomClientIterator.next(); if (done) { this.#randomClientIterator = undefined; return this.#getRandomClient(); diff --git a/lib/commands-queue.ts b/lib/commands-queue.ts index f66bec18be..2804f04f5c 100644 --- a/lib/commands-queue.ts +++ b/lib/commands-queue.ts @@ -79,7 +79,7 @@ export default class RedisCommandsQueue { options.signal.addEventListener('abort', () => { this.#waitingToBeSent.removeNode(node); node.value.reject(new Error('The command was aborted')); - }, { once: true }); + }, {once: true}); } if (options?.asap) { @@ -96,7 +96,7 @@ export default class RedisCommandsQueue { const encoded: Array = []; let size = 0; let lastCommandChainId: Symbol | undefined; - for (const { encodedCommand, chainId } of this.#waitingToBeSent) { + for (const {encodedCommand, chainId} of this.#waitingToBeSent) { encoded.push(encodedCommand); size += encodedCommand.length; if (size > recommendedSize) { diff --git a/lib/commands/AUTH.ts b/lib/commands/AUTH.ts index 579bdff144..eb9e27ae15 100644 --- a/lib/commands/AUTH.ts +++ b/lib/commands/AUTH.ts @@ -5,7 +5,7 @@ export interface AuthOptions { password: string; } -export function transformArguments({ username, password }: AuthOptions): Array { +export function transformArguments({username, password}: AuthOptions): Array { if (!username) { return ['AUTH', password]; } diff --git a/lib/commands/CLUSTER_NODES.spec.ts b/lib/commands/CLUSTER_NODES.spec.ts index 6af6119327..ef2c267d9c 100644 --- a/lib/commands/CLUSTER_NODES.spec.ts +++ b/lib/commands/CLUSTER_NODES.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import {RedisClusterNodeLinkStates, transformArguments, transformReply} from './CLUSTER_NODES.js'; +import { RedisClusterNodeLinkStates, transformArguments, transformReply } from './CLUSTER_NODES.js'; describe('CLUSTER NODES', () => { it('transformArguments', () => { diff --git a/lib/commands/CLUSTER_NODES.ts b/lib/commands/CLUSTER_NODES.ts index 3feab4d83a..4902523de3 100644 --- a/lib/commands/CLUSTER_NODES.ts +++ b/lib/commands/CLUSTER_NODES.ts @@ -26,7 +26,7 @@ export function transformReply(reply: string): Array { const lines = reply.split('\n'); lines.pop(); // last line is empty return lines.map(line => { - const [ id, url, flags, master, pingSent, pongRecv, configEpoch, linkState, ...slots ] = line.split(' '); + const [id, url, flags, master, pingSent, pongRecv, configEpoch, linkState, ...slots] = line.split(' '); return { id, url, @@ -38,7 +38,7 @@ export function transformReply(reply: string): Array { linkState: (linkState as RedisClusterNodeLinkStates), slots: slots.map(slot => { // TODO: importing & exporting (https://redis.io/commands/cluster-nodes#special-slot-entries) - const [ fromString, toString ] = slot.split('-', 2), + const [fromString, toString] = slot.split('-', 2), from = Number(fromString); return { from, diff --git a/lib/commands/COPY.spec.ts b/lib/commands/COPY.spec.ts index 01bb54f1c8..bc0567d366 100644 --- a/lib/commands/COPY.spec.ts +++ b/lib/commands/COPY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; import { transformArguments, transformReply } from './COPY.js'; describe('COPY', () => { @@ -56,7 +56,7 @@ describe('COPY', () => { }); }); - itWithClient('client.copy', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.copy', async client => { assert.equal( await client.copy('source', 'destination'), false diff --git a/lib/commands/DECR.spec.ts b/lib/commands/DECR.spec.ts index 8b19235934..a9eae76f5f 100644 --- a/lib/commands/DECR.spec.ts +++ b/lib/commands/DECR.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; import { transformArguments } from './DECR.js'; describe('DECR', () => { @@ -10,7 +10,7 @@ describe('DECR', () => { ); }); - itWithClient('client.decr', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.decr', async client => { assert.equal( await client.decr('key'), -1 diff --git a/lib/commands/DECRBY.spec.ts b/lib/commands/DECRBY.spec.ts index ca6d160530..c8bde40f46 100644 --- a/lib/commands/DECRBY.spec.ts +++ b/lib/commands/DECRBY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; import { transformArguments } from './DECRBY.js'; describe('DECRBY', () => { @@ -10,7 +10,7 @@ describe('DECRBY', () => { ); }); - itWithClient('client.decrBy', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.decrBy', async client => { assert.equal( await client.decrBy('key', 2), -2 diff --git a/lib/commands/DEL.spec.ts b/lib/commands/DEL.spec.ts index e2e7bcfc87..6533e9c25e 100644 --- a/lib/commands/DEL.spec.ts +++ b/lib/commands/DEL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; import { transformArguments } from './DEL.js'; describe('DEL', () => { @@ -12,7 +12,7 @@ describe('DEL', () => { }); }); - itWithClient('client.del', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.del', async client => { assert.equal( await client.del('key1', 'key2'), 0 diff --git a/lib/commands/DUMP.spec.ts b/lib/commands/DUMP.spec.ts index 16085a9c52..397e404f45 100644 --- a/lib/commands/DUMP.spec.ts +++ b/lib/commands/DUMP.spec.ts @@ -1,8 +1,8 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; describe('DUMP', () => { - itWithClient('client.dump', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.dump', async client => { assert.equal( await client.dump('key'), null diff --git a/lib/commands/KEYS.spec.ts b/lib/commands/KEYS.spec.ts index 29f4290da8..0335e03a0d 100644 --- a/lib/commands/KEYS.spec.ts +++ b/lib/commands/KEYS.spec.ts @@ -1,8 +1,8 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; describe('KEYS', () => { - itWithClient('client.keys', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.keys', async client => { assert.deepEqual( await client.keys('pattern'), [] diff --git a/lib/commands/PING.spec.ts b/lib/commands/PING.spec.ts index 7b342f7c22..58d983ee16 100644 --- a/lib/commands/PING.spec.ts +++ b/lib/commands/PING.spec.ts @@ -1,8 +1,8 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; describe('PING', () => { - itWithClient('client.ping', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'client.ping', async client => { assert.equal( await client.ping(), 'PONG' diff --git a/lib/commands/SET.spec.ts b/lib/commands/SET.spec.ts index 59f158796d..bb364acd57 100644 --- a/lib/commands/SET.spec.ts +++ b/lib/commands/SET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient } from '../test-utils.js'; +import { TestRedisServers, itWithClient } from '../test-utils.js'; import { transformArguments } from './SET.js'; describe('SET', () => { @@ -100,14 +100,14 @@ describe('SET', () => { }); describe('client.set', () => { - itWithClient('simple', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'simple', async client => { assert.equal( await client.set('key', 'value'), 'OK' ); }); - itWithClient('with GET on empty key', {}, async client => { + itWithClient(TestRedisServers.OPEN, 'with GET on empty key', async client => { assert.equal( await client.set('key', 'value', { GET: true diff --git a/lib/multi-command.ts b/lib/multi-command.ts index 9f3061e984..b168524e37 100644 --- a/lib/multi-command.ts +++ b/lib/multi-command.ts @@ -62,7 +62,7 @@ export default class RedisMultiCommand { async exec(): Promise> { const results = await this.#executor(this.#queue, Symbol('[RedisMultiCommand] Chain ID')); - return this.#queue.map(({ transformReply }, i) => { + return this.#queue.map(({transformReply}, i) => { const reply = results[i]; return transformReply ? transformReply(reply) : reply; }); diff --git a/lib/socket.ts b/lib/socket.ts index 518a250b63..8df7d1f097 100644 --- a/lib/socket.ts +++ b/lib/socket.ts @@ -123,7 +123,7 @@ export default class RedisSocket extends EventEmitter { #createSocket(): Promise { return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? + const {connectEvent, socket} = RedisSocket.#isTlsSocket(this.#options) ? this.#createTlsSocket() : this.#createNetSocket(); diff --git a/lib/test-utils.ts b/lib/test-utils.ts index ba387a8699..6b4740c551 100644 --- a/lib/test-utils.ts +++ b/lib/test-utils.ts @@ -1,16 +1,75 @@ import RedisClient, { RedisClientOptions, RedisClientType } from './client.js'; import { RedisModules } from './commands/index.js'; +import { spawn } from 'child_process'; +import { once } from 'events'; +import tcpPortUsed from 'tcp-port-used'; +import { RedisSocketOptions } from './socket.js'; -export function itWithClient(title: string, options: RedisClientOptions, fn: (client: RedisClientType) => Promise) { +export enum TestRedisServers { + OPEN, + PASSWORD +} + +export const TEST_REDIS_SERVERS: Partial> = {}; + +before(() => { + return Promise.all([ + spawnOpenServer(), + spawnPasswordServer() + ]); +}); + +async function spawnOpenServer(): Promise { + TEST_REDIS_SERVERS[TestRedisServers.OPEN] = { + port: await spawnRedisServer() + }; +} + +async function spawnPasswordServer(): Promise { + TEST_REDIS_SERVERS[TestRedisServers.PASSWORD] = { + port: await spawnRedisServer(['--requirepass', 'password']), + username: 'default', + password: 'password' + }; +} + +export function itWithClient(type: TestRedisServers, title: string, fn: (client: RedisClientType) => Promise) { it(title, async () => { - const client = RedisClient.create(options); + const client = RedisClient.create({ + socket: TEST_REDIS_SERVERS[type] + }); + await client.connect(); try { - await client.connect(); - await client.flushAll(); await fn(client); } finally { + await client.flushAll(); await client.disconnect(); } }); -} \ No newline at end of file +} + +let port = 6379; + +async function spawnRedisServer(args?: Array): Promise { + const currentPort = port++, + process = spawn('redis-server', [ + '--save', + '', + '--port', + currentPort.toString(), + ...(args ?? []) + ]); + + // TODO: catch process exit + + await tcpPortUsed.waitForStatus(currentPort, '127.0.0.1', true, 10, 1000); + + after(() => { + process.kill(); + return once(process, 'close'); + }); + + return currentPort; +} + diff --git a/package-lock.json b/package-lock.json index 03f1219a7c..c40cbe11f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,12 @@ }, "devDependencies": { "@types/mocha": "^8.2.2", - "@types/node": "^15.0.1", - "@types/sinon": "^10.0.0", - "@types/yallist": "^3.0.1", - "mocha": "^8.3.2", + "@types/node": "^15.0.2", + "@types/tcp-port-used": "^1.0.0", + "@types/yallist": "^4.0.0", + "mocha": "^8.4.0", "nyc": "^15.1.0", - "sinon": "^10.0.0", + "tcp-port-used": "^1.0.2", "typescript": "^4.3.0-beta" }, "engines": { @@ -448,41 +448,6 @@ "node": ">=8" } }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz", - "integrity": "sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, "node_modules/@types/mocha": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", @@ -495,19 +460,16 @@ "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", "dev": true }, - "node_modules/@types/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-jDZ55oCKxqlDmoTBBbBBEx+N8ZraUVhggMZ9T5t+6/Dh8/4NiOjSUfpLrPiEwxQDlAe3wpAkoXhWvE6LibtsMQ==", - "dev": true, - "dependencies": { - "@sinonjs/fake-timers": "^7.0.4" - } + "node_modules/@types/tcp-port-used": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/tcp-port-used/-/tcp-port-used-1.0.0.tgz", + "integrity": "sha512-UbspV5WZNhfM55HyvLEFyVc5n6K6OKuKep0mzvsgoUXQU1FS42GbePjreBnTCoKXfNzK/3/RJVCRlUDTuszFPg==", + "dev": true }, "node_modules/@types/yallist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-3.0.1.tgz", - "integrity": "sha512-nky1uSaFye8rZctRgEd+hC0rNZuDDH49DwOHdSIvgiRZPERVvcEFfV3kUReE60GMFNjG1z8x9ncSb+WKj3cMcA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-NDr62wWXirlxRSnd3HhMu8dODy2gjs+I+KzAc8AN4W3uyCcTxnoBYOheBqGjyvkZVBCvh0F9bTcM4xHsHt10sA==", "dev": true }, "node_modules/@ungap/promise-all-settled": { @@ -911,6 +873,12 @@ "node": ">=0.10.0" } }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "node_modules/default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -1248,6 +1216,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1323,6 +1300,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -1332,11 +1315,19 @@ "node": ">=0.10.0" } }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "node_modules/is2": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz", + "integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } }, "node_modules/isexe": { "version": "2.0.0", @@ -1505,12 +1496,6 @@ "node": ">=6" } }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1532,12 +1517,6 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, "node_modules/log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -1645,28 +1624,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -1999,15 +1956,6 @@ "node": ">=8" } }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, "node_modules/picomatch": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", @@ -2244,54 +2192,6 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "node_modules/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2385,6 +2285,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -2420,15 +2330,6 @@ "node": ">=8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -3088,41 +2989,6 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz", - "integrity": "sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, "@types/mocha": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", @@ -3135,19 +3001,16 @@ "integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==", "dev": true }, - "@types/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-jDZ55oCKxqlDmoTBBbBBEx+N8ZraUVhggMZ9T5t+6/Dh8/4NiOjSUfpLrPiEwxQDlAe3wpAkoXhWvE6LibtsMQ==", - "dev": true, - "requires": { - "@sinonjs/fake-timers": "^7.0.4" - } + "@types/tcp-port-used": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/tcp-port-used/-/tcp-port-used-1.0.0.tgz", + "integrity": "sha512-UbspV5WZNhfM55HyvLEFyVc5n6K6OKuKep0mzvsgoUXQU1FS42GbePjreBnTCoKXfNzK/3/RJVCRlUDTuszFPg==", + "dev": true }, "@types/yallist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-3.0.1.tgz", - "integrity": "sha512-nky1uSaFye8rZctRgEd+hC0rNZuDDH49DwOHdSIvgiRZPERVvcEFfV3kUReE60GMFNjG1z8x9ncSb+WKj3cMcA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-NDr62wWXirlxRSnd3HhMu8dODy2gjs+I+KzAc8AN4W3uyCcTxnoBYOheBqGjyvkZVBCvh0F9bTcM4xHsHt10sA==", "dev": true }, "@ungap/promise-all-settled": { @@ -3461,6 +3324,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -3692,6 +3561,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3746,17 +3621,28 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "is2": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz", + "integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + } }, "isexe": { "version": "2.0.0", @@ -3887,12 +3773,6 @@ "minimist": "^1.2.5" } }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3908,12 +3788,6 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -3992,30 +3866,6 @@ "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", "dev": true }, - "nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -4272,15 +4122,6 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, "picomatch": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", @@ -4459,46 +4300,6 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4565,6 +4366,16 @@ "has-flag": "^4.0.0" } }, + "tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "requires": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4591,12 +4402,6 @@ "is-number": "^7.0.0" } }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", diff --git a/package.json b/package.json index 5f9021ce99..3fd87c74ba 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,11 @@ "devDependencies": { "@types/mocha": "^8.2.2", "@types/node": "^15.0.2", + "@types/tcp-port-used": "^1.0.0", "@types/yallist": "^4.0.0", "mocha": "^8.4.0", "nyc": "^15.1.0", + "tcp-port-used": "^1.0.2", "typescript": "^4.3.0-beta" }, "engines": {