From 7d2629f083b6067c8986162cba48f5d5349e66d7 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 15 Nov 2021 16:52:48 -0500 Subject: [PATCH] Support esModuleInterop set to false. (#1717) * Support esModuleInterop set to false. When testing the upcoming 4.x release, we got a bunch of typescript errors emitted from this project. We quickly realized this is because the library uses the esModuleInterop flag. This makes some imports _slightly_ easier to write, but it comes at a cost: it forces any application or library using this library to *also* have esModuleInterop on. The `esModuleInterop` flag is a bit of a holdover from an earlier time, and I would not recommend using it in libraries. The main issue is that if it's set to true, you are forcing any users of the library to also have `esModuleInterop`, where if you keep have it set to `false` (the default), you leave the decision to the user. This change should have no rammifications to users with `esModuleInterop` on, but it will enable support for those that have it off. This is especially good for library authors such as myself, because I would also like to keep this flag off to not force *my* users into this feature. * All tests now pass! * Move @types/redis-parser into client sub-package and removed a comma --- package-lock.json | 116 ++++++++++++------ packages/client/lib/client/commands-queue.ts | 8 +- packages/client/lib/client/index.ts | 2 +- packages/client/lib/client/socket.ts | 6 +- packages/client/lib/cluster/cluster-slots.ts | 6 +- packages/client/lib/cluster/index.spec.ts | 6 +- .../lib/ts-declarations/redis-parser.d.ts | 15 --- packages/client/package.json | 1 + packages/test-utils/lib/dockers.ts | 2 +- tsconfig.base.json | 6 +- 10 files changed, 104 insertions(+), 64 deletions(-) delete mode 100644 packages/client/lib/ts-declarations/redis-parser.d.ts diff --git a/package-lock.json b/package-lock.json index 2b4d4be9c6..22f8983cac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -836,10 +836,6 @@ "resolved": "packages/test-utils", "link": true }, - "node_modules/@redis/time-series": { - "resolved": "packages/time-series", - "link": true - }, "node_modules/@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -974,6 +970,22 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/redis-errors": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/redis-errors/-/redis-errors-1.2.1.tgz", + "integrity": "sha512-9p6SQPeDAIR4z3ZdrPsRH/sSRMeIA2fdRKqZ3Y1thQOLeDH4aLY+J4Ze32zjg4Dq7655Y0LonCoRrH5O7vtr4w==", + "dev": true + }, + "node_modules/@types/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-TH9NnE980dXWKjFRkck6FIv9akrD6G+vX9XXONoBgG9+NfP4iZ+SbGkaN7S15c6+JeZ+zBN62bHt2lNyUYwqoA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/redis-errors": "*" + } + }, "node_modules/@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -5556,13 +5568,13 @@ "dev": true }, "node_modules/sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz", + "integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/fake-timers": "^8.1.0", "@sinonjs/samsam": "^6.0.2", "diff": "^5.0.0", "nise": "^5.1.0", @@ -5573,6 +5585,15 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6390,6 +6411,7 @@ } }, "packages/client": { + "name": "@redis/client", "version": "1.0.0-rc", "license": "MIT", "dependencies": { @@ -6401,18 +6423,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@redis/test-utils": "*", - "@types/node": "^16.11.6", + "@types/node": "^16.11.7", + "@types/redis-parser": "^3.0.0", "@types/sinon": "^10.0.6", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.2.0", - "@typescript-eslint/parser": "^5.2.0", - "eslint": "^8.1.0", + "@typescript-eslint/eslint-plugin": "^5.3.1", + "@typescript-eslint/parser": "^5.3.1", + "eslint": "^8.2.0", "nyc": "^15.1.0", "release-it": "^14.11.6", - "sinon": "^11.1.2", + "sinon": "^12.0.1", "source-map-support": "^0.5.20", "ts-node": "^10.4.0", - "typedoc": "^0.22.7", + "typedoc": "^0.22.8", "typedoc-github-wiki-theme": "^0.6.0", "typedoc-plugin-markdown": "^3.11.3", "typescript": "^4.4.4" @@ -6422,6 +6445,7 @@ } }, "packages/json": { + "name": "@redis/json", "version": "1.0.0-rc.0", "license": "MIT", "devDependencies": { @@ -6439,6 +6463,7 @@ } }, "packages/search": { + "name": "@redis/search", "version": "1.0.0-rc.0", "license": "MIT", "devDependencies": { @@ -6456,6 +6481,7 @@ } }, "packages/test-utils": { + "name": "@redis/test-utils", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@tsconfig/node12": "^1.0.9", @@ -6476,6 +6502,7 @@ }, "packages/time-series": { "version": "1.0.0", + "extraneous": true, "license": "ISC", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", @@ -7129,21 +7156,22 @@ "requires": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@redis/test-utils": "*", - "@types/node": "^16.11.6", + "@types/node": "^16.11.7", + "@types/redis-parser": "*", "@types/sinon": "^10.0.6", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.2.0", - "@typescript-eslint/parser": "^5.2.0", + "@typescript-eslint/eslint-plugin": "^5.3.1", + "@typescript-eslint/parser": "^5.3.1", "cluster-key-slot": "1.1.0", - "eslint": "^8.1.0", + "eslint": "^8.2.0", "generic-pool": "3.8.2", "nyc": "^15.1.0", "redis-parser": "3.0.0", "release-it": "^14.11.6", - "sinon": "^11.1.2", + "sinon": "^12.0.1", "source-map-support": "^0.5.20", "ts-node": "^10.4.0", - "typedoc": "^0.22.7", + "typedoc": "^0.22.8", "typedoc-github-wiki-theme": "^0.6.0", "typedoc-plugin-markdown": "^3.11.3", "typescript": "^4.4.4", @@ -7193,19 +7221,6 @@ "yargs": "^17.2.1" } }, - "@redis/time-series": { - "version": "file:packages/time-series", - "requires": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@redis/test-utils": "*", - "@types/node": "^16.11.6", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "source-map-support": "^0.5.20", - "ts-node": "^10.4.0", - "typescript": "^4.4.4" - } - }, "@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -7331,6 +7346,22 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/redis-errors": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/redis-errors/-/redis-errors-1.2.1.tgz", + "integrity": "sha512-9p6SQPeDAIR4z3ZdrPsRH/sSRMeIA2fdRKqZ3Y1thQOLeDH4aLY+J4Ze32zjg4Dq7655Y0LonCoRrH5O7vtr4w==", + "dev": true + }, + "@types/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-TH9NnE980dXWKjFRkck6FIv9akrD6G+vX9XXONoBgG9+NfP4iZ+SbGkaN7S15c6+JeZ+zBN62bHt2lNyUYwqoA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/redis-errors": "*" + } + }, "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -10719,17 +10750,28 @@ "dev": true }, "sinon": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", - "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz", + "integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/fake-timers": "^8.1.0", "@sinonjs/samsam": "^6.0.2", "diff": "^5.0.0", "nise": "^5.1.0", "supports-color": "^7.2.0" + }, + "dependencies": { + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } } }, "slash": { diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 4e2a66c606..4fcae1e8b6 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,8 +1,12 @@ -import LinkedList from 'yallist'; -import RedisParser from 'redis-parser'; +import * as LinkedList from 'yallist'; import { AbortError } from '../errors'; import { RedisCommandArguments, RedisCommandRawReply } from '../commands'; +// We need to use 'require', because it's not possible with Typescript to import +// classes that are exported as 'module.exports = class`, without esModuleInterop +// set to true. +const RedisParser = require('redis-parser'); + export interface QueueCommandOptions { asap?: boolean; chainId?: symbol; diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 05c219ca52..8802631eda 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -4,7 +4,7 @@ import RedisSocket, { RedisSocketOptions, RedisNetSocketOptions, RedisTlsSocketO import RedisCommandsQueue, { PubSubListener, PubSubSubscribeCommands, PubSubUnsubscribeCommands, QueueCommandOptions } from './commands-queue'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; -import EventEmitter from 'events'; +import { EventEmitter } from 'events'; import { CommandOptions, commandOptions, isCommandOptions } from '../command-options'; import { ScanOptions, ZMember } from '../commands/generic-transformers'; import { ScanCommandOptions } from '../commands/SCAN'; diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 81a3aa098a..d42b42d64d 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -1,6 +1,6 @@ -import EventEmitter from 'events'; -import net from 'net'; -import tls from 'tls'; +import { EventEmitter } from 'events'; +import * as net from 'net'; +import * as tls from 'tls'; import { encodeCommand } from '../commander'; import { RedisCommandArguments } from '../commands'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError } from '../errors'; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 4c53445b68..ff4c79b4d3 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -1,9 +1,13 @@ -import calculateSlot from 'cluster-key-slot'; import RedisClient, { InstantiableRedisClient, RedisClientType } from '../client'; import { RedisClusterMasterNode, RedisClusterReplicaNode } from '../commands/CLUSTER_NODES'; import { RedisClusterClientOptions, RedisClusterOptions } from '.'; import { RedisModules, RedisScripts } from '../commands'; +// We need to use 'require', because it's not possible with Typescript to import +// function that are exported as 'module.exports = function`, without esModuleInterop +// set to true. +const calculateSlot = require('cluster-key-slot'); + export interface ClusterNode { id: string; client: RedisClientType; diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index c926c02d03..66d458522e 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -1,9 +1,13 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import calculateSlot from 'cluster-key-slot'; import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; import { SQUARE_SCRIPT } from '../client/index.spec'; +// We need to use 'require', because it's not possible with Typescript to import +// function that are exported as 'module.exports = function`, without esModuleInterop +// set to true. +const calculateSlot = require('cluster-key-slot'); + describe('Cluster', () => { testUtils.testWithCluster('sendCommand', async cluster => { await cluster.connect(); diff --git a/packages/client/lib/ts-declarations/redis-parser.d.ts b/packages/client/lib/ts-declarations/redis-parser.d.ts deleted file mode 100644 index 7ec129ed8c..0000000000 --- a/packages/client/lib/ts-declarations/redis-parser.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -declare module 'redis-parser' { - interface RedisParserCallbacks { - returnReply(reply: unknown): void; - returnError(err: Error): void; - returnFatalError?(err: Error): void; - } - - export default class RedisParser { - constructor(callbacks: RedisParserCallbacks); - - setReturnBuffers(returnBuffers?: boolean): void; - - execute(buffer: Buffer): void; - } -} diff --git a/packages/client/package.json b/packages/client/package.json index 88f40a4b19..1f8226cc98 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -20,6 +20,7 @@ "@istanbuljs/nyc-config-typescript": "^1.0.1", "@redis/test-utils": "*", "@types/node": "^16.11.7", + "@types/redis-parser": "^3.0.0", "@types/sinon": "^10.0.6", "@types/yallist": "^4.0.1", "@typescript-eslint/eslint-plugin": "^5.3.1", diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index 28bd1e4905..052388970e 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -3,7 +3,7 @@ import { once } from 'events'; import { RedisModules, RedisScripts } from '@redis/client/lib/commands'; import RedisClient, { RedisClientType } from '@redis/client/lib/client'; import { promiseTimeout } from '@redis/client/lib/utils'; -import path from 'path'; +import * as path from 'path'; import { promisify } from 'util'; import { exec } from 'child_process'; const execAsync = promisify(exec); diff --git a/tsconfig.base.json b/tsconfig.base.json index d6cd971b01..7df8102966 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -3,11 +3,11 @@ "compilerOptions": { "declaration": true, "allowJs": true, - "useDefineForClassFields": true + "useDefineForClassFields": true, + "esModuleInterop": false }, "files": [ - "./packages/client/lib/ts-declarations/cluster-key-slot.d.ts", - "./packages/client/lib/ts-declarations/redis-parser.d.ts" + "./packages/client/lib/ts-declarations/cluster-key-slot.d.ts" ], "ts-node": { "files": true