From 88313bda940f1c3ce3faf04a05350a5f8bfb49f6 Mon Sep 17 00:00:00 2001 From: leibale Date: Thu, 1 Jul 2021 15:45:25 -0400 Subject: [PATCH] handle ASK errors, add some commands and tests --- lib/cluster-slots.ts | 104 ++-- lib/cluster.spec.ts | 68 ++- lib/cluster.ts | 40 +- lib/commands/ASKING.spec.ts | 11 + lib/commands/ASKING.ts | 7 + lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts | 11 + lib/commands/CLUSTER_GETKEYSINSLOT.ts | 7 + lib/commands/CLUSTER_RESET.spec.ts | 4 +- lib/commands/CLUSTER_SETSLOT.spec.ts | 20 + lib/commands/CLUSTER_SETSLOT.ts | 20 + lib/commands/MIGRATE.spec.ts | 76 +++ lib/commands/MIGRATE.ts | 65 +++ lib/commands/index.ts | 9 + lib/test-utils.ts | 131 +++-- package-lock.json | 537 ++++++++------------- package.json | 10 +- 16 files changed, 683 insertions(+), 437 deletions(-) create mode 100644 lib/commands/ASKING.spec.ts create mode 100644 lib/commands/ASKING.ts create mode 100644 lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts create mode 100644 lib/commands/CLUSTER_GETKEYSINSLOT.ts create mode 100644 lib/commands/CLUSTER_SETSLOT.spec.ts create mode 100644 lib/commands/CLUSTER_SETSLOT.ts create mode 100644 lib/commands/MIGRATE.spec.ts create mode 100644 lib/commands/MIGRATE.ts diff --git a/lib/cluster-slots.ts b/lib/cluster-slots.ts index 153faedd3e..3e255fc2a6 100644 --- a/lib/cluster-slots.ts +++ b/lib/cluster-slots.ts @@ -6,16 +6,21 @@ import { RedisClusterOptions } from './cluster'; import { RedisModules } from './commands'; import { RedisLuaScripts } from './lua-script'; -interface SlotClients { - master: RedisClientType; - replicas: Array>; - iterator: IterableIterator> | undefined; +export interface ClusterNode { + id: string; + client: RedisClientType; +} + +interface SlotNodes { + master: ClusterNode; + replicas: Array>; + clientIterator: IterableIterator> | undefined; } export default class RedisClusterSlots { readonly #options: RedisClusterOptions; - readonly #clientByKey = new Map>(); - readonly #slots: Array> = []; + readonly #nodeByUrl = new Map>(); + readonly #slots: Array> = []; constructor(options: RedisClusterOptions) { this.#options = options; @@ -27,6 +32,7 @@ export default class RedisClusterSlots this.#initiateClientForNode(replica, true, clientsInUse, promises)) : [], - iterator: undefined // will be initiated in use + clientIterator: undefined // will be initiated in use }; for (const { from, to } of master.slots) { @@ -91,73 +99,77 @@ export default class RedisClusterSlots, promises: Array>): RedisClientType { - clientsInUse.add(node.url); + #initiateClientForNode(nodeData: RedisClusterMasterNode | RedisClusterReplicaNode, readonly: boolean, clientsInUse: Set, promises: Array>): ClusterNode { + const url = `${nodeData.host}:${nodeData.port}`; + clientsInUse.add(url); - let client = this.#clientByKey.get(node.url); - if (!client) { - client = RedisClient.create({ - socket: { - host: node.host, - port: node.port - }, - readonly - }); - promises.push(client.connect()); - this.#clientByKey.set(node.url, client); + let node = this.#nodeByUrl.get(url); + if (!node) { + node = { + id: nodeData.id, + client: RedisClient.create({ + socket: { + host: nodeData.host, + port: nodeData.port + }, + readonly + }) + }; + promises.push(node.client.connect()); + this.#nodeByUrl.set(url, node); } - return client; + return node; } - #getSlotMaster(slot: number): RedisClientType { + getSlotMaster(slot: number): ClusterNode { return this.#slots[slot].master; } - *#slotIterator(slotNumber: number): IterableIterator> { + *#slotClientIterator(slotNumber: number): IterableIterator> { const slot = this.#slots[slotNumber]; - yield slot.master; + yield slot.master.client; for (const replica of slot.replicas) { - yield replica; + yield replica.client; } } #getSlotClient(slotNumber: number): RedisClientType { const slot = this.#slots[slotNumber]; - if (!slot.iterator) { - slot.iterator = this.#slotIterator(slotNumber); + if (!slot.clientIterator) { + slot.clientIterator = this.#slotClientIterator(slotNumber); } - const {done, value} = slot.iterator.next(); + const {done, value} = slot.clientIterator.next(); if (done) { - slot.iterator = undefined; + slot.clientIterator = undefined; return this.#getSlotClient(slotNumber); } return value; } - #randomClientIterator?: IterableIterator>; + #randomClientIterator?: IterableIterator>; #getRandomClient(): RedisClientType { - if (!this.#clientByKey.size) { + if (!this.#nodeByUrl.size) { throw new Error('Cluster is not connected'); } if (!this.#randomClientIterator) { - this.#randomClientIterator = this.#clientByKey.values(); + this.#randomClientIterator = this.#nodeByUrl.values(); } const {done, value} = this.#randomClientIterator.next(); @@ -166,7 +178,7 @@ export default class RedisClusterSlots { @@ -176,30 +188,34 @@ export default class RedisClusterSlots> { + getMasters(): Array> { const masters = []; - for (const client of this.#clientByKey.values()) { - if (client.options?.readonly) continue; + for (const node of this.#nodeByUrl.values()) { + if (node.client.options?.readonly) continue; - masters.push(client); + masters.push(node); } return masters; } + getNodeByUrl(url: string): ClusterNode | undefined { + return this.#nodeByUrl.get(url); + } + async disconnect(): Promise { await Promise.all( - [...this.#clientByKey.values()].map(client => client.disconnect()) + [...this.#nodeByUrl.values()].map(({ client }) => client.disconnect()) ); - this.#clientByKey.clear(); + this.#nodeByUrl.clear(); this.#slots.splice(0); } } diff --git a/lib/cluster.spec.ts b/lib/cluster.spec.ts index 5f99b52f7d..1a7c307822 100644 --- a/lib/cluster.spec.ts +++ b/lib/cluster.spec.ts @@ -1,7 +1,9 @@ import { strict as assert } from 'assert'; import RedisCluster from './cluster'; import { defineScript } from './lua-script'; -import { TestRedisClusters, TEST_REDIS_CLUSTERES } from './test-utils'; +import { itWithDedicatedCluster, TestRedisClusters, TEST_REDIS_CLUSTERES } from './test-utils'; +import calculateSlot from 'cluster-key-slot'; +import { ClusterSlotStates } from './commands/CLUSTER_SETSLOT'; describe('Cluster', () => { it('sendCommand', async () => { @@ -12,16 +14,18 @@ describe('Cluster', () => { await cluster.connect(); - await cluster.ping(); - await cluster.set('a', 'b'); - await cluster.set('a{a}', 'bb'); - await cluster.set('aa', 'bb'); - await cluster.get('aa'); - await cluster.get('aa'); - await cluster.get('aa'); - await cluster.get('aa'); - - await cluster.disconnect(); + try { + await cluster.ping(); + await cluster.set('a', 'b'); + await cluster.set('a{a}', 'bb'); + await cluster.set('aa', 'bb'); + await cluster.get('aa'); + await cluster.get('aa'); + await cluster.get('aa'); + await cluster.get('aa'); + } finally { + await cluster.disconnect(); + } }); it('scripts', async () => { @@ -54,4 +58,46 @@ describe('Cluster', () => { await cluster.disconnect(); } }); + + itWithDedicatedCluster('should handle live resharding', async cluster => { + const key = 'key', + value = 'value'; + await cluster.set(key, value); + + const slot = calculateSlot(key), + from = cluster.getSlotMaster(slot), + to = cluster.getMasters().find(node => node.id !== from.id); + + await to!.client.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, from.id); + + // should be able to get the key from the original node before it was migrated + assert.equal( + await cluster.get(key), + value + ); + + await from.client.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, to!.id); + + // should be able to get the key from the original node using the "ASKING" command + assert.equal( + await cluster.get(key), + value + ); + + const { port: toPort } = to!.client.options!.socket; + + await from.client.migrate( + '127.0.0.1', + toPort, + key, + 0, + 10 + ); + + // should be able to get the key from the new node + assert.equal( + await cluster.get(key), + value + ); + }); }); diff --git a/lib/cluster.ts b/lib/cluster.ts index 3ee303c019..c3e06e7539 100644 --- a/lib/cluster.ts +++ b/lib/cluster.ts @@ -1,10 +1,11 @@ import COMMANDS from './commands'; import { RedisCommand, RedisModules } from './commands'; -import { ClientCommandOptions, RedisClientType, WithPlugins } from './client'; +import RedisClient, { ClientCommandOptions, RedisClientType, WithPlugins } from './client'; import { RedisSocketOptions } from './socket'; -import RedisClusterSlots from './cluster-slots'; +import RedisClusterSlots, { ClusterNode } from './cluster-slots'; import { RedisLuaScript, RedisLuaScripts } from './lua-script'; import { commandOptions, CommandOptions, isCommandOptions } from './command-options'; +import { Console } from 'console'; export interface RedisClusterOptions { rootNodes: Array; @@ -105,8 +106,11 @@ export default class RedisCluster, redirections = 0): Promise { - if (redirections < (this.#options.maxCommandRedirections ?? 16)) { + async #handleCommandError(err: Error, client: RedisClientType, redirections: number): Promise> { + if (redirections > (this.#options.maxCommandRedirections ?? 16)) { throw err; } if (err.message.startsWith('ASK')) { - // TODO + const url = err.message.substring(err.message.lastIndexOf(' ') + 1); + let node = this.#slots.getNodeByUrl(url); + if (!node) { + await this.#slots.discover(client); + node = this.#slots.getNodeByUrl(url); + + if (!node) { + throw new Error(`Cannot find node ${url}`); + } + } + + await node.client.asking(); + return node.client; } else if (err.message.startsWith('MOVED')) { await this.#slots.discover(client); + return client; } throw err; } - getMasters(): Array> { + getMasters(): Array> { return this.#slots.getMasters(); } + getSlotMaster(slot: number): ClusterNode { + return this.#slots.getSlotMaster(slot); + } + disconnect(): Promise { return this.#slots.disconnect(); } diff --git a/lib/commands/ASKING.spec.ts b/lib/commands/ASKING.spec.ts new file mode 100644 index 0000000000..3da2015199 --- /dev/null +++ b/lib/commands/ASKING.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './ASKING'; + +describe('ASKING', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['ASKING'] + ); + }); +}); diff --git a/lib/commands/ASKING.ts b/lib/commands/ASKING.ts new file mode 100644 index 0000000000..3f836131ac --- /dev/null +++ b/lib/commands/ASKING.ts @@ -0,0 +1,7 @@ +import { transformReplyString } from './generic-transformers'; + +export function transformArguments(): Array { + return ['ASKING']; +} + +export const transformReply = transformReplyString; diff --git a/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts b/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts new file mode 100644 index 0000000000..bb20f7521d --- /dev/null +++ b/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './CLUSTER_GETKEYSINSLOT'; + +describe('CLUSTER GETKEYSINSLOT', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(0, 10), + ['CLUSTER', 'GETKEYSINSLOT', '0', '10'] + ); + }); +}); diff --git a/lib/commands/CLUSTER_GETKEYSINSLOT.ts b/lib/commands/CLUSTER_GETKEYSINSLOT.ts new file mode 100644 index 0000000000..c5719848cf --- /dev/null +++ b/lib/commands/CLUSTER_GETKEYSINSLOT.ts @@ -0,0 +1,7 @@ +import { transformReplyString } from './generic-transformers'; + +export function transformArguments(slot: number, count: number): Array { + return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()]; +} + +export const transformReply = transformReplyString; diff --git a/lib/commands/CLUSTER_RESET.spec.ts b/lib/commands/CLUSTER_RESET.spec.ts index 6e9c8958d8..c077e7f887 100644 --- a/lib/commands/CLUSTER_RESET.spec.ts +++ b/lib/commands/CLUSTER_RESET.spec.ts @@ -10,14 +10,14 @@ describe('CLUSTER RESET', () => { ); }); - it('simple', () => { + it('HARD', () => { assert.deepEqual( transformArguments('HARD'), ['CLUSTER', 'RESET', 'HARD'] ); }); - it('simple', () => { + it('SOFT', () => { assert.deepEqual( transformArguments('SOFT'), ['CLUSTER', 'RESET', 'SOFT'] diff --git a/lib/commands/CLUSTER_SETSLOT.spec.ts b/lib/commands/CLUSTER_SETSLOT.spec.ts new file mode 100644 index 0000000000..0f46aafd13 --- /dev/null +++ b/lib/commands/CLUSTER_SETSLOT.spec.ts @@ -0,0 +1,20 @@ +import { strict as assert } from 'assert'; +import { ClusterSlotStates, transformArguments } from './CLUSTER_SETSLOT'; + +describe('CLUSTER SETSLOT', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments(0, ClusterSlotStates.IMPORTING), + ['CLUSTER', 'SETSLOT', '0', 'IMPORTING'] + ); + }); + + it('with nodeId', () => { + assert.deepEqual( + transformArguments(0, ClusterSlotStates.IMPORTING, 'nodeId'), + ['CLUSTER', 'SETSLOT', '0', 'IMPORTING', 'nodeId'] + ); + }); + }); +}); diff --git a/lib/commands/CLUSTER_SETSLOT.ts b/lib/commands/CLUSTER_SETSLOT.ts new file mode 100644 index 0000000000..c665b34962 --- /dev/null +++ b/lib/commands/CLUSTER_SETSLOT.ts @@ -0,0 +1,20 @@ +import { transformReplyString } from './generic-transformers'; + +export enum ClusterSlotStates { + IMPORTING = 'IMPORTING', + MIGRATING = 'MIGRATING', + STABLE = 'STABLE', + NODE = 'NODE' +} + +export function transformArguments(slot: number, state: ClusterSlotStates, nodeId?: string): Array { + const args = ['CLUSTER', 'SETSLOT', slot.toString(), state]; + + if (nodeId) { + args.push(nodeId); + } + + return args; +} + +export const transformReply = transformReplyString; diff --git a/lib/commands/MIGRATE.spec.ts b/lib/commands/MIGRATE.spec.ts new file mode 100644 index 0000000000..eb233f2290 --- /dev/null +++ b/lib/commands/MIGRATE.spec.ts @@ -0,0 +1,76 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './MIGRATE'; + +describe('MIGRATE', () => { + describe('transformArguments', () => { + it('single key', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10'] + ); + }); + + it('multiple keys', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, ['1', '2'], 0, 10), + ['MIGRATE', '127.0.0.1', '6379', '""', '0', '10', 'KEYS', '1', '2'] + ); + }); + + it('with COPY', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + COPY: true + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY'] + ); + }); + + it('with REPLACE', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + REPLACE: true + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'REPLACE'] + ); + }); + + describe('with AUTH', () => { + it('password only', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + AUTH: { + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH', 'password'] + ); + }); + + it('username & password', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + AUTH: { + username: 'username', + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH2', 'username', 'password'] + ); + }); + }); + + it('with COPY, REPLACE, AUTH', () => { + assert.deepEqual( + transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + COPY: true, + REPLACE: true, + AUTH: { + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE', 'AUTH', 'password'] + ); + }); + }); +}); diff --git a/lib/commands/MIGRATE.ts b/lib/commands/MIGRATE.ts new file mode 100644 index 0000000000..1d2fc075ef --- /dev/null +++ b/lib/commands/MIGRATE.ts @@ -0,0 +1,65 @@ +import { AuthOptions } from './AUTH'; +import { transformReplyString } from './generic-transformers'; + +interface MigrateOptions { + COPY?: true; + REPLACE?: true; + AUTH?: AuthOptions; +} + +export function transformArguments( + host: string, + port: number, + key: string | Array, + destinationDb: number, + timeout: number, + options?: MigrateOptions +): Array { + const args = ['MIGRATE', host, port.toString()], + isKeyString = typeof key === 'string'; + + if (isKeyString) { + args.push(key as string); + } else { + args.push('""'); + } + + args.push( + destinationDb.toString(), + timeout.toString() + ); + + if (options?.COPY) { + args.push('COPY'); + } + + if (options?.REPLACE) { + args.push('REPLACE'); + } + + if (options?.AUTH) { + if (options.AUTH.username) { + args.push( + 'AUTH2', + options.AUTH.username, + options.AUTH.password + ); + } else { + args.push( + 'AUTH', + options.AUTH.password + ); + } + } + + if (!isKeyString) { + args.push( + 'KEYS', + ...key + ); + } + + return args; +} + +export const transformReply = transformReplyString; diff --git a/lib/commands/index.ts b/lib/commands/index.ts index 16f6476009..962261e3d6 100644 --- a/lib/commands/index.ts +++ b/lib/commands/index.ts @@ -1,4 +1,5 @@ import * as APPEND from './APPEND'; +import * as ASKING from './ASKING'; import * as AUTH from './AUTH'; import * as BITCOUNT from './BITCOUNT'; import * as BITFIELD from './BITFIELD'; @@ -15,6 +16,7 @@ import * as CLUSTER_INFO from './CLUSTER_INFO'; import * as CLUSTER_NODES from './CLUSTER_NODES'; import * as CLUSTER_MEET from './CLUSTER_MEET'; import * as CLUSTER_RESET from './CLUSTER_RESET'; +import * as CLUSTER_SETSLOT from './CLUSTER_SETSLOT'; import * as COPY from './COPY'; import * as DECR from './DECR'; import * as DECRBY from './DECRBY'; @@ -61,6 +63,7 @@ import * as LRANGE from './LRANGE'; import * as LREM from './LREM'; import * as LSET from './LSET'; import * as LTRIM from './LTRIM'; +import * as MIGRATE from './MIGRATE'; import * as MOVE from './MOVE'; import * as PERSIST from './PERSIST'; import * as PEXPIRE from './PEXPIRE'; @@ -167,6 +170,8 @@ import * as ZUNIONSTORE from './ZUNIONSTORE'; export default { APPEND, append: APPEND, + ASKING, + asking: ASKING, AUTH, auth: AUTH, BITCOUNT, @@ -199,6 +204,8 @@ export default { clusterMeet: CLUSTER_MEET, CLUSTER_RESET, clusterReset: CLUSTER_RESET, + CLUSTER_SETSLOT, + clusterSetSlot: CLUSTER_SETSLOT, COPY, copy: COPY, DECR, @@ -290,6 +297,8 @@ export default { lSet: LSET, LTRIM, lTrim: LTRIM, + MIGRATE, + migrate: MIGRATE, MOVE, move: MOVE, PERSIST, diff --git a/lib/test-utils.ts b/lib/test-utils.ts index b41c53ba46..9da6509ff7 100644 --- a/lib/test-utils.ts +++ b/lib/test-utils.ts @@ -4,7 +4,6 @@ import { RedisModules } from './commands'; import { RedisLuaScripts } from './lua-script'; import { spawn } from 'child_process'; import { once } from 'events'; -import tcpPortUsed from 'tcp-port-used'; import { RedisSocketOptions } from './socket'; import which from 'which'; import { SinonSpy } from 'sinon'; @@ -37,20 +36,20 @@ before(function () { async function spawnOpenServer(): Promise { TEST_REDIS_SERVERS[TestRedisServers.OPEN] = { - port: await spawnRedisServer() + port: await spawnGlobalRedisServer() }; } async function spawnPasswordServer(): Promise { TEST_REDIS_SERVERS[TestRedisServers.PASSWORD] = { - port: await spawnRedisServer(['--requirepass', 'password']), + port: await spawnGlobalRedisServer(['--requirepass', 'password']), username: 'default', password: 'password' }; } async function spawnOpenCluster(): Promise { - TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN] = (await spawnRedisCluster(TestRedisClusters.OPEN, 3)).map(port => ({ + TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN] = (await spawnGlobalRedisCluster(TestRedisClusters.OPEN, 3)).map(port => ({ port })); } @@ -91,9 +90,34 @@ export function itWithCluster(type: TestRedisClusters, title: string, fn: (clust }); } +export function itWithDedicatedCluster(title: string, fn: (cluster: RedisClusterType) => Promise): void { + it(title, async function () { + this.timeout(10000); + + const spawnResults = await spawnRedisCluster(null, 3), + cluster = RedisCluster.create({ + rootNodes: [{ + port: spawnResults[0].port + }] + }); + + await cluster.connect(); + + try { + await fn(cluster); + } finally { + await cluster.disconnect(); + + for (const { cleanup } of spawnResults) { + await cleanup(); + } + } + }); +} + async function clusterFlushAll(cluster: RedisCluster): Promise { await Promise.all( - cluster.getMasters().map(master => master.flushAll()) + cluster.getMasters().map(({ client }) => client.flushAll()) ); } @@ -101,7 +125,12 @@ const REDIS_PATH = which.sync('redis-server'); let port = 6379; -async function spawnRedisServer(args?: Array): Promise { +interface SpawnRedisServerResult { + port: number; + cleanup: () => Promise; +} + +async function spawnRedisServer(args?: Array): Promise { const currentPort = port++, process = spawn(REDIS_PATH, [ '--save', @@ -110,23 +139,41 @@ async function spawnRedisServer(args?: Array): Promise { currentPort.toString(), ...(args ?? []) ]); + + process + .on('error', err => console.error('Redis process error', err)) + .on('close', code => console.error(`Redis process closed unexpectedly with code ${code}`)); - // TODO: catch process exit + for await (const chunk of process.stdout) { + if (chunk.toString().includes('Ready to accept connections')) { + break; + } + } - await tcpPortUsed.waitForStatus(currentPort, '127.0.0.1', true, 10, 10000); + if (process.exitCode !== null) { + throw new Error('Error while spawning redis server'); + } - after(() => { - assert.ok(process.kill()); - return once(process, 'close'); - }); + return { + port: currentPort, + async cleanup(): Promise { + process.removeAllListeners('close'); + assert.ok(process.kill()); + await once(process, 'close'); + } + }; +} - return currentPort; +async function spawnGlobalRedisServer(args?: Array): Promise { + const { port, cleanup } = await spawnRedisServer(args); + after(cleanup); + return port; } const SLOTS = 16384, CLUSTER_NODE_TIMEOUT = 2000; -async function spawnRedisCluster(type: TestRedisClusters, numberOfNodes: number, args?: Array): Promise> { +export async function spawnRedisCluster(type: TestRedisClusters | null, numberOfNodes: number, args?: Array): Promise> { const spawnPromises = [], slotsPerNode = Math.floor(SLOTS / numberOfNodes); for (let i = 0; i < numberOfNodes; i++) { @@ -157,30 +204,41 @@ async function spawnRedisCluster(type: TestRedisClusters, numberOfNodes: number, await setTimeout(CLUSTER_NODE_TIMEOUT); } - const ports = [], - disconnectPromises = []; - for (const { port, client } of spawnResults) { - ports.push(port); - disconnectPromises.push(client.disconnect()); + const disconnectPromises = []; + for (const result of spawnResults) { + disconnectPromises.push(result.client.disconnect()); } await Promise.all(disconnectPromises); - return ports; + return spawnResults; +} + +export async function spawnGlobalRedisCluster(type: TestRedisClusters | null, numberOfNodes: number, args?: Array): Promise> { + const results = await spawnRedisCluster(type, numberOfNodes, args); + + after(() => { + for (const { cleanup } of results) { + cleanup(); + } + }); + + return results.map(({ port }) => port); +} + +interface SpawnRedisClusterNodeResult extends SpawnRedisServerResult { + client: RedisClientType } async function spawnRedisClusterNode( - type: TestRedisClusters, + type: TestRedisClusters | null, nodeIndex: number, fromSlot: number, toSlot: number, args?: Array -): Promise<{ - port: number; - client: RedisClientType; -}> { +): Promise { const clusterConfigFile = `/tmp/${type}-${nodeIndex}.conf`, - port = await spawnRedisServer([ + { port, cleanup: originalCleanup } = await spawnRedisServer([ '--cluster-enabled', 'yes', '--cluster-node-timeout', @@ -190,16 +248,6 @@ async function spawnRedisClusterNode( ...(args ?? []) ]); - after(async () => { - try { - await unlink(clusterConfigFile); - } catch (err) { - if (err.code == 'ENOENT') return; - - throw err; - } - }); - const client = RedisClient.create({ socket: { port @@ -220,6 +268,17 @@ async function spawnRedisClusterNode( return { port, + async cleanup(): Promise { + await originalCleanup(); + + try { + await unlink(clusterConfigFile); + } catch (err) { + if (err.code == 'ENOENT') return; + + throw err; + } + }, client }; } diff --git a/package-lock.json b/package-lock.json index d45f6251af..f95e220d76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,19 +16,17 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/mocha": "^8.2.2", - "@types/node": "^15.6.1", + "@types/node": "^15.12.5", "@types/sinon": "^10.0.2", - "@types/tcp-port-used": "^1.0.0", "@types/which": "^2.0.0", "@types/yallist": "^4.0.0", - "mocha": "^8.4.0", + "mocha": "^9.0.1", "nyc": "^15.1.0", - "release-it": "^14.8.0", + "release-it": "^14.10.0", "sinon": "^11.1.1", "source-map-support": "^0.5.19", - "tcp-port-used": "^1.0.2", "ts-node": "^10.0.0", - "typescript": "^4.3.2", + "typescript": "^4.3.5", "which": "^2.0.2" }, "engines": { @@ -520,14 +518,14 @@ } }, "node_modules/@octokit/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.4.0.tgz", - "integrity": "sha512-6/vlKPP8NF17cgYXqucdshWqmMZGXkuvtcrWCgU5NOI0Pl2GjlmZyWgBMrU8zJ3v2MJlM6++CiB45VKYmhiWWg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "dev": true, "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -546,29 +544,29 @@ } }, "node_modules/@octokit/graphql": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.3.tgz", - "integrity": "sha512-ww2fYpuPPWhlKENk7g3Ynbqm6R5zqXOnbXuyELCiM/zjZq+hMlNOsiV/LgwCH81+i5FkeZA/IB/BgWGoAuXJwA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", "dev": true, "dependencies": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "node_modules/@octokit/openapi-types": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-7.3.2.tgz", - "integrity": "sha512-oJhK/yhl9Gt430OrZOzAl2wJqR0No9445vmZ9Ey8GjUZUpwuu/vmEFP0TDhDXdpGDoxD6/EIFHJEcY8nHXpDTA==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-8.1.4.tgz", + "integrity": "sha512-NnGr4NNDqO5wjSDJo5nxrGtzZUwoT23YasqK2H4Pav/6vSgeVTxuqCL9Aeh+cWfTxDomj1M4Os5BrXFsvl7qiQ==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.5.tgz", - "integrity": "sha512-3WSAKBLa1RaR/7GG+LQR/tAZ9fp9H9waE9aPXallidyci9oZsfgsLn5M836d3LuDC6Fcym+2idRTBpssHZePVg==", + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.6.tgz", + "integrity": "sha512-ai7TNKLi8tGkDvLM7fm0X1fbIP9u1nfXnN49ZAw2PgSoQou9yixKn5c3m0awuLacbuX2aXEvJpv1gKm3jboabg==", "dev": true, "dependencies": { - "@octokit/types": "^6.13.0" + "@octokit/types": "^6.17.3" }, "peerDependencies": { "@octokit/core": ">=2" @@ -584,12 +582,12 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.1.tgz", - "integrity": "sha512-vvWbPtPqLyIzJ7A4IPdTl+8IeuKAwMJ4LjvmqWOOdfSuqWQYZXq2CEd0hsnkidff2YfKlguzujHs/reBdAx8Sg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.3.1.tgz", + "integrity": "sha512-3B2iguGmkh6bQQaVOtCsS0gixrz8Lg0v4JuXPqBcFqLKuJtxAUf3K88RxMEf/naDOI73spD+goJ/o7Ie7Cvdjg==", "dev": true, "dependencies": { - "@octokit/types": "^6.13.1", + "@octokit/types": "^6.16.2", "deprecation": "^2.3.1" }, "peerDependencies": { @@ -597,13 +595,13 @@ } }, "node_modules/@octokit/request": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.5.0.tgz", - "integrity": "sha512-jxbMLQdQ3heFMZUaTLSCqcKs2oAHEYh7SnLLXyxbZmlULExZ/RXai7QUWWFKowcGGPlCZuKTZg0gSKHWrfYEoQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.0.tgz", + "integrity": "sha512-4cPp/N+NqmaGQwbh3vUsYqokQIzt7VjsgTYVXiwpUP2pxd5YiZB2XuTedbb0SPtv9XS7nzAKjAuQxmY8/aZkiA==", "dev": true, "dependencies": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", + "@octokit/request-error": "^2.1.0", "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", @@ -611,9 +609,9 @@ } }, "node_modules/@octokit/request-error": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.6.tgz", - "integrity": "sha512-oGQkw2/m+bVUM8h5xO8qDWDELgTKvWy6MwM5kjJyibnQBO09TXHgodB4ym7JVrFDHkQSWt47UeP9GsE8a6Fj3Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dev": true, "dependencies": { "@octokit/types": "^6.0.3", @@ -622,24 +620,24 @@ } }, "node_modules/@octokit/rest": { - "version": "18.5.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.3.tgz", - "integrity": "sha512-KPAsUCr1DOdLVbZJgGNuE/QVLWEaVBpFQwDAz/2Cnya6uW2wJ/P5RVGk0itx7yyN1aGa8uXm2pri4umEqG1JBA==", + "version": "18.6.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.6.0.tgz", + "integrity": "sha512-MdHuXHDJM7e5sUBe3K9tt7th0cs4csKU5Bb52LRi2oHAeIMrMZ4XqaTrEv660HoUPoM1iDlnj27Ab/Nh3MtwlA==", "dev": true, "dependencies": { - "@octokit/core": "^3.2.3", + "@octokit/core": "^3.5.0", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "5.0.1" + "@octokit/plugin-rest-endpoint-methods": "5.3.1" } }, "node_modules/@octokit/types": { - "version": "6.16.4", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.16.4.tgz", - "integrity": "sha512-UxhWCdSzloULfUyamfOg4dJxV9B+XjgrIZscI0VCbp4eNrjmorGEw+4qdwcpTsu6DIrm9tQsFQS2pK5QkqQ04A==", + "version": "6.17.4", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.17.4.tgz", + "integrity": "sha512-Ghk/JC4zC/1al1GwH6p8jVX6pLdypSWmbnx6h79C/yo3DeaDd6MsNsBFlHu22KbkFh+CdcAzFqdP7UdPaPPmmA==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^7.3.2" + "@octokit/openapi-types": "^8.1.4" } }, "node_modules/@sindresorhus/is": { @@ -759,11 +757,10 @@ "dev": true }, "node_modules/@types/node": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", - "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", - "dev": true, - "license": "MIT" + "version": "15.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", + "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==", + "dev": true }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -789,12 +786,6 @@ "@sinonjs/fake-timers": "^7.1.0" } }, - "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/which": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.0.tgz", @@ -1716,12 +1707,6 @@ "node": ">=4.0.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", @@ -1899,9 +1884,9 @@ } }, "node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -1936,17 +1921,16 @@ } }, "node_modules/fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", + "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" }, "engines": { "node": ">=8" @@ -2194,9 +2178,9 @@ } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -2250,9 +2234,9 @@ } }, "node_modules/globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, "dependencies": { "array-union": "^2.1.0", @@ -2553,9 +2537,9 @@ } }, "node_modules/inquirer": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.0.tgz", - "integrity": "sha512-1nKYPoalt1vMBfCMtpomsUc32wmOoWXAoq3kM/5iTfxyQ2f/BxjixQpC+mbZ7BI0JUXHED4/XPXekDVtJNpXYw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.1.tgz", + "integrity": "sha512-hUDjc3vBkh/uk1gPfMAD/7Z188Q8cvTGl0nxwaCdwSbzFh6ZKkZh+s2ozVxbE5G9ZNRyeY0+lgbAIOUFsFf98w==", "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", @@ -2630,15 +2614,6 @@ "node": ">= 0.10" } }, - "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-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2829,12 +2804,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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", @@ -2850,20 +2819,6 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "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/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2999,9 +2954,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -3116,15 +3071,19 @@ "dev": true }, "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lowercase-keys": { @@ -3210,21 +3169,21 @@ } }, "node_modules/mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "dev": true, "dependencies": { - "mime-db": "1.47.0" + "mime-db": "1.48.0" }, "engines": { "node": ">= 0.6" @@ -3267,9 +3226,9 @@ "dev": true }, "node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", + "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", @@ -3280,20 +3239,20 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", + "nanoid": "3.1.23", "serialize-javascript": "5.0.1", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.4", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -3303,7 +3262,7 @@ "mocha": "bin/mocha" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", @@ -3323,9 +3282,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -3644,9 +3603,9 @@ } }, "node_modules/ora": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz", - "integrity": "sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "dependencies": { "bl": "^4.1.0", @@ -3675,22 +3634,6 @@ "node": ">=8" } }, - "node_modules/ora/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ora/node_modules/strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -4400,30 +4343,30 @@ } }, "node_modules/release-it": { - "version": "14.8.0", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.8.0.tgz", - "integrity": "sha512-XCw4kzJqdKgtis97HcNZ45r5dx+tZhcG1Yu2IEBKym1SceXiLBbycLsfqJQ8z+VLimClKpDeBdJkU03Vo/yFqw==", + "version": "14.10.0", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.10.0.tgz", + "integrity": "sha512-BwL7W3VPILma+MwO2kEtZaAL0/G/mZafg4xgpfxy4MVxLd+28lBp22EDF2gS4GXHmcblawyV2IdbWo/56QIyJw==", "dev": true, "dependencies": { "@iarna/toml": "2.2.5", - "@octokit/rest": "18.5.3", + "@octokit/rest": "18.6.0", "async-retry": "1.3.1", "chalk": "4.1.1", "cosmiconfig": "7.0.0", "debug": "4.3.1", "deprecated-obj": "2.0.0", - "execa": "5.0.0", + "execa": "5.1.1", "find-up": "5.0.0", "form-data": "4.0.0", "git-url-parse": "11.4.4", - "globby": "11.0.3", + "globby": "11.0.4", "got": "11.8.2", "import-cwd": "3.0.0", - "inquirer": "8.1.0", + "inquirer": "8.1.1", "is-ci": "3.0.0", "lodash": "4.17.21", - "mime-types": "2.1.30", - "ora": "5.4.0", + "mime-types": "2.1.31", + "ora": "5.4.1", "os-name": "4.0.0", "parse-json": "5.2.0", "semver": "7.3.5", @@ -4942,16 +4885,6 @@ "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", @@ -5099,11 +5032,10 @@ } }, "node_modules/typescript": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", - "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5382,9 +5314,9 @@ } }, "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", + "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", "dev": true }, "node_modules/wrap-ansi": { @@ -6048,14 +5980,14 @@ } }, "@octokit/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.4.0.tgz", - "integrity": "sha512-6/vlKPP8NF17cgYXqucdshWqmMZGXkuvtcrWCgU5NOI0Pl2GjlmZyWgBMrU8zJ3v2MJlM6++CiB45VKYmhiWWg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "dev": true, "requires": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -6074,29 +6006,29 @@ } }, "@octokit/graphql": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.3.tgz", - "integrity": "sha512-ww2fYpuPPWhlKENk7g3Ynbqm6R5zqXOnbXuyELCiM/zjZq+hMlNOsiV/LgwCH81+i5FkeZA/IB/BgWGoAuXJwA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", "dev": true, "requires": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-7.3.2.tgz", - "integrity": "sha512-oJhK/yhl9Gt430OrZOzAl2wJqR0No9445vmZ9Ey8GjUZUpwuu/vmEFP0TDhDXdpGDoxD6/EIFHJEcY8nHXpDTA==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-8.1.4.tgz", + "integrity": "sha512-NnGr4NNDqO5wjSDJo5nxrGtzZUwoT23YasqK2H4Pav/6vSgeVTxuqCL9Aeh+cWfTxDomj1M4Os5BrXFsvl7qiQ==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.5.tgz", - "integrity": "sha512-3WSAKBLa1RaR/7GG+LQR/tAZ9fp9H9waE9aPXallidyci9oZsfgsLn5M836d3LuDC6Fcym+2idRTBpssHZePVg==", + "version": "2.13.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.6.tgz", + "integrity": "sha512-ai7TNKLi8tGkDvLM7fm0X1fbIP9u1nfXnN49ZAw2PgSoQou9yixKn5c3m0awuLacbuX2aXEvJpv1gKm3jboabg==", "dev": true, "requires": { - "@octokit/types": "^6.13.0" + "@octokit/types": "^6.17.3" } }, "@octokit/plugin-request-log": { @@ -6107,23 +6039,23 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.1.tgz", - "integrity": "sha512-vvWbPtPqLyIzJ7A4IPdTl+8IeuKAwMJ4LjvmqWOOdfSuqWQYZXq2CEd0hsnkidff2YfKlguzujHs/reBdAx8Sg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.3.1.tgz", + "integrity": "sha512-3B2iguGmkh6bQQaVOtCsS0gixrz8Lg0v4JuXPqBcFqLKuJtxAUf3K88RxMEf/naDOI73spD+goJ/o7Ie7Cvdjg==", "dev": true, "requires": { - "@octokit/types": "^6.13.1", + "@octokit/types": "^6.16.2", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.5.0.tgz", - "integrity": "sha512-jxbMLQdQ3heFMZUaTLSCqcKs2oAHEYh7SnLLXyxbZmlULExZ/RXai7QUWWFKowcGGPlCZuKTZg0gSKHWrfYEoQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.0.tgz", + "integrity": "sha512-4cPp/N+NqmaGQwbh3vUsYqokQIzt7VjsgTYVXiwpUP2pxd5YiZB2XuTedbb0SPtv9XS7nzAKjAuQxmY8/aZkiA==", "dev": true, "requires": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", + "@octokit/request-error": "^2.1.0", "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", @@ -6131,9 +6063,9 @@ } }, "@octokit/request-error": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.6.tgz", - "integrity": "sha512-oGQkw2/m+bVUM8h5xO8qDWDELgTKvWy6MwM5kjJyibnQBO09TXHgodB4ym7JVrFDHkQSWt47UeP9GsE8a6Fj3Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dev": true, "requires": { "@octokit/types": "^6.0.3", @@ -6142,24 +6074,24 @@ } }, "@octokit/rest": { - "version": "18.5.3", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.3.tgz", - "integrity": "sha512-KPAsUCr1DOdLVbZJgGNuE/QVLWEaVBpFQwDAz/2Cnya6uW2wJ/P5RVGk0itx7yyN1aGa8uXm2pri4umEqG1JBA==", + "version": "18.6.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.6.0.tgz", + "integrity": "sha512-MdHuXHDJM7e5sUBe3K9tt7th0cs4csKU5Bb52LRi2oHAeIMrMZ4XqaTrEv660HoUPoM1iDlnj27Ab/Nh3MtwlA==", "dev": true, "requires": { - "@octokit/core": "^3.2.3", + "@octokit/core": "^3.5.0", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "5.0.1" + "@octokit/plugin-rest-endpoint-methods": "5.3.1" } }, "@octokit/types": { - "version": "6.16.4", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.16.4.tgz", - "integrity": "sha512-UxhWCdSzloULfUyamfOg4dJxV9B+XjgrIZscI0VCbp4eNrjmorGEw+4qdwcpTsu6DIrm9tQsFQS2pK5QkqQ04A==", + "version": "6.17.4", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.17.4.tgz", + "integrity": "sha512-Ghk/JC4zC/1al1GwH6p8jVX6pLdypSWmbnx6h79C/yo3DeaDd6MsNsBFlHu22KbkFh+CdcAzFqdP7UdPaPPmmA==", "dev": true, "requires": { - "@octokit/openapi-types": "^7.3.2" + "@octokit/openapi-types": "^8.1.4" } }, "@sindresorhus/is": { @@ -6270,9 +6202,9 @@ "dev": true }, "@types/node": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", - "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", + "version": "15.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", + "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==", "dev": true }, "@types/parse-json": { @@ -6299,12 +6231,6 @@ "@sinonjs/fake-timers": "^7.1.0" } }, - "@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/which": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.0.tgz", @@ -6995,12 +6921,6 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "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", @@ -7138,9 +7058,9 @@ "dev": true }, "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", @@ -7166,17 +7086,16 @@ } }, "fast-glob": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", + "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fastq": { @@ -7348,9 +7267,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7386,9 +7305,9 @@ "dev": true }, "globby": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", - "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -7599,9 +7518,9 @@ "dev": true }, "inquirer": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.0.tgz", - "integrity": "sha512-1nKYPoalt1vMBfCMtpomsUc32wmOoWXAoq3kM/5iTfxyQ2f/BxjixQpC+mbZ7BI0JUXHED4/XPXekDVtJNpXYw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.1.tgz", + "integrity": "sha512-hUDjc3vBkh/uk1gPfMAD/7Z188Q8cvTGl0nxwaCdwSbzFh6ZKkZh+s2ozVxbE5G9ZNRyeY0+lgbAIOUFsFf98w==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", @@ -7660,12 +7579,6 @@ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "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-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -7799,12 +7712,6 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "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", @@ -7817,17 +7724,6 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "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" - } - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -7940,9 +7836,9 @@ "dev": true }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -8033,12 +7929,13 @@ "dev": true }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { @@ -8100,18 +7997,18 @@ } }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", "dev": true }, "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "dev": true, "requires": { - "mime-db": "1.47.0" + "mime-db": "1.48.0" } }, "mimic-fn": { @@ -8142,9 +8039,9 @@ "dev": true }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", + "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -8155,20 +8052,20 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", + "nanoid": "3.1.23", "serialize-javascript": "5.0.1", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.4", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -8187,9 +8084,9 @@ "dev": true }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true }, "nise": { @@ -8435,9 +8332,9 @@ } }, "ora": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz", - "integrity": "sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "requires": { "bl": "^4.1.0", @@ -8457,16 +8354,6 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -9002,30 +8889,30 @@ } }, "release-it": { - "version": "14.8.0", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.8.0.tgz", - "integrity": "sha512-XCw4kzJqdKgtis97HcNZ45r5dx+tZhcG1Yu2IEBKym1SceXiLBbycLsfqJQ8z+VLimClKpDeBdJkU03Vo/yFqw==", + "version": "14.10.0", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.10.0.tgz", + "integrity": "sha512-BwL7W3VPILma+MwO2kEtZaAL0/G/mZafg4xgpfxy4MVxLd+28lBp22EDF2gS4GXHmcblawyV2IdbWo/56QIyJw==", "dev": true, "requires": { "@iarna/toml": "2.2.5", - "@octokit/rest": "18.5.3", + "@octokit/rest": "18.6.0", "async-retry": "1.3.1", "chalk": "4.1.1", "cosmiconfig": "7.0.0", "debug": "4.3.1", "deprecated-obj": "2.0.0", - "execa": "5.0.0", + "execa": "5.1.1", "find-up": "5.0.0", "form-data": "4.0.0", "git-url-parse": "11.4.4", - "globby": "11.0.3", + "globby": "11.0.4", "got": "11.8.2", "import-cwd": "3.0.0", - "inquirer": "8.1.0", + "inquirer": "8.1.1", "is-ci": "3.0.0", "lodash": "4.17.21", - "mime-types": "2.1.30", - "ora": "5.4.0", + "mime-types": "2.1.31", + "ora": "5.4.1", "os-name": "4.0.0", "parse-json": "5.2.0", "semver": "7.3.5", @@ -9402,16 +9289,6 @@ "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", @@ -9513,9 +9390,9 @@ } }, "typescript": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", - "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "unique-string": { @@ -9728,9 +9605,9 @@ } }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", + "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", "dev": true }, "wrap-ansi": { diff --git a/package.json b/package.json index 9bb6025bf2..5858e3567c 100644 --- a/package.json +++ b/package.json @@ -33,19 +33,17 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/mocha": "^8.2.2", - "@types/node": "^15.6.1", + "@types/node": "^15.12.5", "@types/sinon": "^10.0.2", - "@types/tcp-port-used": "^1.0.0", "@types/which": "^2.0.0", "@types/yallist": "^4.0.0", - "mocha": "^8.4.0", + "mocha": "^9.0.1", "nyc": "^15.1.0", - "release-it": "^14.8.0", + "release-it": "^14.10.0", "sinon": "^11.1.1", "source-map-support": "^0.5.19", - "tcp-port-used": "^1.0.2", "ts-node": "^10.0.0", - "typescript": "^4.3.2", + "typescript": "^4.3.5", "which": "^2.0.2" }, "engines": {