diff --git a/TODO.md b/TODO.md index fc63534adc..5871eee2bf 100644 --- a/TODO.md +++ b/TODO.md @@ -29,9 +29,8 @@ * optionally filtered master(RW) & optionally filtered slaves(R) (?) ## Lua Scripts -* Create `RedisLuaScript` class -* In `RedisClient` (with TypeScript mapping) -* In `RedisMultiCommand` (with TypeScript mapping) +* ~~In `RedisClient` (with TypeScript mapping)~~ +* ~~In `RedisMultiCommand` (with TypeScript mapping)~~ * In `RedisCluster` (with TypeScript mapping) ## Multi diff --git a/lib/client.spec.ts b/lib/client.spec.ts index 1a30536083..30daf03a86 100644 --- a/lib/client.spec.ts +++ b/lib/client.spec.ts @@ -3,6 +3,7 @@ import { once } from 'events'; import { itWithClient, TEST_REDIS_SERVERS, TestRedisServers } from './test-utils'; import RedisClient from './client'; import { AbortError } from './errors'; +import { defineScript } from './lua-script'; describe('Client', () => { describe('authentication', () => { @@ -142,6 +143,64 @@ describe('Client', () => { .exec() ); }); + + it('with script', async () => { + const client = RedisClient.create({ + scripts: { + add: defineScript({ + NUMBER_OF_KEYS: 0, + SCRIPT: 'return ARGV[1] + 1;', + transformArguments(number: number): Array { + return [number.toString()]; + }, + transformReply(reply: number): number { + return reply; + } + }) + } + }); + + await client.connect(); + + try { + assert.deepEqual( + await client.multi() + .add(1) + .exec(), + [2] + ); + } finally { + await client.disconnect(); + } + }); + }); + + it('scripts', async () => { + const client = RedisClient.create({ + scripts: { + add: defineScript({ + NUMBER_OF_KEYS: 0, + SCRIPT: 'return ARGV[1] + 1;', + transformArguments(number: number): Array { + return [number.toString()]; + }, + transformReply(reply: number): number { + return reply; + } + }) + } + }); + + await client.connect(); + + try { + assert.equal( + await client.add(1), + 2 + ); + } finally { + await client.disconnect(); + } }); itWithClient(TestRedisServers.OPEN, 'should reconnect after DEBUG RESTART', async client => { @@ -160,8 +219,10 @@ describe('Client', () => { }); await client.select(1); - await client.set('key', 'value'); await assert.rejects(client.sendCommand(['DEBUG', 'RESTART'])); - // assert.equal(await client.get('key'), 'value'); + assert.equal( + (await client.clientInfo()).db, + 1 + ); }); }); \ No newline at end of file diff --git a/lib/client.ts b/lib/client.ts index 7f8ef13ad5..2df4cda01f 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -1,14 +1,16 @@ import RedisSocket, { RedisSocketOptions } from './socket'; import RedisCommandsQueue, { QueueCommandOptions } from './commands-queue'; import COMMANDS from './commands/client'; -import { RedisCommand, RedisModules, RedisModule, RedisReply } from './commands'; +import { RedisCommand, RedisModules, RedisReply } from './commands'; import RedisMultiCommand, { MultiQueuedCommand, RedisMultiCommandType } from './multi-command'; import EventEmitter from 'events'; import { CommandOptions, commandOptions, isCommandOptions } from './command-options'; +import { RedisLuaScript, RedisLuaScripts } from './lua-script'; -export interface RedisClientOptions { +export interface RedisClientOptions { socket?: RedisSocketOptions; modules?: M; + scripts?: S; commandsQueueMaxLength?: number; readOnly?: boolean; callbackify?: boolean; @@ -21,17 +23,21 @@ type WithCommands = { [P in keyof typeof COMMANDS]: RedisCommandSignature<(typeof COMMANDS)[P]>; }; -type WithModules> = { +type WithModules = { [P in keyof M[number]]: RedisCommandSignature; }; -export type RedisClientType = WithCommands & WithModules & RedisClient; +type WithScripts = { + [P in keyof S]: RedisCommandSignature; +}; + +export type RedisClientType = WithCommands & WithModules & WithScripts & RedisClient; export interface ClientCommandOptions extends QueueCommandOptions { duplicateConnection?: boolean; } -export default class RedisClient extends EventEmitter { +export default class RedisClient extends EventEmitter { static defineCommand(on: any, name: string, command: RedisCommand): void { on[name] = async function (...args: Array): Promise { const options = isCommandOptions(args[0]) && args.shift(); @@ -62,31 +68,36 @@ export default class RedisClient extends }; } - static create(options?: RedisClientOptions): RedisClientType { - return new RedisClient(options); + static create(options?: RedisClientOptions): RedisClientType { + return new RedisClient(options); } static commandOptions(options: ClientCommandOptions): CommandOptions { return commandOptions(options); }; - readonly #options?: RedisClientOptions; + readonly #options?: RedisClientOptions; readonly #socket: RedisSocket; readonly #queue: RedisCommandsQueue; - readonly #Multi: typeof RedisMultiCommand & { new(): RedisMultiCommandType }; + readonly #Multi: typeof RedisMultiCommand & { new(): RedisMultiCommandType }; #selectedDB = 0; + get options(): RedisClientOptions | null | undefined { + return this.#options; + } + get isOpen(): boolean { return this.#socket.isOpen; } - constructor(options?: RedisClientOptions) { + constructor(options?: RedisClientOptions) { super(); this.#options = options; this.#socket = this.#initiateSocket(); this.#queue = this.#initiateQueue(); this.#Multi = this.#initiateMulti(); this.#initiateModules(); + this.#initiateScripts(); this.#callbackify(); } @@ -95,15 +106,15 @@ export default class RedisClient extends const promises = []; if (this.#options?.socket?.password) { - promises.push((this as any).auth(this.#options?.socket)); + promises.push((this as any).auth(RedisClient.commandOptions({ asap: true }), this.#options?.socket)); } if (this.#options?.readOnly) { - promises.push((this as any).readOnly()); + promises.push((this as any).readOnly(RedisClient.commandOptions({ asap: true }))); } if (this.#selectedDB !== 0) { - promises.push((this as any).select(this.#selectedDB)); + promises.push((this as any).select(RedisClient.commandOptions({ asap: true }), this.#selectedDB)); } await Promise.all(promises); @@ -131,7 +142,7 @@ export default class RedisClient extends ); } - #initiateMulti(): typeof RedisMultiCommand & { new(): RedisMultiCommandType } { + #initiateMulti(): typeof RedisMultiCommand & { new(): RedisMultiCommandType } { const executor = async (commands: Array): Promise> => { const promise = Promise.all( commands.map(({encodedCommand}) => { @@ -145,11 +156,10 @@ export default class RedisClient extends return (replies[replies.length - 1] as Array); }; - const modules = this.#options?.modules; - + const options = this.#options; return class extends RedisMultiCommand { constructor() { - super(executor, modules); + super(executor, options?.modules, options?.scripts); } }; } @@ -165,6 +175,34 @@ export default class RedisClient extends } } + #initiateScripts(): void { + if (!this.#options?.scripts) return; + + for (const [name, script] of Object.entries(this.#options.scripts)) { + (this as any)[name] = async function (...args: Parameters): Promise> { + const options = isCommandOptions(args[0]) && args[0]; + return script.transformReply( + await this.#executeScript(script, [ + script.NUMBER_OF_KEYS.toString(), + ...script.transformArguments(options ? args.slice(1) : args) + ]) + ); + }; + } + } + + async #executeScript(script: S, args: Array): Promise> { + try { + return await this.sendCommand(['EVALSHA', script.SHA, ...args]); + } catch (err: any) { + if (!err?.message?.startsWith?.('NOSCRIPT')) { + throw err; + } + + return await this.sendCommand(['EVAL', script.SCRIPT, ...args]); + } + } + #callbackify(): void { if (!this.#options?.callbackify) return; @@ -183,7 +221,7 @@ export default class RedisClient extends } } - duplicate(): RedisClientType { + duplicate(): RedisClientType { return RedisClient.create(this.#options); } @@ -191,8 +229,15 @@ export default class RedisClient extends await this.#socket.connect(); } - async SELECT(db: number): Promise { - await this.sendCommand(['SELECT', db.toString()]); + async SELECT(db: number): Promise; + async SELECT(options: CommandOptions, db: number): Promise; + async SELECT(options?: any, db?: any): Promise { + if (!isCommandOptions(options)) { + db = options; + options = null; + } + + await this.sendCommand(['SELECT', db.toString()], options); this.#selectedDB = db; } @@ -218,7 +263,7 @@ export default class RedisClient extends return await promise; } - multi(): RedisMultiCommandType { + multi(): RedisMultiCommandType { return new this.#Multi(); } diff --git a/lib/cluster-slots.ts b/lib/cluster-slots.ts index 328522a7f4..bd3d5381de 100644 --- a/lib/cluster-slots.ts +++ b/lib/cluster-slots.ts @@ -33,11 +33,20 @@ export default class RedisClusterSlots { } async discover(): Promise { - // TODO - throw new Error('None of the cluster node is available'); + // TODO: shuffle? + for (const client of this.#clientByKey.values()) { + try { + await this.#discoverNodes(client.options?.socket); + return; + } catch (err) { + // this.emit('error', err); + } + } + + throw new Error('None of the cluster nodes is available'); } - async #discoverNodes(socketOptions: RedisSocketOptions) { + async #discoverNodes(socketOptions?: RedisSocketOptions) { const client = RedisClient.create({ socket: socketOptions }); diff --git a/lib/commands/CLIENT_INFO.ts b/lib/commands/CLIENT_INFO.ts new file mode 100644 index 0000000000..8dd30b7059 --- /dev/null +++ b/lib/commands/CLIENT_INFO.ts @@ -0,0 +1,85 @@ +export function transformArguments(): Array { + return ['CLIENT', 'INFO']; +} + +interface ClientInfoReply { + id: number; + addr: string; + laddr: string; + fd: number; + name: string; + age: number; + idle: number; + flags: string; + db: number; + sub: number; + psub: number; + multi: number; + qbuf: number; + qbufFree: number; + argvMem: number; + obl: number; + oll: number; + omem: number; + totMem: number; + events: string; + cmd: string; + user: string; + redir: number; +} + +const REGEX = /=([^\s]*)/g; + +export function transformReply(reply: string): ClientInfoReply { + const [ + [, id], + [, addr], + [, laddr], + [, fd], + [, name], + [, age], + [, idle], + [, flags], + [, db], + [, sub], + [, psub], + [, multi], + [, qbuf], + [, qbufFree], + [, argvMem], + [, obl], + [, oll], + [, omem], + [, totMem], + [, events], + [, cmd], + [, user], + [, redir] + ] = [...reply.matchAll(REGEX)]; + + return { + id: Number(id), + addr, + laddr, + fd: Number(fd), + name, + age: Number(age), + idle: Number(idle), + flags, + db: Number(db), + sub: Number(sub), + psub: Number(psub), + multi: Number(multi), + qbuf: Number(qbuf), + qbufFree: Number(qbufFree), + argvMem: Number(argvMem), + obl: Number(obl), + oll: Number(oll), + omem: Number(omem), + totMem: Number(totMem), + events, + cmd, + user, + redir: Number(redir) + }; +} diff --git a/lib/commands/index.ts b/lib/commands/index.ts index c855006e6a..7186b0d264 100644 --- a/lib/commands/index.ts +++ b/lib/commands/index.ts @@ -1,6 +1,7 @@ import * as APPEND from './APPEND'; import * as AUTH from './AUTH'; import * as BLPOP from './BLPOP'; +import * as CLIENT_INFO from './CLIENT_INFO'; import * as CLUSTER_NODES from './CLUSTER_NODES'; import * as COPY from './COPY'; import * as DECR from './DECR'; @@ -42,6 +43,8 @@ export default { auth: AUTH, BLPOP, blPop: BLPOP, + CLIENT_INFO, + clientInfo: CLIENT_INFO, CLUSTER_NODES, clusterNodes: CLUSTER_NODES, COPY, diff --git a/lib/lua-script.ts b/lib/lua-script.ts new file mode 100644 index 0000000000..2ff83ead2b --- /dev/null +++ b/lib/lua-script.ts @@ -0,0 +1,24 @@ +import { createHash } from 'crypto'; +import { RedisCommand } from './commands'; + +export interface RedisLuaScriptConfig extends RedisCommand { + SCRIPT: string; + NUMBER_OF_KEYS: number; +} + +interface SHA { + SHA: string; +} + +export type RedisLuaScript = RedisLuaScriptConfig & SHA; + +export interface RedisLuaScripts { + [key: string]: RedisLuaScript; +} + +export function defineScript(script: S): S & SHA { + return { + ...script, + SHA: createHash('sha1').update(script.SCRIPT).digest('hex') + }; +} diff --git a/lib/multi-command.ts b/lib/multi-command.ts index 9e5821bc6c..045bd24fb5 100644 --- a/lib/multi-command.ts +++ b/lib/multi-command.ts @@ -1,18 +1,23 @@ import COMMANDS from './commands/client'; -import { RedisCommand, RedisModule, RedisModules, RedisReply } from './commands'; +import { RedisCommand, RedisModules, RedisReply } from './commands'; import RedisCommandsQueue from './commands-queue'; +import { RedisLuaScript, RedisLuaScripts } from './lua-script'; -type RedisMultiCommandSignature = (...args: Parameters) => RedisMultiCommandType; +type RedisMultiCommandSignature = (...args: Parameters) => RedisMultiCommandType; -type RedisMultiWithCommands = { - [P in keyof typeof COMMANDS]: RedisMultiCommandSignature<(typeof COMMANDS)[P], M> +type WithCommands = { + [P in keyof typeof COMMANDS]: RedisMultiCommandSignature<(typeof COMMANDS)[P], M, S> }; -type RedisMultiWithModules> = { - [P in keyof M[number]]: RedisMultiCommandSignature +type WithModules = { + [P in keyof M[number]]: RedisMultiCommandSignature }; -export type RedisMultiCommandType = RedisMultiCommand & RedisMultiWithCommands & RedisMultiWithModules; +type WithScripts = { + [P in keyof S]: RedisMultiCommandSignature +}; + +export type RedisMultiCommandType = RedisMultiCommand & WithCommands & WithModules & WithScripts; export interface MultiQueuedCommand { encodedCommand: string; @@ -21,27 +26,57 @@ export interface MultiQueuedCommand { export type RedisMultiExecutor = (queue: Array, chainId: Symbol) => Promise>; -export default class RedisMultiCommand { - static defineCommand(on: any, name: string, command: RedisCommand) { - on[name] = function (...args: Array) { +export default class RedisMultiCommand { + static defineCommand(on: any, name: string, command: RedisCommand): void { + on[name] = function (...args: Parameters) { return this.addCommand(command.transformArguments(...args), command.transformReply); }; } - static create(executor: RedisMultiExecutor, modules?: M): RedisMultiCommandType { - return new RedisMultiCommand(executor, modules); + static defineLuaScript(on: any, name: string, script: RedisLuaScript): void { + on[name] = function (...args: Array) { + let evalArgs; + if (this.#scriptsInUse.has(name)) { + evalArgs = [ + 'EVALSHA', + script.SHA + ]; + } else { + this.#scriptsInUse.add(name); + evalArgs = [ + 'EVAL', + script.SCRIPT + ]; + } + + return this.addCommand( + [ + ...evalArgs, + script.NUMBER_OF_KEYS, + ...script.transformArguments(...args) + ], + script.transformReply + ); + }; + } + + static create(executor: RedisMultiExecutor, modules?: M, scripts?: S): RedisMultiCommandType { + return new RedisMultiCommand(executor, modules, scripts); } readonly #executor: RedisMultiExecutor; readonly #queue: Array = []; - constructor(executor: RedisMultiExecutor, modules?: RedisModules) { + readonly #scriptsInUse = new Set(); + + constructor(executor: RedisMultiExecutor, modules?: RedisModules, scripts?: RedisLuaScripts) { this.#executor = executor; this.#initiateModules(modules); + this.#initiateScripts(scripts); } - #initiateModules(modules?: RedisModules) { + #initiateModules(modules?: RedisModules): void { if (!modules) return; for (const m of modules) { @@ -51,6 +86,14 @@ export default class RedisMultiCommand { } } + #initiateScripts(scripts?: RedisLuaScripts): void { + if (!scripts) return; + + for (const [name, script] of Object.entries(scripts)) { + RedisMultiCommand.defineLuaScript(this, name, script); + } + } + addCommand(args: Array, transformReply?: RedisCommand['transformReply']): this { this.#queue.push({ encodedCommand: RedisCommandsQueue.encodeCommand(args), diff --git a/lib/test-utils.ts b/lib/test-utils.ts index a7afb851d5..e9b0f9c237 100644 --- a/lib/test-utils.ts +++ b/lib/test-utils.ts @@ -1,6 +1,7 @@ import assert from 'assert/strict'; import RedisClient, { RedisClientType } from './client'; import { RedisModules } from './commands'; +import { RedisLuaScripts } from './lua-script'; import { spawn } from 'child_process'; import { once } from 'events'; import tcpPortUsed from 'tcp-port-used'; @@ -35,7 +36,7 @@ async function spawnPasswordServer(): Promise { }; } -export function itWithClient(type: TestRedisServers, title: string, fn: (client: RedisClientType) => Promise) { +export function itWithClient(type: TestRedisServers, title: string, fn: (client: RedisClientType) => Promise) { it(title, async () => { const client = RedisClient.create({ socket: TEST_REDIS_SERVERS[type] diff --git a/package-lock.json b/package-lock.json index 1dbf084778..9bbea3db08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/mocha": "^8.2.2", - "@types/node": "^15.3.1", + "@types/node": "^15.6.1", "@types/tcp-port-used": "^1.0.0", "@types/which": "^2.0.0", "@types/yallist": "^4.0.0", @@ -24,8 +24,8 @@ "nyc": "^15.1.0", "source-map-support": "^0.5.19", "tcp-port-used": "^1.0.2", - "ts-node": "^9.1.1", - "typescript": "^4.3.1-rc", + "ts-node": "^10.0.0", + "typescript": "^4.3.2", "which": "^2.0.2" }, "engines": { @@ -470,6 +470,30 @@ "node": ">=8" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.7.tgz", + "integrity": "sha512-aBvUmXLQbayM4w3A8TrjwrXs4DZ8iduJnuJLLRGdkWlyakCf1q6uHZJBzXoRA/huAEknG5tcUyQxN3A+In5euQ==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.7.tgz", + "integrity": "sha512-dgasobK/Y0wVMswcipr3k0HpevxFJLijN03A8mYfEPvWvOs14v0ZlYTR4kIgMx8g4+fTyTFv8/jLCIfRqLDJ4A==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.0.tgz", + "integrity": "sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", + "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "dev": true + }, "node_modules/@types/mocha": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", @@ -480,7 +504,8 @@ "version": "15.6.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/tcp-port-used": { "version": "1.0.0", @@ -692,9 +717,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001228", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", - "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", "dev": true, "funding": { "type": "opencollective", @@ -947,9 +972,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.3.738", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz", - "integrity": "sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==", + "version": "1.3.740", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.740.tgz", + "integrity": "sha512-Mi2m55JrX2BFbNZGKYR+2ItcGnR4O5HhrvgoRRyZQlaMGQULqDhoGkLWHzJoshSzi7k1PUofxcDbNhlFrDZNhg==", "dev": true }, "node_modules/emoji-regex": { @@ -2402,11 +2427,15 @@ } }, "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", + "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", "dev": true, "dependencies": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", @@ -2416,15 +2445,27 @@ }, "bin": { "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" }, "peerDependencies": { + "@swc/core": ">=1.2.45", + "@swc/wasm": ">=1.2.45", + "@types/node": "*", "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "node_modules/ts-node/node_modules/diff": { @@ -2455,10 +2496,11 @@ } }, "node_modules/typescript": { - "version": "4.3.1-rc", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.1-rc.tgz", - "integrity": "sha512-L3uJ0gcntaRaKni9aV2amYB+pCDVodKe/B5+IREyvtKGsDOF7cYjchHb/B894skqkgD52ykRuWatIZMqEsHIqA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3113,6 +3155,30 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@tsconfig/node10": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.7.tgz", + "integrity": "sha512-aBvUmXLQbayM4w3A8TrjwrXs4DZ8iduJnuJLLRGdkWlyakCf1q6uHZJBzXoRA/huAEknG5tcUyQxN3A+In5euQ==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.7.tgz", + "integrity": "sha512-dgasobK/Y0wVMswcipr3k0HpevxFJLijN03A8mYfEPvWvOs14v0ZlYTR4kIgMx8g4+fTyTFv8/jLCIfRqLDJ4A==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.0.tgz", + "integrity": "sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", + "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "dev": true + }, "@types/mocha": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", @@ -3292,9 +3358,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001228", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", - "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", "dev": true }, "chalk": { @@ -3494,9 +3560,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.738", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz", - "integrity": "sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==", + "version": "1.3.740", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.740.tgz", + "integrity": "sha512-Mi2m55JrX2BFbNZGKYR+2ItcGnR4O5HhrvgoRRyZQlaMGQULqDhoGkLWHzJoshSzi7k1PUofxcDbNhlFrDZNhg==", "dev": true }, "emoji-regex": { @@ -4575,11 +4641,15 @@ } }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", + "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", "dev": true, "requires": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", @@ -4612,9 +4682,9 @@ } }, "typescript": { - "version": "4.3.1-rc", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.1-rc.tgz", - "integrity": "sha512-L3uJ0gcntaRaKni9aV2amYB+pCDVodKe/B5+IREyvtKGsDOF7cYjchHb/B894skqkgD52ykRuWatIZMqEsHIqA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true }, "uuid": { diff --git a/package.json b/package.json index 12abb9204c..541696da13 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/mocha": "^8.2.2", - "@types/node": "^15.3.1", + "@types/node": "^15.6.1", "@types/tcp-port-used": "^1.0.0", "@types/which": "^2.0.0", "@types/yallist": "^4.0.0", @@ -42,8 +42,8 @@ "nyc": "^15.1.0", "source-map-support": "^0.5.19", "tcp-port-used": "^1.0.2", - "ts-node": "^9.1.1", - "typescript": "^4.3.1-rc", + "ts-node": "^10.0.0", + "typescript": "^4.3.2", "which": "^2.0.2" }, "engines": {