diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 00000000000..c7046805107 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,298 @@ +# Node-Redis + +[![Tests](https://img.shields.io/github/workflow/status/redis/node-redis/Tests/master.svg?label=tests)](https://codecov.io/gh/redis/node-redis) +[![Coverage](https://codecov.io/gh/redis/node-redis/branch/master/graph/badge.svg?token=xcfqHhJC37)](https://codecov.io/gh/redis/node-redis) +[![License](https://img.shields.io/github/license/redis/node-redis.svg)](https://codecov.io/gh/redis/node-redis) +[![Chat](https://img.shields.io/discord/697882427875393627.svg)](https://discord.gg/XMMVgxUm) + +## Installation + +```bash +npm install redis@next +``` + +> :warning: The new interface is clean and cool, but if you have an existing code base, you'll want to read the [migration guide](../docs/v3-to-v4.md). + +## Usage + +### Basic Example + +```typescript +import { createClient } from 'redis'; + +(async () => { + const client = createClient(); + + client.on('error', (err) => console.log('Redis Client Error', err)); + + await client.connect(); + + await client.set('key', 'value'); + const value = await client.get('key'); +})(); +``` + +The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in the format `redis[s]://[[username][:password]@][host][:port][/db-number]`: + +```typescript +createClient({ + url: 'redis://alice:foobared@awesome.redis.server:6380' +}); +``` + +You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in the [client configuration guide](../docs/client-configuration.md). + +### Redis Commands + +There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed using the raw Redis command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`, etc.): + +```typescript +// raw Redis commands +await client.HSET('key', 'field', 'value'); +await client.HGETALL('key'); + +// friendly JavaScript commands +await client.hSet('key', 'field', 'value'); +await client.hGetAll('key'); +``` + +Modifiers to commands are specified using a JavaScript object: + +```typescript +await client.set('key', 'value', { + EX: 10, + NX: true +}); +``` + +Replies will be transformed into useful data structures: + +```typescript +await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } +await client.hVals('key'); // ['value1', 'value2'] +``` + +### Unsupported Redis Commands + +If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`: + +```typescript +await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' + +await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] +``` + +### Transactions (Multi/Exec) + +Start a [transaction](https://redis.io/topics/transactions) by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results: + +```typescript +await client.set('another-key', 'another-value'); + +const [setKeyReply, otherKeyValue] = await client + .multi() + .set('key', 'value') + .get('another-key') + .exec(); // ['OK', 'another-value'] +``` + +You can also [watch](https://redis.io/topics/transactions#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. + +To dig deeper into transactions, check out the [Isolated Execution Guide](../docs/isolated-execution.md). + +### Blocking Commands + +Any command can be run on a new connection by specifying the `isolated` option. The newly created connection is closed when the command's `Promise` is fulfilled. + +This pattern works especially well for blocking commands—such as `BLPOP` and `BLMOVE`: + +```typescript +import { commandOptions } from 'redis'; + +const blPopPromise = client.blPop(commandOptions({ isolated: true }), 'key', 0); + +await client.lPush('key', ['1', '2']); + +await blPopPromise; // '2' +``` + +To learn more about isolated execution, check out the [guide](../docs/isolated-execution.md). + +### Pub/Sub + +Subscribing to a channel requires a dedicated stand-alone connection. You can easily get one by `.duplicate()`ing an existing Redis connection. + +```typescript +const subscriber = client.duplicate(); + +await subscriber.connect(); +``` + +Once you have one, simply subscribe and unsubscribe as needed: + +```typescript +await subscriber.subscribe('channel', (message) => { + console.log(message); // 'message' +}); + +await subscriber.pSubscribe('channe*', (message, channel) => { + console.log(message, channel); // 'message', 'channel' +}); + +await subscriber.unsubscribe('channel'); + +await subscriber.pUnsubscribe('channe*'); +``` + +Publish a message on a channel: + +```typescript +await publisher.publish('channel', 'message'); +``` + +### Scan Iterator + +[`SCAN`](https://redis.io/commands/scan) results can be looped over using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator): + +```typescript +for await (const key of client.scanIterator()) { + // use the key! + await client.get(key); +} +``` + +This works with `HSCAN`, `SSCAN`, and `ZSCAN` too: + +```typescript +for await (const { field, value } of client.hScanIterator('hash')) {} +for await (const member of client.sScanIterator('set')) {} +for await (const { score, member } of client.zScanIterator('sorted-set')) {} +``` + +You can override the default options by providing a configuration object: + +```typescript +client.scanIterator({ + TYPE: 'string', // `SCAN` only + MATCH: 'patter*', + COUNT: 100 +}); +``` + +### Lua Scripts + +Define new functions using [Lua scripts](https://redis.io/commands/eval) which execute on the Redis server: + +```typescript +import { createClient, defineScript } from 'redis'; + +(async () => { + const client = createClient({ + scripts: { + add: defineScript({ + NUMBER_OF_KEYS: 1, + SCRIPT: + 'local val = redis.pcall("GET", KEYS[1]);' + + 'return val + ARGV[1];', + transformArguments(key: string, toAdd: number): Array { + return [key, toAdd.toString()]; + }, + transformReply(reply: number): number { + return reply; + } + }) + } + }); + + await client.connect(); + + await client.set('key', '1'); + await client.add('key', 2); // 3 +})(); +``` + +### Disconnecting + +There are two functions that disconnect a client from the Redis server. In most scenarios you should use `.quit()` to ensure that pending commands are sent to Redis before closing a connection. + +#### `.QUIT()`/`.quit()` + +Gracefully close a client's connection to Redis, by sending the [`QUIT`](https://redis.io/commands/quit) command to the server. Before quitting, the client executes any remaining commands in its queue, and will receive replies from Redis for each of them. + +```typescript +const [ping, get, quit] = await Promise.all([ + client.ping(), + client.get('key'), + client.quit() +]); // ['PONG', null, 'OK'] + +try { + await client.get('key'); +} catch (err) { + // ClosedClient Error +} +``` + +#### `.disconnect()` + +Forcibly close a client's connection to Redis immediately. Calling `disconnect` will not send further pending commands to the Redis server, or wait for or parse outstanding responses. + +```typescript +await client.disconnect(); +``` + +### Auto-Pipelining + +Node Redis will automatically pipeline requests that are made during the same "tick". + +```typescript +client.set('Tm9kZSBSZWRpcw==', 'users:1'); +client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw=='); +``` + +Of course, if you don't do something with your Promises you're certain to get [unhandled Promise exceptions](https://nodejs.org/api/process.html#process_event_unhandledrejection). To take advantage of auto-pipelining and handle your Promises, use `Promise.all()`. + +```typescript +await Promise.all([ + client.set('Tm9kZSBSZWRpcw==', 'users:1'), + client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==') +]); +``` + +### Clustering + +Check out the [Clustering Guide](../docs/clustering.md) when using Node Redis to connect to a Redis Cluster. + +## Supported Redis versions + +Node Redis is supported with the following versions of Redis: + +| Version | Supported | +|---------|--------------------| +| 6.2.z | :heavy_check_mark: | +| 6.0.z | :heavy_check_mark: | +| 5.y.z | :heavy_check_mark: | +| < 5.0 | :x: | + +> Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support. + +## Packages + +| Name | Description | +|-------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [redis](../) | [![Downloads](https://img.shields.io/npm/dm/redis.svg)](https://www.npmjs.com/package/redis/v/next) [![Version](https://img.shields.io/npm/v/redis/next.svg)](https://www.npmjs.com/package/redis/v/next) | +| [@node-redis/client](../packages/client) | [![Downloads](https://img.shields.io/npm/dm/@node-redis/client.svg)](https://www.npmjs.com/package/@node-redis/client/v/next) [![Version](https://img.shields.io/npm/v/@node-redis/client/next.svg)](https://www.npmjs.com/package/@node-redis/client/v/next) | +| [@node-redis/json](../packages/json) | [![Downloads](https://img.shields.io/npm/dm/@node-redis/json.svg)](https://www.npmjs.com/package/@node-redis/json/v/next) [![Version](https://img.shields.io/npm/v/@node-redis/json/next.svg)](https://www.npmjs.com/package/@node-redis/json/v/next) [Redis JSON](https://oss.redis.com/redisjson/) commands | +| [@node-redis/search](../packages/search) | [![Downloads](https://img.shields.io/npm/dm/@node-redis/search.svg)](https://www.npmjs.com/package/@node-redis/search/v/next) [![Version](https://img.shields.io/npm/v/@node-redis/search/next.svg)](https://www.npmjs.com/package/@node-redis/search/v/next) [Redis Search](https://oss.redis.com/redisearch/) commands | + +## Contributing + +If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md). + +Thank you to all the people who already contributed to Node Redis! + +[![Contributors](https://contrib.rocks/image?repo=redis/node-redis)](https://github.com/redis/node-redis/graphs/contributors) + +## License + +This repository is licensed under the "MIT" license. See [LICENSE](LICENSE). diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml new file mode 100644 index 00000000000..9a98b1c08a3 --- /dev/null +++ b/.github/release-drafter-config.yml @@ -0,0 +1,43 @@ +name-template: 'Version $NEXT_PATCH_VERSION' +tag-template: 'v$NEXT_PATCH_VERSION' +autolabeler: + - label: 'chore' + files: + - '*.md' + - '.github/*' + - label: 'bug' + branch: + - '/bug-.+' + - label: 'chore' + branch: + - '/chore-.+' + - label: 'feature' + branch: + - '/feature-.+' +categories: + - title: 'Breaking Changes' + labels: + - 'breakingchange' + - title: '🚀 New Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE (#$NUMBER)' +exclude-labels: + - 'skip-changelog' +template: | + ## Changes + + $CHANGES + + ## Contributors + We'd like to thank all the contributors who worked on this release! + + $CONTRIBUTORS diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml deleted file mode 100644 index 2df438eb19c..00000000000 --- a/.github/workflows/benchmark.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Benchmark - -on: - push: - branches: - - master - - v4.0 - -jobs: - benchmark: - name: Benchmark - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - node-version: [16.x] - redis-version: [6.x] - - steps: - - uses: actions/checkout@v2.3.4 - with: - fetch-depth: 1 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2.3.0 - with: - node-version: ${{ matrix.node-version }} - - - name: Setup Redis - uses: shogo82148/actions-setup-redis@v1.12.0 - with: - redis-version: ${{ matrix.redis-version }} - - - name: Install Packages - run: npm ci - - - name: Build - run: npm run build - - - name: Install Benchmark Packages - run: npm ci - working-directory: ./benchmark - - - name: Benchmark - run: npm run start - working-directory: ./benchmark diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 9575d4639b9..861010b7f01 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -9,21 +9,16 @@ on: jobs: documentation: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v2.3.4 with: fetch-depth: 1 - - name: Use Node.js uses: actions/setup-node@v2.3.0 - - name: Install Packages run: npm ci - - name: Generate Documentation run: npm run documentation - - name: Upload Documentation to Wiki uses: SwiftDocOrg/github-wiki-publish-action@v1 with: diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 00000000000..ec2d88bf6e7 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,19 @@ +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml + config-name: release-drafter-config.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 557d4f452dc..f8e68c0e203 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,6 +5,10 @@ on: branches: - master - v4.0 + pull_request: + branches: + - master + - v4.0 jobs: tests: @@ -12,47 +16,32 @@ jobs: strategy: fail-fast: false matrix: - node-version: [12.x, 14.x, 16.x] - redis-version: [5.x, 6.x] - + node-version: [12, 14, 16] + redis-version: [5, 6.0, 6.2] steps: - uses: actions/checkout@v2.3.4 with: fetch-depth: 1 - - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2.3.0 with: node-version: ${{ matrix.node-version }} - - - name: Setup Redis - uses: shogo82148/actions-setup-redis@v1.12.0 - with: - redis-version: ${{ matrix.redis-version }} - auto-start: "false" - + - name: Update npm + run: npm i -g npm + if: ${{ matrix.node-version <= 14 }} - name: Install Packages run: npm ci - + - name: Build tests tools + run: npm run build:tests-tools - name: Run Tests - run: npm run test - - - name: Generate lcov - run: ./node_modules/.bin/nyc report -r lcov - - - name: Coveralls - uses: coverallsapp/github-action@1.1.3 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - flag-name: Node ${{ matrix.node-version }} Redis ${{ matrix.redis-version }} - parallel: true - - finish: - needs: tests - runs-on: ubuntu-latest - steps: - - name: Coveralls Finished - uses: coverallsapp/github-action@1.1.3 - with: - github-token: ${{ secrets.github_token }} - parallel-finished: true + run: npm run test -- --forbid-only --redis-version=${{ matrix.redis-version }} + - name: Upload to Codecov + run: | + curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import + curl -Os https://uploader.codecov.io/latest/linux/codecov + curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM + curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig + gpgv codecov.SHA256SUM.sig codecov.SHA256SUM + shasum -a 256 -c codecov.SHA256SUM + chmod +x codecov + ./codecov diff --git a/.gitignore b/.gitignore index 0bdff14c7ff..9ee58bfbd30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ -.vscode/ .idea/ -node_modules/ -dist/ .nyc_output/ +.vscode/ coverage/ +dist/ +node_modules/ +.DS_Store dump.rdb -documentation/ diff --git a/.npmignore b/.npmignore index e3fc1a7731d..a36c5e83cf2 100644 --- a/.npmignore +++ b/.npmignore @@ -1,18 +1,12 @@ +.github/ .vscode/ -.idea/ -node_modules/ -.nyc_output/ -coverage/ -dump.rdb -documentation/ -CONTRIBUTING.md -tsconfig.json +docs/ +examples/ +packages/ .deepsource.toml -.nycrc.json -benchmark/ -.github/ -scripts/ -lib/ +.release-it.json +CONTRIBUTING.md +SECURITY.md index.ts -*.spec.* -dist/lib/test-utils.* +tsconfig.base.json +tsconfig.json diff --git a/.release-it.json b/.release-it.json new file mode 100644 index 00000000000..982b4ac6cbe --- /dev/null +++ b/.release-it.json @@ -0,0 +1,7 @@ +{ + "git": { + "tagName": "redis@${version}", + "commitMessage": "Release ${tagName}", + "tagAnnotation": "Release ${tagName}" + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbad5205081..0243cc19359 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,12 +45,9 @@ A huge thank you to the original author of Node Redis, [Matthew Ranney](https:// Node Redis has a full test suite with coverage setup. -To run the tests, run `npm install` to install dependencies, then run `npm test`. +To run the tests, run `npm install` to install dependencies, then run `npm run build:tests-tools && npm test`. -Note that the test suite assumes that a few tools are installed in your environment, such as: - -- redis (make sure redis-server is not running when starting the tests, it's part of the test-suite to start it and you'll end up with a "port already in use" error) -- stunnel (for TLS tests) +Note that the test suite assumes that [`docker`](https://www.docker.com/) is installed in your environment. ### Submitting Code for Review diff --git a/LICENSE b/LICENSE index 5cb3bb4180b..db86cc4de7f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ - MIT License +MIT License Copyright (c) 2016-present Node Redis contributors. diff --git a/README.md b/README.md index c768b691d71..a98e6a261b2 100644 --- a/README.md +++ b/README.md @@ -1,289 +1,2 @@ -

- - - -

Node Redis

-

- -
- - Coverage Status - - - Downloads - - - Version - - - Chat - -
- ---- - -## Installation - -```bash -npm install redis@next -``` - -> :warning: The new interface is clean and cool, but if you have an existing code base, you'll want to read the [migration guide](./docs/v3-to-v4.md). - -## Usage - -### Basic Example - -```typescript -import { createClient } from 'redis'; - -(async () => { - const client = createClient(); - - client.on('error', (err) => console.log('Redis Client Error', err)); - - await client.connect(); - - await client.set('key', 'value'); - const value = await client.get('key'); -})(); -``` - -The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in the format `redis[s]://[[username][:password]@][host][:port][/db-number]`: - -```typescript -createClient({ - url: 'redis://alice:foobared@awesome.redis.server:6380' -}); -``` - -You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in in the [Wiki](https://github.com/NodeRedis/node-redis/wiki/lib.socket#RedisSocketOptions). - -### Redis Commands - -There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed using the raw Redis command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`, etc.): - -```typescript -// raw Redis commands -await client.HSET('key', 'field', 'value'); -await client.HGETALL('key'); - -// friendly JavaScript commands -await client.hSet('key', 'field', 'value'); -await client.hGetAll('key'); -``` - -Modifiers to commands are specified using a JavaScript object: - -```typescript -await client.set('key', 'value', { - EX: 10, - NX: true -}); -``` - -Replies will be transformed into useful data structures: - -```typescript -await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } -await client.hVals('key'); // ['value1', 'value2'] -``` - -### Unsupported Redis Commands - -If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`: - -```typescript -await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' - -await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] -``` - -### Transactions (Multi/Exec) - -Start a [transaction](https://redis.io/topics/transactions) by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results: - -```typescript -await client.set('another-key', 'another-value'); - -const [setKeyReply, otherKeyValue] = await client - .multi() - .set('key', 'value') - .get('another-key') - .exec(); // ['OK', 'another-value'] -``` - -You can also [watch](https://redis.io/topics/transactions#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. - -To dig deeper into transactions, check out the [Isolated Execution Guide](./docs/isolated-execution.md). - -### Blocking Commands - -Any command can be run on a new connection by specifying the `isolated` option. The newly created connection is closed when the command's `Promise` is fulfilled. - -This pattern works especially well for blocking commands—such as `BLPOP` and `BLMOVE`: - -```typescript -import { commandOptions } from 'redis'; - -const blPopPromise = client.blPop(commandOptions({ isolated: true }), 'key'); - -await client.lPush('key', ['1', '2']); - -await blPopPromise; // '2' -``` - -To learn more about isolated execution, check out the [guide](./docs/isolated-execution.md). - -### Pub/Sub - -Subscribing to a channel requires a dedicated stand-alone connection. You can easily get one by `.duplicate()`ing an existing Redis connection. - -```typescript -const subscriber = client.duplicate(); - -await subscriber.connect(); -``` - -Once you have one, simply subscribe and unsubscribe as needed: - -```typescript -await subscriber.subscribe('channel', (message) => { - console.log(message); // 'message' -}); - -await subscriber.pSubscribe('channe*', (message, channel) => { - console.log(message, channel); // 'message', 'channel' -}); - -await subscriber.unsubscribe('channel'); - -await subscriber.pUnsubscribe('channe*'); -``` - -Publish a message on a channel: - -```typescript -await publisher.publish('channel', 'message'); -``` - -### Scan Iterator - -[`SCAN`](https://redis.io/commands/scan) results can be looped over using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator): - -```typescript -for await (const key of client.scanIterator()) { - // use the key! - await client.get(key); -} -``` - -This works with `HSCAN`, `SSCAN`, and `ZSCAN` too: - -```typescript -for await (const member of client.hScanIterator('hash')) {} -for await (const { field, value } of client.sScanIterator('set')) {} -for await (const { member, score } of client.zScanIterator('sorted-set')) {} -``` - -You can override the default options by providing a configuration object: - -```typescript -client.scanIterator({ - TYPE: 'string', // `SCAN` only - MATCH: 'patter*', - COUNT: 100, -}); -``` - -### Lua Scripts - -Define new functions using [Lua scripts](https://redis.io/commands/eval) which execute on the Redis server: - -```typescript -import { createClient } from 'redis'; -import { defineScript } from 'redis/lua-script'; - -(async () => { - const client = createClient({ - scripts: { - add: defineScript({ - NUMBER_OF_KEYS: 1, - SCRIPT: - "local val = redis.pcall('GET', KEYS[1]);' + 'return val + ARGV[1];", - transformArguments(key: string, toAdd: number): Array { - return [key, number.toString()]; - }, - transformReply(reply: number): number { - return reply; - } - }) - } - }); - - await client.connect(); - - await client.set('key', '1'); - await client.add('key', 2); // 3 -})(); -``` - -### Cluster - -Connecting to a cluster is a bit different. Create the client by specifying some (or all) of the nodes in your cluster and then use it like a non-clustered client: - -```typescript -import { createCluster } from 'redis'; - -(async () => { - const cluster = createCluster({ - rootNodes: [ - { - url: 'redis://10.0.0.1:30001' - }, - { - url: 'redis://10.0.0.2:30002' - } - ] - }); - - cluster.on('error', (err) => console.log('Redis Cluster Error', err)); - - await cluster.connect(); - - await cluster.set('key', 'value'); - const value = await cluster.get('key'); -})(); -``` - -### Auto-Pipelining - -Node Redis will automatically pipeline requests that are made during the same "tick". - -```typescript -client.set('Tm9kZSBSZWRpcw==', 'users:1'); -client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw=='); -``` - -Of course, if you don't do something with your Promises you're certain to get [unhandled Promise exceptions](https://nodejs.org/api/process.html#process_event_unhandledrejection). To take advantage of auto-pipelining and handle your Promises, use `Promise.all()`. - -```typescript -await Promise.all([ - client.set('Tm9kZSBSZWRpcw==', 'users:1'), - client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==') -]); -``` - -## Contributing - -If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md). - -Thank you to all the people who already contributed to Node Redis! - - - - - -## License - -This repository is licensed under the "MIT" license. See [LICENSE](LICENSE). +# redis +The sources and docs for this package are in the main [node-redis](https://github.com/redis/node-redis) repo. diff --git a/SECURITY.md b/SECURITY.md index 0839a123c96..f96aa68dc12 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,9 +5,9 @@ Node Redis is generally backwards compatible with very few exceptions, so we recommend users to always use the latest version to experience stability, performance and security. | Version | Supported | -| ------- | ------------------ | -| 4.0.x | :white_check_mark: | -| 3.1.x | :white_check_mark: | +|---------|--------------------| +| 4.0.z | :heavy_check_mark: | +| 3.1.z | :heavy_check_mark: | | < 3.1 | :x: | ## Reporting a Vulnerability diff --git a/benchmark/.gitignore b/benchmark/.gitignore deleted file mode 100644 index 3c3629e647f..00000000000 --- a/benchmark/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/benchmark/index.js b/benchmark/index.js deleted file mode 100644 index 37f88176653..00000000000 --- a/benchmark/index.js +++ /dev/null @@ -1,81 +0,0 @@ -import { add, suite, cycle, complete } from 'benny'; -import v4 from 'v4'; -import v3 from 'v3'; -import { once } from 'events'; - -const v4Client = v4.createClient(), - v4LegacyClient = v4.createClient({ - legacyMode: true - }), - v3Client = v3.createClient(); - -await Promise.all([ - v4Client.connect(), - v4LegacyClient.connect(), - once(v3Client, 'connect') -]); - -const key = random(100), - value = random(100); - -function random(size) { - const result = []; - - for (let i = 0; i < size; i++) { - result.push(Math.floor(Math.random() * 10)); - } - - return result.join(''); -} - -suite( - 'SET GET', - add('v4', async () => { - await Promise.all([ - v4Client.set(key, value), - v4Client.get(key) - ]); - }), - add('v4 - legacy mode', () => { - return new Promise((resolve, reject) => { - v4LegacyClient.set(key, value); - v4LegacyClient.get(key, (err, reply) => { - if (err) { - reject(err); - } else { - resolve(reply); - } - }); - }); - }), - add('v3', () => { - return new Promise((resolve, reject) => { - v3Client.set(key, value); - v3Client.get(key, (err, reply) => { - if (err) { - reject(err); - } else { - resolve(reply); - } - }); - }); - }), - cycle(), - complete(), - complete(() => { - return Promise.all([ - v4Client.disconnect(), - v4LegacyClient.disconnect(), - new Promise((resolve, reject) => { - v3Client.quit((err) => { - if (err) { - reject(err); - } else { - resolve(err); - } - }); - }) - ]); - }) -); - diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json deleted file mode 100644 index 4afaf8c305c..00000000000 --- a/benchmark/package-lock.json +++ /dev/null @@ -1,849 +0,0 @@ -{ - "name": "benchmark", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "benchmark", - "license": "ISC", - "dependencies": { - "benny": "3.6.15", - "v3": "npm:redis@3.1.2", - "v4": "file:../" - } - }, - "..": { - "name": "redis", - "version": "4.0.0-rc.2", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" - }, - "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.10.3", - "@types/sinon": "^10.0.4", - "@types/which": "^2.0.1", - "@types/yallist": "^4.0.1", - "mocha": "^9.1.2", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.3.0", - "typedoc": "^0.22.5", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.3", - "which": "^2.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@arrows/array": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", - "integrity": "sha512-MGYS8xi3c4tTy1ivhrVntFvufoNzje0PchjEz6G/SsWRgUKxL4tKwS6iPdO8vsaJYldagAeWMd5KRD0aX3Q39g==", - "dependencies": { - "@arrows/composition": "^1.2.2" - } - }, - "node_modules/@arrows/composition": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@arrows/composition/-/composition-1.2.2.tgz", - "integrity": "sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ==" - }, - "node_modules/@arrows/dispatch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@arrows/dispatch/-/dispatch-1.0.3.tgz", - "integrity": "sha512-v/HwvrFonitYZM2PmBlAlCqVqxrkIIoiEuy5bQgn0BdfvlL0ooSBzcPzTMrtzY8eYktPyYcHg8fLbSgyybXEqw==", - "dependencies": { - "@arrows/composition": "^1.2.2" - } - }, - "node_modules/@arrows/error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@arrows/error/-/error-1.0.2.tgz", - "integrity": "sha512-yvkiv1ay4Z3+Z6oQsUkedsQm5aFdyPpkBUQs8vejazU/RmANABx6bMMcBPPHI4aW43VPQmXFfBzr/4FExwWTEA==" - }, - "node_modules/@arrows/multimethod": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@arrows/multimethod/-/multimethod-1.1.7.tgz", - "integrity": "sha512-EjHD3XuGAV4G28rm7mu8k7zQJh/EOizh104/p9i2ofGcnL5mgKONFH/Bq6H3SJjM+WDAlKcR9WBpNhaAKCnH2g==", - "dependencies": { - "@arrows/array": "^1.4.0", - "@arrows/composition": "^1.2.2", - "@arrows/error": "^1.0.2", - "fast-deep-equal": "^3.1.1" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/benchmark": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", - "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", - "dependencies": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, - "node_modules/benny": { - "version": "3.6.15", - "resolved": "https://registry.npmjs.org/benny/-/benny-3.6.15.tgz", - "integrity": "sha512-kq6XVGGYVou3Y8KNPs3SEF881vi5fJ8sIf9w69D2rreiNfRicWVWK6u6/mObMw6BiexoHHumtipn5gcu0Tngng==", - "dependencies": { - "@arrows/composition": "^1.0.0", - "@arrows/dispatch": "^1.0.2", - "@arrows/multimethod": "^1.1.6", - "benchmark": "^2.1.4", - "fs-extra": "^9.0.1", - "json2csv": "^5.0.4", - "kleur": "^4.1.3", - "log-update": "^4.0.0", - "prettier": "^2.1.2", - "stats-median": "^1.0.1" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/json2csv": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.6.tgz", - "integrity": "sha512-0/4Lv6IenJV0qj2oBdgPIAmFiKKnh8qh7bmLFJ+/ZZHLjSeiL3fKKGX3UryvKPbxFbhV+JcYo9KUC19GJ/Z/4A==", - "dependencies": { - "commander": "^6.1.0", - "jsonparse": "^1.3.1", - "lodash.get": "^4.4.2" - }, - "bin": { - "json2csv": "bin/json2csv.js" - }, - "engines": { - "node": ">= 10", - "npm": ">= 6.13.0" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "node_modules/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/redis-commands": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/stats-median": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stats-median/-/stats-median-1.0.1.tgz", - "integrity": "sha512-IYsheLg6dasD3zT/w9+8Iq9tcIQqqu91ZIpJOnIEM25C3X/g4Tl8mhXwW2ZQpbrsJISr9+wizEYgsibN5/b32Q==" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/v3": { - "name": "redis", - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", - "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", - "dependencies": { - "denque": "^1.5.0", - "redis-commands": "^1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-redis" - } - }, - "node_modules/v4": { - "resolved": "..", - "link": true - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - } - }, - "dependencies": { - "@arrows/array": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz", - "integrity": "sha512-MGYS8xi3c4tTy1ivhrVntFvufoNzje0PchjEz6G/SsWRgUKxL4tKwS6iPdO8vsaJYldagAeWMd5KRD0aX3Q39g==", - "requires": { - "@arrows/composition": "^1.2.2" - } - }, - "@arrows/composition": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@arrows/composition/-/composition-1.2.2.tgz", - "integrity": "sha512-9fh1yHwrx32lundiB3SlZ/VwuStPB4QakPsSLrGJFH6rCXvdrd060ivAZ7/2vlqPnEjBkPRRXOcG1YOu19p2GQ==" - }, - "@arrows/dispatch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@arrows/dispatch/-/dispatch-1.0.3.tgz", - "integrity": "sha512-v/HwvrFonitYZM2PmBlAlCqVqxrkIIoiEuy5bQgn0BdfvlL0ooSBzcPzTMrtzY8eYktPyYcHg8fLbSgyybXEqw==", - "requires": { - "@arrows/composition": "^1.2.2" - } - }, - "@arrows/error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@arrows/error/-/error-1.0.2.tgz", - "integrity": "sha512-yvkiv1ay4Z3+Z6oQsUkedsQm5aFdyPpkBUQs8vejazU/RmANABx6bMMcBPPHI4aW43VPQmXFfBzr/4FExwWTEA==" - }, - "@arrows/multimethod": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@arrows/multimethod/-/multimethod-1.1.7.tgz", - "integrity": "sha512-EjHD3XuGAV4G28rm7mu8k7zQJh/EOizh104/p9i2ofGcnL5mgKONFH/Bq6H3SJjM+WDAlKcR9WBpNhaAKCnH2g==", - "requires": { - "@arrows/array": "^1.4.0", - "@arrows/composition": "^1.2.2", - "@arrows/error": "^1.0.2", - "fast-deep-equal": "^3.1.1" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "benchmark": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", - "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", - "requires": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, - "benny": { - "version": "3.6.15", - "resolved": "https://registry.npmjs.org/benny/-/benny-3.6.15.tgz", - "integrity": "sha512-kq6XVGGYVou3Y8KNPs3SEF881vi5fJ8sIf9w69D2rreiNfRicWVWK6u6/mObMw6BiexoHHumtipn5gcu0Tngng==", - "requires": { - "@arrows/composition": "^1.0.0", - "@arrows/dispatch": "^1.0.2", - "@arrows/multimethod": "^1.1.6", - "benchmark": "^2.1.4", - "fs-extra": "^9.0.1", - "json2csv": "^5.0.4", - "kleur": "^4.1.3", - "log-update": "^4.0.0", - "prettier": "^2.1.2", - "stats-median": "^1.0.1" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" - }, - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "json2csv": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.6.tgz", - "integrity": "sha512-0/4Lv6IenJV0qj2oBdgPIAmFiKKnh8qh7bmLFJ+/ZZHLjSeiL3fKKGX3UryvKPbxFbhV+JcYo9KUC19GJ/Z/4A==", - "requires": { - "commander": "^6.1.0", - "jsonparse": "^1.3.1", - "lodash.get": "^4.4.2" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==" - }, - "redis-commands": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "stats-median": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stats-median/-/stats-median-1.0.1.tgz", - "integrity": "sha512-IYsheLg6dasD3zT/w9+8Iq9tcIQqqu91ZIpJOnIEM25C3X/g4Tl8mhXwW2ZQpbrsJISr9+wizEYgsibN5/b32Q==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - }, - "v3": { - "version": "npm:redis@3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", - "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", - "requires": { - "denque": "^1.5.0", - "redis-commands": "^1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - } - }, - "v4": { - "version": "file:..", - "requires": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.10.3", - "@types/sinon": "^10.0.4", - "@types/which": "^2.0.1", - "@types/yallist": "^4.0.1", - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "mocha": "^9.1.2", - "nyc": "^15.1.0", - "redis-parser": "3.0.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.3.0", - "typedoc": "^0.22.5", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.3", - "which": "^2.0.2", - "yallist": "4.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } -} diff --git a/benchmark/package.json b/benchmark/package.json deleted file mode 100644 index ab874090c4b..00000000000 --- a/benchmark/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "benchmark", - "private": true, - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "start": "node ./" - }, - "author": "", - "license": "ISC", - "dependencies": { - "benny": "3.6.15", - "v3": "npm:redis@3.1.2", - "v4": "file:../" - } -} diff --git a/docs/client-configuration.md b/docs/client-configuration.md index 11fdb0a6819..1dbbdd8cba2 100644 --- a/docs/client-configuration.md +++ b/docs/client-configuration.md @@ -15,7 +15,7 @@ | username | | ACL username ([see ACL guide](https://redis.io/topics/acl)) | | password | | ACL password or the old "--requirepass" password | | database | | Database number to connect to (see [`SELECT`](https://redis.io/commands/select) command) | -| modules | | Object defining which [Redis Modules](https://redis.io/modules) to include (TODO - document) | +| modules | | Object defining which [Redis Modules](../.github/README.md#packages) to include | | scripts | | Object defining Lua Scripts to use with this client (see [Lua Scripts](../README.md#lua-scripts)) | | commandsQueueMaxLength | | Maximum length of the client's internal command queue | | readonly | `false` | Connect in [`READONLY`](https://redis.io/commands/readonly) mode | diff --git a/docs/clustering.md b/docs/clustering.md new file mode 100644 index 00000000000..3b5ef94a5c7 --- /dev/null +++ b/docs/clustering.md @@ -0,0 +1,56 @@ +# Clustering + +## Basic Example + +Connecting to a cluster is a bit different. Create the client by specifying some (or all) of the nodes in your cluster and then use it like a regular client instance: + +```typescript +import { createCluster } from 'redis'; + +(async () => { + const cluster = createCluster({ + rootNodes: [ + { + url: 'redis://10.0.0.1:30001' + }, + { + url: 'redis://10.0.0.2:30002' + } + ] + }); + + cluster.on('error', (err) => console.log('Redis Cluster Error', err)); + + await cluster.connect(); + + await cluster.set('key', 'value'); + const value = await cluster.get('key'); +})(); +``` + +## `createCluster` configuration + +> See the [client configuration](./client-configuration.md) page for the `rootNodes` and `defaults` configuration schemas. + +| Property | Default | Description | +|------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| rootNodes | | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster, 3 should be enough to reliably connect and obtain the cluster configuration from the server | +| defaults | | The default configuration values for every client in the cluster. Use this for example when specifying an ACL user to connect with | +| useReplicas | `false` | When `true`, distribute load by executing readonly commands (such as `GET`, `GEOSEARCH`, etc.) across all cluster nodes. When `false`, only use master nodes | +| maxCommandRedirections | `16` | The maximum number of times a command will be redirected due to `MOVED` or `ASK` errors | +| modules | | Object defining which [Redis Modules](../../README.md#modules) to include | +| scripts | | Object defining Lua Scripts to use with this client (see [Lua Scripts](../README.md#lua-scripts)) | + +## Command Routing + +### Commands that operate on Redis Keys + +Commands such as `GET`, `SET`, etc. will be routed by the first key, for instance `MGET 1 2 3` will be routed by the key `1`. + +### [Server Commands](https://redis.io/commands#server) + +Admin commands such as `MEMORY STATS`, `FLUSHALL`, etc. are not attached to the cluster, and should be executed on a specific node using `.getSlot()` or `.getAllMasters()`. + +### "Forwarded Commands" + +Some commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. The client will send these commands to a random node in order to spread the load across the cluster. diff --git a/docs/isolated-execution.md b/docs/isolated-execution.md index 78b34252a0f..1fd16b8f462 100644 --- a/docs/isolated-execution.md +++ b/docs/isolated-execution.md @@ -10,7 +10,7 @@ Below are several examples of how to use isolated execution. > NOTE: Behind the scences we're using [`generic-pool`](https://www.npmjs.com/package/generic-pool) to provide a pool of connections that can be isolated. Go there to learn more. -## The Simple Secnario +## The Simple Scenario This just isolates execution on a single connection. Do what you want with that connection: diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000000..d8b83df9cdb --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +package-lock.json diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000000..aef0b38bdbb --- /dev/null +++ b/examples/README.md @@ -0,0 +1,76 @@ +# Node Redis: Examples + +This folder contains example scripts showing how to use Node Redis in different scenarios. + +| File Name | Description | +|-----------------------------|------------------------------------------------------------------------------------| +| `blocking-list-pop.js` | Block until an element is pushed to a list | +| `command-with-modifiers.js` | Define a script that allows to run a command with several modifiers | +| `connect-as-acl-user.js` | Connect to Redis 6 using an ACL user | +| `lua-multi-incr.js` | Define a custom lua script that allows you to perform INCRBY on multiple keys | +| `search+json.js` | Use [Redis Search](https://redisearch.io/) and [Redis JSON](https://redisjson.io/) | +| `set-scan.js` | An example script that shows how to use the SSCAN iterator functionality | + +## Contributing + +We'd love to see more examples here. If you have an idea that you'd like to see included here, submit a Pull Request and we'll be sure to review it! Don't forget to check out our [contributing guide](../CONTRIBUTING.md). + +## Setup + +To set up the examples folder so that you can run an example / develop one of your own: + +``` +$ git clone https://github.com/redis/node-redis.git +$ cd node-redis +$ npm install -ws && npm run build +$ cd examples +$ npm install +``` + +### Coding Guidelines for Examples + +When adding a new example, please follow these guidelines: + +* Add your code in a single JavaScript or TypeScript file per example, directly in the `examples` folder +* Do not introduce other dependencies in your example +* Give your `.js` file a meaningful name using `-` separators e.g. `adding-to-a-stream.js` / `adding-to-a-stream.ts` +* Indent your code using 2 spaces +* Use the single line `//` comment style and comment your code +* Add a comment at the top of your `.js` / `.ts` file describing what your example does +* Add a comment at the top of your `.js` / `.ts` file describing any Redis commands that need to be run to set up data for your example (try and keep this minimal) +* Use semicolons +* Use `async` and `await` +* Use single quotes, `'hello'` not `"hello"` +* Place your example code in a single `async` function where possible, named according to the file name e.g. `add-to-stream.js` would contain `const addtoStream = async () => { ... };`, and call this function at the end of the file e.g. `addToStream();` +* Unless your example requires a connection string, assume Redis is on the default localhost port 6379 with no password +* Use meaningful example data, let's not use `foo`, `bar`, `baz` etc! +* Leave an empty line at the end of your `.js` file +* Update this `README.md` file to add your example to the table + +Use [connect-as-acl-user.js](./connect-as-acl-user.js) as a guide to develop a well formatted example script. + +### Example Template + +Here's a starter template for adding a new example, imagine this is stored in `do-something.js`: + +```javascript +// This comment should describe what the example does +// and can extend to multiple lines. + +// Set up the data in redis-cli using these commands: +// + +import { createClient } from 'redis'; + +async function doSomething() { + const client = createClient(); + + await client.connect(); + + // Add your example code here... + + await client.quit(); +} + +doSomething(); +``` diff --git a/examples/blocking-list-pop.js b/examples/blocking-list-pop.js new file mode 100644 index 00000000000..59dde3274a3 --- /dev/null +++ b/examples/blocking-list-pop.js @@ -0,0 +1,32 @@ +// This example shows how to use the blocking LPUSH command. + +// This code shows how to run with isolation the blPop Command to block the script while waiting for a value to be pushed to the list. +// The script will be blocked until the LPUSH command is executed. +// After which we log the list and quit the client. + +import { createClient, commandOptions } from 'redis'; + +async function blockingListPop() { + const client = createClient(); + + await client.connect(); + + const keyName = 'keyName'; + + const blpopPromise = client.blPop( + commandOptions({ isolated: true }), + keyName, + 0 + ); + + await client.lPush(keyName, 'value'); + + await blpopPromise; + + console.log('blpopPromise resolved'); + console.log(keyName); + + await client.quit(); +} + +blockingListPop(); diff --git a/examples/command-with-modifiers.js b/examples/command-with-modifiers.js new file mode 100644 index 00000000000..78b1d2e3d2f --- /dev/null +++ b/examples/command-with-modifiers.js @@ -0,0 +1,31 @@ +// Define a custom script that shows example of SET command +// with several modifiers. + +import { createClient } from 'redis'; + +async function commandWithModifiers() { + const client = createClient(); + + await client.connect(); + await client.del('mykey'); + + let result = await client.set('mykey', 'myvalue', { + EX: 60, + GET: true + }); + + console.log(result); //nil + + result = await client.set('mykey', 'newvalue', { + EX: 60, + GET: true + } + ); + + console.log(result); //myvalue + + await client.quit(); +} + +commandWithModifiers(); + diff --git a/examples/connect-as-acl-user.js b/examples/connect-as-acl-user.js new file mode 100644 index 00000000000..26e1e443b0a --- /dev/null +++ b/examples/connect-as-acl-user.js @@ -0,0 +1,30 @@ +// Connect to Redis 6.x as an ACL user. Attempt to run a command +// that the user is allowed to execute, and a command that the +// user is not allowed to execute. + +// Create the test user in redis-cli with this command: +// acl setuser testuser on >testpassword +ping + +import { createClient } from 'redis'; + +async function connectWithACLUser() { + const client = createClient({ + url: 'redis://testuser:testpassword@127.0.0.1:6379' + }); + + await client.connect(); + + // Returns PONG + console.log(`Response from PING command: ${await client.ping()}`); + + try { + // This will error as this user is not allowed to run this command... + console.log(`Response from GET command: ${await client.get('somekey')}`); + } catch (e) { + console.log(`GET command failed: ${e.message}`); + } + + await client.quit(); +} + +connectWithACLUser(); diff --git a/examples/lua-multi-incr.js b/examples/lua-multi-incr.js new file mode 100644 index 00000000000..ec433c27ea2 --- /dev/null +++ b/examples/lua-multi-incr.js @@ -0,0 +1,31 @@ +// Define a custome lua script that accepts two keys and an amount to +// increment each of them by + +import { createClient, defineScript } from 'redis'; + +async function luaMultiIncr() { + const client = createClient({ + scripts: { + mincr: defineScript({ + NUMBER_OF_KEYS: 2, + SCRIPT: + 'return {' + + 'redis.pcall("INCRBY", KEYS[1], ARGV[1]),' + + 'redis.pcall("INCRBY", KEYS[2], ARGV[1])' + + '}', + transformArguments(key1, key2, increment) { + return [key1, key2, increment.toString()]; + }, + }), + }, + }); + + await client.connect(); + + await client.set('mykey', '5'); + console.log(await client.mincr('mykey', 'myotherkey', 10)); // [ 15, 10 ] + + await client.quit(); +} + +luaMultiIncr(); diff --git a/examples/package.json b/examples/package.json new file mode 100644 index 00000000000..65ba1442f7e --- /dev/null +++ b/examples/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-redis-examples", + "version": "1.0.0", + "description": "node-redis 4 example script", + "main": "index.js", + "private": true, + "type": "module", + "dependencies": { + "redis": "../" + } +} + diff --git a/examples/search+json.js b/examples/search+json.js new file mode 100644 index 00000000000..adc298289cd --- /dev/null +++ b/examples/search+json.js @@ -0,0 +1,74 @@ +// Use Redis Search and Redis JSON + +import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps } from 'redis'; + +async function searchPlusJson() { + const client = createClient(); + + await client.connect(); + + // Create an index + await client.ft.create('users', { + '$.name': { + type: SchemaFieldTypes.TEXT, + SORTABLE: 'UNF' + }, + '$.age': SchemaFieldTypes.NUMERIC, + '$.coins': SchemaFieldTypes.NUMERIC + }, { + ON: 'JSON' + }); + + // Add some users + await Promise.all([ + client.json.set('users:1', '$', { + name: 'Alice', + age: 32, + coins: 100 + }), + client.json.set('users:2', '$', { + name: 'Bob', + age: 23, + coins: 15 + }) + ]); + + // Search all users under 30 + // TODO: why "$.age:[-inf, 30]" does not work? + console.log( + await client.ft.search('users', '*') + ); + // { + // total: 1, + // documents: [...] + // } + + // Some aggrigrations + console.log( + await client.ft.aggregate('users', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: [{ + type: AggregateGroupByReducers.AVG, + property: '$.age', + AS: 'avarageAge' + }, { + type: AggregateGroupByReducers.SUM, + property: '$.coins', + AS: 'totalCoins' + }] + }] + }) + ); + // { + // total: 2, + // results: [{ + // avarageAvg: '27.5', + // totalCoins: '115' + // }] + // } + + await client.quit(); +} + +searchPlusJson(); diff --git a/examples/set-scan.js b/examples/set-scan.js new file mode 100644 index 00000000000..3cca05b152d --- /dev/null +++ b/examples/set-scan.js @@ -0,0 +1,19 @@ +// An example script that shows how to use the SSCAN iterator functionality to retrieve the contents of a Redis set. +// Create the set in redis-cli with this command: +// sadd setName a b c d e f g h i j k l m n o p q + +import { createClient } from 'redis'; + +async function setScan() { + const client = createClient(); + await client.connect(); + + const setName = 'setName'; + for await (const member of client.sScanIterator(setName)) { + console.log(member); + } + + await client.quit(); +} + +setScan(); diff --git a/index.ts b/index.ts index fb448f989c7..8fb31edb08a 100644 --- a/index.ts +++ b/index.ts @@ -1,8 +1,33 @@ -import RedisClient from './lib/client'; -import RedisCluster from './lib/cluster'; +import { createClient as _createClient, createCluster as _createCluster } from '@node-redis/client'; +import { RedisScripts } from '@node-redis/client/dist/lib/commands'; +import { RedisClientOptions, RedisClientType } from '@node-redis/client/dist/lib/client'; +import { RedisClusterOptions, RedisClusterType } from '@node-redis/client/dist/lib/cluster'; +import RedisJSON from '@node-redis/json'; +import RediSearch from '@node-redis/search'; -export const createClient = RedisClient.create; +export * from '@node-redis/client'; +export * from '@node-redis/json'; +export * from '@node-redis/search'; -export const commandOptions = RedisClient.commandOptions; +const modules = { + json: RedisJSON, + ft: RediSearch +}; -export const createCluster = RedisCluster.create; +export function createClient>( + options?: Omit, 'modules'> +): RedisClientType { + return _createClient({ + ...options, + modules + }); +} + +export function createCluster>( + options: Omit, 'modules'> +): RedisClusterType { + return _createCluster({ + ...options, + modules + }); +} diff --git a/lib/cluster/index.spec.ts b/lib/cluster/index.spec.ts deleted file mode 100644 index f2227395385..00000000000 --- a/lib/cluster/index.spec.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { strict as assert } from 'assert'; -import RedisCluster from '.'; -import { defineScript } from '../lua-script'; -import { itWithCluster, 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 () => { - const cluster = RedisCluster.create({ - ...TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN], - useReplicas: true - }); - - await cluster.connect(); - - try { - await cluster.publish('channel', 'message'); - 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(); - } - }); - - itWithCluster(TestRedisClusters.OPEN, 'multi', async cluster => { - const key = 'key'; - assert.deepEqual( - await cluster.multi() - .set(key, 'value') - .get(key) - .exec(), - ['OK', 'value'] - ); - }); - - it('scripts', async () => { - const cluster = RedisCluster.create({ - ...TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN], - scripts: { - add: defineScript({ - NUMBER_OF_KEYS: 0, - SCRIPT: 'return ARGV[1] + 1;', - transformArguments(number: number): Array { - assert.equal(number, 1); - return [number.toString()]; - }, - transformReply(reply: number): number { - assert.equal(reply, 2); - return reply; - } - }) - } - }); - - await cluster.connect(); - - try { - assert.equal( - await cluster.add(1), - 2 - ); - } finally { - 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/commands/ACL_GETUSER.spec.ts b/lib/commands/ACL_GETUSER.spec.ts deleted file mode 100644 index c43cdc364ae..00000000000 --- a/lib/commands/ACL_GETUSER.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion, itWithClient, TestRedisServers } from '../test-utils'; -import { transformArguments } from './ACL_GETUSER'; - -describe('ACL GETUSER', () => { - describeHandleMinimumRedisVersion([6]); - - it('transformArguments', () => { - assert.deepEqual( - transformArguments('username'), - ['ACL', 'GETUSER', 'username'] - ); - }); - - itWithClient(TestRedisServers.OPEN, 'client.aclGetUser', async client => { - assert.deepEqual( - await client.aclGetUser('default'), - { - flags: ['on', 'allkeys', 'allchannels', 'allcommands', 'nopass'], - passwords: [], - commands: '+@all', - keys: ['*'], - channels: ['*'] - } - ); - }); -}); diff --git a/lib/commands/COMMAND.spec.ts b/lib/commands/COMMAND.spec.ts deleted file mode 100644 index 1f036dadc17..00000000000 --- a/lib/commands/COMMAND.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { strict as assert } from 'assert'; -import { itWithClient, TestRedisServers } from '../test-utils'; -import { transformArguments } from './COMMAND'; -import { CommandCategories, CommandFlags } from './generic-transformers'; - -describe('COMMAND', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['COMMAND'] - ); - }); - - itWithClient(TestRedisServers.OPEN, 'client.command', async client => { - assert.deepEqual( - (await client.command()).find(command => command.name === 'ping'), - { - name: 'ping', - arity: -1, - flags: new Set([CommandFlags.STALE, CommandFlags.FAST]), - firstKeyIndex: 0, - lastKeyIndex: 0, - step: 0, - categories: new Set([CommandCategories.FAST, CommandCategories.CONNECTION]) - } - ); - }, { - minimumRedisVersion: [6] - }); -}); diff --git a/lib/commands/COMMAND_INFO.spec.ts b/lib/commands/COMMAND_INFO.spec.ts deleted file mode 100644 index 59a61f6680a..00000000000 --- a/lib/commands/COMMAND_INFO.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { strict as assert } from 'assert'; -import { itWithClient, TestRedisServers } from '../test-utils'; -import { transformArguments } from './COMMAND_INFO'; -import { CommandCategories, CommandFlags } from './generic-transformers'; - -describe('COMMAND INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['PING']), - ['COMMAND', 'INFO', 'PING'] - ); - }); - - itWithClient(TestRedisServers.OPEN, 'client.commandInfo', async client => { - assert.deepEqual( - await client.commandInfo(['PING']), - [{ - name: 'ping', - arity: -1, - flags: new Set([CommandFlags.STALE, CommandFlags.FAST]), - firstKeyIndex: 0, - lastKeyIndex: 0, - step: 0, - categories: new Set([CommandCategories.FAST, CommandCategories.CONNECTION]) - }] - ); - }, { - minimumRedisVersion: [6] - }); -}); diff --git a/lib/commands/CONFIG_GET.ts b/lib/commands/CONFIG_GET.ts deleted file mode 100644 index 423683c13a4..00000000000 --- a/lib/commands/CONFIG_GET.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { transformReplyTuples } from './generic-transformers'; - -export function transformArguments(parameter: string): Array { - return ['CONFIG', 'GET', parameter]; -} - -export const transformReply = transformReplyTuples; diff --git a/lib/commands/ZCOUNT.ts b/lib/commands/ZCOUNT.ts deleted file mode 100644 index a18ba0fd790..00000000000 --- a/lib/commands/ZCOUNT.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { transformArgumentNumberInfinity } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, min: number, max: number): Array { - return [ - 'ZCOUNT', - key, - transformArgumentNumberInfinity(min), - transformArgumentNumberInfinity(max) - ]; -} - -export declare function transformReply(): number; diff --git a/lib/test-utils.ts b/lib/test-utils.ts deleted file mode 100644 index 978940ff93d..00000000000 --- a/lib/test-utils.ts +++ /dev/null @@ -1,377 +0,0 @@ -import { strict as assert } from 'assert'; -import RedisClient, { RedisClientOptions, RedisClientType } from './client'; -import { execSync, spawn } from 'child_process'; -import { once } from 'events'; -import which from 'which'; -import { SinonSpy } from 'sinon'; -import RedisCluster, { RedisClusterOptions, RedisClusterType } from './cluster'; -import { promises as fs } from 'fs'; -import { Context as MochaContext } from 'mocha'; -import { promiseTimeout } from './utils'; -import { RedisModules, RedisScripts } from './commands'; - -type RedisVersion = [major: number, minor: number, patch: number]; - -type PartialRedisVersion = RedisVersion | [major: number, minor: number] | [major: number]; - -const REDIS_PATH = which.sync('redis-server'); -export const REDIS_VERSION = getRedisVersion(); - -function getRedisVersion(): RedisVersion { - const raw = execSync(`${REDIS_PATH} -v`).toString(), - indexOfVersion = raw.indexOf('v='); - - if (indexOfVersion === -1) { - throw new Error('Unknown redis version'); - } - - const start = indexOfVersion + 2; - return raw.substring( - start, - raw.indexOf(' ', start) - ).split('.', 3).map(Number) as RedisVersion; -} - -export function isRedisVersionGreaterThan(minimumVersion: PartialRedisVersion | undefined): boolean { - if (minimumVersion === undefined) return true; - - const lastIndex = minimumVersion.length - 1; - for (let i = 0; i < lastIndex; i++) { - if (REDIS_VERSION[i] > minimumVersion[i]) { - return true; - } else if (minimumVersion[i] > REDIS_VERSION[i]) { - return false; - } - } - - return REDIS_VERSION[lastIndex] >= minimumVersion[lastIndex]; -} - -export enum TestRedisServers { - OPEN, - PASSWORD -} - -export const TEST_REDIS_SERVERS: Record> = {}; - -export enum TestRedisClusters { - OPEN -} - -export const TEST_REDIS_CLUSTERES: Record> = {}; - -let port = 6379; - -interface SpawnRedisServerResult { - port: number; - cleanup: () => Promise; -} - -async function spawnRedisServer(args?: Array): Promise { - const currentPort = port++, - process = spawn(REDIS_PATH, [ - '--save', - '', - '--port', - currentPort.toString(), - ...(args ?? []) - ]); - - process - .once('error', err => console.error('Redis process error', err)) - .once('close', code => console.error(`Redis process closed unexpectedly with code ${code}`)); - - for await (const chunk of process.stdout) { - if (chunk.toString().includes('Ready to accept connections')) { - break; - } - } - - if (process.exitCode !== null) { - throw new Error('Error while spawning redis server'); - } - - return { - port: currentPort, - async cleanup(): Promise { - process.removeAllListeners('close'); - assert.ok(process.kill()); - await once(process, 'close'); - } - }; -} - -async function spawnGlobalRedisServer(args?: Array): Promise { - const { port, cleanup } = await spawnRedisServer(args); - after(cleanup); - return port; -} - -const SLOTS = 16384; - -interface SpawnRedisClusterNodeResult extends SpawnRedisServerResult { - client: RedisClientType -} - -async function spawnRedisClusterNode( - type: TestRedisClusters | null, - nodeIndex: number, - fromSlot: number, - toSlot: number, - args?: Array -): Promise { - const clusterConfigFile = `/tmp/${type}-${nodeIndex}.conf`, - { port, cleanup: originalCleanup } = await spawnRedisServer([ - '--cluster-enabled', - 'yes', - '--cluster-node-timeout', - '5000', - '--cluster-config-file', - clusterConfigFile, - ...(args ?? []) - ]); - - const client = RedisClient.create({ - socket: { - port - } - }); - - await client.connect(); - - const range = []; - for (let i = fromSlot; i < toSlot; i++) { - range.push(i); - } - - await Promise.all([ - client.clusterFlushSlots(), - client.clusterAddSlots(range) - ]); - - return { - port, - async cleanup(): Promise { - await originalCleanup(); - - try { - await fs.unlink(clusterConfigFile); - } catch (err: any) { - if (err.code === 'ENOENT') return; - - throw err; - } - }, - client - }; -} - -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++) { - const fromSlot = i * slotsPerNode; - spawnPromises.push( - spawnRedisClusterNode( - type, - i, - fromSlot, - i === numberOfNodes - 1 ? SLOTS : fromSlot + slotsPerNode, - args - ) - ); - } - - const spawnResults = await Promise.all(spawnPromises), - meetPromises = []; - for (let i = 1; i < spawnResults.length; i++) { - meetPromises.push( - spawnResults[i].client.clusterMeet( - '127.0.0.1', - spawnResults[i - 1].port - ) - ); - } - - await Promise.all(meetPromises); - - while (!(await clusterIsReady(spawnResults))) { - await promiseTimeout(100); - } - - await Promise.all( - spawnResults.map(result => result.client.disconnect()) - ); - - return spawnResults; -} - -async function clusterIsReady(spawnResults: Array): Promise { - const nodesClusetrInfo = await Promise.all( - spawnResults.map(result => result.client.clusterInfo()) - ); - - return nodesClusetrInfo.every(({ state }) => state === 'ok'); -} - -export async function spawnGlobalRedisCluster(type: TestRedisClusters | null, numberOfNodes: number, args?: Array): Promise> { - const results = await spawnRedisCluster(type, numberOfNodes, args); - - after(() => Promise.all( - results.map(({ cleanup }) => cleanup()) - )); - - return results.map(({ port }) => port); -} - -async function spawnOpenServer(): Promise { - TEST_REDIS_SERVERS[TestRedisServers.OPEN] = { - socket: { - port: await spawnGlobalRedisServer() - } - }; -} - -async function spawnPasswordServer(): Promise { - TEST_REDIS_SERVERS[TestRedisServers.PASSWORD] = { - socket: { - port: await spawnGlobalRedisServer(['--requirepass', 'password']), - }, - password: 'password' - }; - - if (isRedisVersionGreaterThan([6])) { - TEST_REDIS_SERVERS[TestRedisServers.PASSWORD].username = 'default'; - } -} - -async function spawnOpenCluster(): Promise { - TEST_REDIS_CLUSTERES[TestRedisClusters.OPEN] = { - rootNodes: (await spawnGlobalRedisCluster(TestRedisClusters.OPEN, 3)).map(port => ({ - socket: { - port - } - })) - }; -} - -before(function () { - this.timeout(10000); - - return Promise.all([ - spawnOpenServer(), - spawnPasswordServer(), - spawnOpenCluster() - ]); -}); - -interface RedisTestOptions { - minimumRedisVersion?: PartialRedisVersion; -} - -export function handleMinimumRedisVersion(mochaContext: MochaContext, minimumVersion: PartialRedisVersion | undefined): boolean { - if (isRedisVersionGreaterThan(minimumVersion)) { - return false; - } - - mochaContext.skip(); - return true; -} - -export function describeHandleMinimumRedisVersion(minimumVersion: PartialRedisVersion): void { - before(function () { - handleMinimumRedisVersion(this, minimumVersion); - }); -} - -export function itWithClient( - type: TestRedisServers, - title: string, - fn: (client: RedisClientType) => Promise, - options?: RedisTestOptions -): void { - it(title, async function () { - if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return; - - const client = RedisClient.create(TEST_REDIS_SERVERS[type]); - - await client.connect(); - - try { - await client.flushAll(); - await fn(client); - } finally { - await client.flushAll(); - await client.disconnect(); - } - }); -} - -export function itWithCluster( - type: TestRedisClusters, - title: string, - fn: (cluster: RedisClusterType) => Promise, - options?: RedisTestOptions -): void { - it(title, async function () { - if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return; - - const cluster = RedisCluster.create(TEST_REDIS_CLUSTERES[type]); - - await cluster.connect(); - - try { - await clusterFlushAll(cluster); - await fn(cluster); - } finally { - await clusterFlushAll(cluster); - await cluster.disconnect(); - } - }); -} - -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: [{ - socket: { - 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(({ client }) => client.flushAll()) - ); -} - -export async function waitTillBeenCalled(spy: SinonSpy): Promise { - const start = process.hrtime.bigint(), - calls = spy.callCount; - - do { - if (process.hrtime.bigint() - start > 1_000_000_000) { - throw new Error('Waiting for more than 1 second'); - } - - await promiseTimeout(1); - } while (spy.callCount === calls) -} diff --git a/lib/ts-declarations/redis-parser.d.ts b/lib/ts-declarations/redis-parser.d.ts deleted file mode 100644 index 7ec129ed8cd..00000000000 --- a/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/package-lock.json b/package-lock.json index f47208d6c9d..5c3ebb5c208 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,79 +1,63 @@ { "name": "redis", - "version": "4.0.0-rc.3", + "version": "4.0.0-rc.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "redis", - "version": "4.0.0-rc.3", + "version": "4.0.0-rc.4", "license": "MIT", + "workspaces": [ + "./packages/*" + ], "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" + "@node-redis/client": "^1.0.0-rc", + "@node-redis/json": "^1.0.0-rc", + "@node-redis/search": "^1.0.0-rc" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.10.3", - "@types/sinon": "^10.0.4", - "@types/which": "^2.0.1", - "@types/yallist": "^4.0.1", - "mocha": "^9.1.2", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.3.0", - "typedoc": "^0.22.5", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.3", - "which": "^2.0.2" - }, - "engines": { - "node": ">=12" + "release-it": "^14.11.7", + "typescript": "^4.4.4" } }, "node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.0.tgz", + "integrity": "sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz", + "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-compilation-targets": "^7.16.0", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helpers": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -89,13 +73,22 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", + "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", "dev": true, "dependencies": { - "@babel/types": "^7.15.6", + "@babel/types": "^7.16.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -104,14 +97,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", + "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.15.0", + "@babel/compat-data": "^7.16.0", "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "browserslist": "^4.17.5", "semver": "^6.3.0" }, "engines": { @@ -121,133 +114,142 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", + "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", "dev": true, "dependencies": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-get-function-arity": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", + "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", + "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", + "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", + "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-simple-access": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz", + "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", + "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", + "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", + "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" @@ -272,26 +274,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.3.tgz", + "integrity": "sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==", "dev": true, "dependencies": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -340,15 +342,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -371,9 +364,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.3.tgz", + "integrity": "sha512-dcNwU1O4sx57ClvLBVFbEgx0UZWfd0JQX5X6fxFRCLHelFBGXFfSz6Y0FAq2PEwUqlqLkdVjVr4VASEOuUnLJw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -383,32 +376,32 @@ } }, "node_modules/@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", + "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/code-frame": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", + "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/parser": "^7.16.3", + "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -416,13 +409,22 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", + "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -450,6 +452,67 @@ "node": ">=12" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", + "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.0.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", + "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -481,6 +544,15 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -546,6 +618,15 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.1.tgz", @@ -572,6 +653,22 @@ "node": ">=8" } }, + "node_modules/@node-redis/client": { + "resolved": "packages/client", + "link": true + }, + "node_modules/@node-redis/json": { + "resolved": "packages/json", + "link": true + }, + "node_modules/@node-redis/search": { + "resolved": "packages/search", + "link": true + }, + "node_modules/@node-redis/test-utils": { + "resolved": "packages/test-utils", + "link": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -840,6 +937,12 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, "node_modules/@types/keyv": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", @@ -856,9 +959,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz", - "integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==", + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", "dev": true }, "node_modules/@types/parse-json": { @@ -867,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", @@ -877,26 +996,192 @@ } }, "node_modules/@types/sinon": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.4.tgz", - "integrity": "sha512-fOYjrxQv8zJsqOY6V6ecP4eZhQBxtY80X0er1VVnUIAIZo74jHm8e1vguG5Yt4Iv8W2Wr7TgibB8MfRe32k9pA==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.6.tgz", + "integrity": "sha512-6EF+wzMWvBNeGrfP3Nx60hhx+FfwSg1JJBLAAP/IdIUq0EYkqCYf70VT3PhuhPX9eLD+Dp+lNdpb/ZeHG8Yezg==", "dev": true, "dependencies": { "@sinonjs/fake-timers": "^7.1.0" } }, - "node_modules/@types/which": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz", - "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==", - "dev": true - }, "node_modules/@types/yallist": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", "dev": true }, + "node_modules/@types/yargs": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.5.tgz", + "integrity": "sha512-4HNq144yhaVjJs+ON6A07NEoi9Hh0Rhl/jI9Nt/l/YRjt+T6St/QK3meFARWZ8IgkzoD1LC0PdTdJenlQQi2WQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz", + "integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "5.4.0", + "@typescript-eslint/scope-manager": "5.4.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz", + "integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz", + "integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "debug": "^4.3.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz", + "integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz", + "integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz", + "integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz", + "integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.4.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -915,6 +1200,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", @@ -937,6 +1231,22 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -970,18 +1280,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1147,18 +1445,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -1200,16 +1486,16 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.3.tgz", - "integrity": "sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", + "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001264", - "electron-to-chromium": "^1.3.857", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.77", - "picocolors": "^0.2.1" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" }, "bin": { "browserslist": "cli.js" @@ -1332,18 +1618,21 @@ } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001265", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", - "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", + "version": "1.0.30001280", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001280.tgz", + "integrity": "sha512-kFXwYvHe5rix25uwueBxC569o53J6TpnGu0BEEn+6Lhl2vsnAumRFWEBhDft1fwyo6m1r4i+RqA4+163FpeFcA==", "dev": true, "funding": { "type": "opencollective", @@ -1366,18 +1655,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -1570,7 +1847,13 @@ "safe-buffer": "~5.1.1" } }, - "node_modules/cosmiconfig": { + "node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", @@ -1632,12 +1915,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1692,6 +1969,12 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "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", @@ -1771,6 +2054,18 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -1790,9 +2085,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.864", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", - "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "version": "1.3.897", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.897.tgz", + "integrity": "sha512-nRNZhAZ7hVCe75jrCUG7xLOqHMwloJMj6GEXEzY4OMahRGgwerAo+ls/qbqUwFH+E20eaSncKkQ4W8KP5SOiAg==", "dev": true }, "node_modules/emoji-regex": { @@ -1810,6 +2105,18 @@ "once": "^1.4.0" } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1844,6 +2151,119 @@ } }, "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.2.0.tgz", + "integrity": "sha512-erw7XmM+CLxTOickrimJ1SiF55jiNlVSp2qqm0NuBWPtHYQCegD5ZMaW0c3i5ytPqL+SSLaCxdvQXFPLJn+ABw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.0.4", + "@humanwhocodes/config-array": "^0.6.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^6.0.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.2.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", @@ -1855,6 +2275,75 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", + "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", + "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", + "dev": true, + "dependencies": { + "acorn": "^8.5.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -1868,6 +2357,66 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -1905,6 +2454,12 @@ "node": ">=4" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", @@ -1921,6 +2476,18 @@ "node": ">=8" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -1945,13 +2512,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, "engines": { - "node": ">=0.8.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/fill-range": { @@ -2017,6 +2587,25 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -2090,6 +2679,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "node_modules/generic-pool": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", @@ -2171,9 +2766,9 @@ } }, "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -2218,12 +2813,30 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { @@ -2374,6 +2987,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2450,9 +3072,9 @@ ] }, "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", "dev": true, "engines": { "node": ">= 4" @@ -2486,15 +3108,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/import-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", @@ -2507,6 +3120,15 @@ "node": ">=8" } }, + "node_modules/import-from/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -2624,9 +3246,9 @@ } }, "node_modules/is-core-module": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", - "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -2841,9 +3463,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { "node": ">=8" @@ -2876,6 +3498,15 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", @@ -2894,6 +3525,16 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", @@ -2908,22 +3549,10 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { "debug": "^4.1.1", @@ -2931,7 +3560,7 @@ "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { @@ -2944,9 +3573,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.5.tgz", + "integrity": "sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -2998,6 +3627,18 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -3026,9 +3667,9 @@ "dev": true }, "node_modules/keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", + "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", "dev": true, "dependencies": { "json-buffer": "3.0.1" @@ -3046,6 +3687,19 @@ "node": ">=8" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -3085,6 +3739,12 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3111,20 +3771,17 @@ } }, "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", @@ -3158,6 +3815,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -3165,9 +3831,9 @@ "dev": true }, "node_modules/marked": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.7.tgz", - "integrity": "sha512-ctKqbnLuNbsHbI26cfMyOlKgXGfl1orOv1AvWWDX7AkgfMOwCWvmuYc+mVLeWhQ9W6hdWVBynOs96VkcscKo0Q==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.8.tgz", + "integrity": "sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==", "dev": true, "bin": { "marked": "bin/marked" @@ -3262,9 +3928,9 @@ "dev": true }, "node_modules/mocha": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.2.tgz", - "integrity": "sha512-ta3LtJ+63RIBP03VBjMGtSqbe6cWXRejF9SyM9Zyli1CKZJZ+vfCTj3oW24V7wAphMJdpOFLoMI3hjJ1LWbs0w==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", + "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", @@ -3304,12 +3970,104 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/ms": { + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "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", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -3328,6 +4086,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3369,9 +4133,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -3393,9 +4157,9 @@ } }, "node_modules/node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", "dev": true }, "node_modules/normalize-path": { @@ -3472,6 +4236,15 @@ "node": ">=8.9" } }, + "node_modules/nyc/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -3535,6 +4308,15 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -3632,6 +4414,21 @@ "lru-cache": "^5.1.1" } }, + "node_modules/onigasm/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/onigasm/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -3648,6 +4445,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -3952,6 +4766,15 @@ "node": ">=0.10.0" } }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4058,9 +4881,9 @@ } }, "node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "node_modules/picomatch": { @@ -4139,6 +4962,15 @@ "node": ">=8" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -4160,6 +4992,15 @@ "node": ">=8" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/protocols": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", @@ -4176,6 +5017,15 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -4283,15 +5133,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -4349,6 +5190,18 @@ "node": ">=4" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -4374,9 +5227,9 @@ } }, "node_modules/release-it": { - "version": "14.11.6", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.11.6.tgz", - "integrity": "sha512-6BNcuzFZHThBUBJ/xYw/bxZ+58CAwrwf1zgmjq2Ibl3nlDZbjphHG6iqxkJu7mZ8TIWs6NjloEAhqpjeXoN//Q==", + "version": "14.11.7", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.11.7.tgz", + "integrity": "sha512-m4p9+x6AEQPczc96Jyg6dGFeovpJVgRCtA1lxeIgTmQVt9dutYPkkjZeJngZgUJ17/Lb1bx6ZzW2qsKmopKnbQ==", "dev": true, "dependencies": { "@iarna/toml": "2.2.5", @@ -4416,70 +5269,25 @@ "node": ">=10" } }, - "node_modules/release-it/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "es6-error": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/release-it/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" - } - }, - "node_modules/release-it/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/release-it/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" } }, "node_modules/require-main-filename": { @@ -4508,12 +5316,12 @@ "dev": true }, "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/responselike": { @@ -4614,10 +5422,24 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -4626,12 +5448,18 @@ "dev": true }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/semver-diff": { @@ -4646,6 +5474,15 @@ "node": ">=8" } }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -4700,9 +5537,9 @@ } }, "node_modules/shiki": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.11.tgz", - "integrity": "sha512-tjruNTLFhU0hruCPoJP0y+B9LKOmcqUhTpxn7pcJB3fa+04gFChuEmxmrUfOJ7ZO6Jd+HwMnDHgY3lv3Tqonuw==", + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.12.tgz", + "integrity": "sha512-VXcROdldv0/Qu0w2XvzU4IrvTeBNs/Kj/FCmtcEXGz7Tic/veQzliJj6tEiAgoKianhQstpYmbPDStHU5Opqcw==", "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", @@ -4731,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", @@ -4748,16 +5585,13 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@sinonjs/commons": "^1.7.0" } }, "node_modules/slash": { @@ -4847,26 +5681,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4912,30 +5726,24 @@ } }, "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/test-exclude": { @@ -4952,6 +5760,12 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -5007,9 +5821,9 @@ "dev": true }, "node_modules/ts-node": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.0.tgz", - "integrity": "sha512-RYIy3i8IgpFH45AX4fQHExrT8BxDeKTdC83QFJkNzkvt8uFB6QJ8XMyhynYiKMLxt9a7yuXaDBZNOYS3XjDcYw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", @@ -5062,6 +5876,39 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", "dev": true }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -5072,12 +5919,15 @@ } }, "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/typedarray-to-buffer": { @@ -5090,16 +5940,16 @@ } }, "node_modules/typedoc": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.5.tgz", - "integrity": "sha512-KFrWGU1iKiTGw0RcyjLNYDmhd7uICU14HgBNPmFKY/sT4Pm/fraaLyWyisst9vGTUAKxqibqoDITR7+ZcAkhHg==", + "version": "0.22.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.9.tgz", + "integrity": "sha512-84PjudoXVcap6bwdZFbYIUWlgdz/iLV09ZHwrCzhtHWXaDQG6mlosJ8te6DSThuRkRvQjp46HO+qY/P7Gpm78g==", "dev": true, "dependencies": { "glob": "^7.2.0", "lunr": "^2.3.9", - "marked": "^3.0.4", + "marked": "^3.0.8", "minimatch": "^3.0.4", - "shiki": "^0.9.11" + "shiki": "^0.9.12" }, "bin": { "typedoc": "bin/typedoc" @@ -5122,9 +5972,9 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.3.tgz", - "integrity": "sha512-rWiHbEIe0oZetDIsBR24XJVxGOJ91kDcHoj2KhFKxCLoJGX659EKBQkHne9QJ4W2stGhu1fRgFyQaouSBnxukA==", + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.6.tgz", + "integrity": "sha512-CV1BuxL7HR/EE1ctnPXOWzf4/Exl0FzkwtFVYaKTVWTnD/dkFLgABOfWuOL4lPmzLUOsAL85pmq+/PB6cdRppw==", "dev": true, "dependencies": { "handlebars": "^4.7.7" @@ -5133,30 +5983,10 @@ "typedoc": ">=0.22.0" } }, - "node_modules/typedoc/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5167,9 +5997,9 @@ } }, "node_modules/uglify-js": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", - "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", "dev": true, "optional": true, "bin": { @@ -5243,31 +6073,13 @@ "is-ci": "bin.js" } }, - "node_modules/update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "punycode": "^2.1.0" } }, "node_modules/url-join": { @@ -5295,15 +6107,20 @@ "dev": true }, "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "bin": { - "uuid": "bin/uuid" + "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, "node_modules/vscode-textmate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", @@ -5430,6 +6247,15 @@ "node": ">=8.12.0" } }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -5510,9 +6336,9 @@ } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", "dev": true, "dependencies": { "cliui": "^7.0.2", @@ -5524,13 +6350,13 @@ "yargs-parser": "^20.2.2" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "engines": { "node": ">=10" @@ -5551,18 +6377,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", @@ -5595,170 +6409,275 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "packages/client": { + "name": "@node-redis/client", + "version": "1.0.0-rc", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "redis-parser": "3.0.0", + "yallist": "4.0.0" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-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.4.0", + "@typescript-eslint/parser": "^5.4.0", + "eslint": "^8.2.0", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "sinon": "^12.0.1", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typedoc": "^0.22.9", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.6", + "typescript": "^4.4.4" + }, + "engines": { + "node": ">=12" + } + }, + "packages/json": { + "name": "@node-redis/json", + "version": "1.0.0-rc.0", + "license": "MIT", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + } + }, + "packages/search": { + "name": "@node-redis/search", + "version": "1.0.0-rc.0", + "license": "MIT", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + } + }, + "packages/test-utils": { + "name": "@node-redis/test-utils", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.7", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4", + "yargs": "^17.2.1" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + } } }, "dependencies": { "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "dev": true, "requires": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.0" } }, "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.0.tgz", + "integrity": "sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==", "dev": true }, "@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz", + "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-compilation-targets": "^7.16.0", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helpers": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "semver": "^6.3.0", "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", + "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", "dev": true, "requires": { - "@babel/types": "^7.15.6", + "@babel/types": "^7.16.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", + "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", "dev": true, "requires": { - "@babel/compat-data": "^7.15.0", + "@babel/compat-data": "^7.16.0", "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "browserslist": "^4.17.5", "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", + "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-get-function-arity": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", + "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", + "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", + "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", + "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-simple-access": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz", + "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", + "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", + "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", + "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.16.0" } }, "@babel/helper-validator-identifier": { @@ -5774,23 +6693,23 @@ "dev": true }, "@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.3.tgz", + "integrity": "sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==", "dev": true, "requires": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0" } }, "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -5830,12 +6749,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5854,46 +6767,54 @@ } }, "@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.3.tgz", + "integrity": "sha512-dcNwU1O4sx57ClvLBVFbEgx0UZWfd0JQX5X6fxFRCLHelFBGXFfSz6Y0FAq2PEwUqlqLkdVjVr4VASEOuUnLJw==", "dev": true }, "@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", + "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", "dev": true, "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/code-frame": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", + "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/parser": "^7.16.3", + "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } } }, "@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", + "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "to-fast-properties": "^2.0.0" } }, @@ -5912,6 +6833,54 @@ "@cspotcode/source-map-consumer": "0.8.0" } }, + "@eslint/eslintrc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz", + "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.0.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", + "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -5940,6 +6909,12 @@ "sprintf-js": "~1.0.2" } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -5986,6 +6961,12 @@ "requires": { "p-limit": "^2.2.0" } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } }, @@ -6004,6 +6985,75 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@node-redis/client": { + "version": "file:packages/client", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-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.4.0", + "@typescript-eslint/parser": "^5.4.0", + "cluster-key-slot": "1.1.0", + "eslint": "^8.2.0", + "generic-pool": "3.8.2", + "nyc": "^15.1.0", + "redis-parser": "3.0.0", + "release-it": "^14.11.7", + "sinon": "^12.0.1", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typedoc": "^0.22.9", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.6", + "typescript": "^4.4.4", + "yallist": "4.0.0" + } + }, + "@node-redis/json": { + "version": "file:packages/json", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } + }, + "@node-redis/search": { + "version": "file:packages/search", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } + }, + "@node-redis/test-utils": { + "version": "file:packages/test-utils", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.7", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4", + "yargs": "^17.2.1" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6246,6 +7296,12 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "dev": true }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, "@types/keyv": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", @@ -6262,9 +7318,9 @@ "dev": true }, "@types/node": { - "version": "16.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz", - "integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==", + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", "dev": true }, "@types/parse-json": { @@ -6273,36 +7329,144 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "@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", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/sinon": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.6.tgz", + "integrity": "sha512-6EF+wzMWvBNeGrfP3Nx60hhx+FfwSg1JJBLAAP/IdIUq0EYkqCYf70VT3PhuhPX9eLD+Dp+lNdpb/ZeHG8Yezg==", + "dev": true, + "requires": { + "@sinonjs/fake-timers": "^7.1.0" + } + }, + "@types/yallist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", + "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.5.tgz", + "integrity": "sha512-4HNq144yhaVjJs+ON6A07NEoi9Hh0Rhl/jI9Nt/l/YRjt+T6St/QK3meFARWZ8IgkzoD1LC0PdTdJenlQQi2WQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz", + "integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "5.4.0", + "@typescript-eslint/scope-manager": "5.4.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz", + "integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==", "dev": true, "requires": { - "@types/node": "*" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" } }, - "@types/sinon": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.4.tgz", - "integrity": "sha512-fOYjrxQv8zJsqOY6V6ecP4eZhQBxtY80X0er1VVnUIAIZo74jHm8e1vguG5Yt4Iv8W2Wr7TgibB8MfRe32k9pA==", + "@typescript-eslint/parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz", + "integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==", "dev": true, "requires": { - "@sinonjs/fake-timers": "^7.1.0" + "@typescript-eslint/scope-manager": "5.4.0", + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/typescript-estree": "5.4.0", + "debug": "^4.3.2" } }, - "@types/which": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz", - "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==", - "dev": true + "@typescript-eslint/scope-manager": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz", + "integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0" + } }, - "@types/yallist": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", - "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", + "@typescript-eslint/types": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz", + "integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==", "dev": true }, + "@typescript-eslint/typescript-estree": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz", + "integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "@typescript-eslint/visitor-keys": "5.4.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz", + "integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.4.0", + "eslint-visitor-keys": "^3.0.0" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -6315,6 +7479,13 @@ "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", "dev": true }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", @@ -6331,6 +7502,18 @@ "indent-string": "^4.0.0" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -6353,14 +7536,6 @@ "dev": true, "requires": { "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } } }, "ansi-regex": { @@ -6487,12 +7662,6 @@ "wrap-ansi": "^7.0.0" }, "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -6527,16 +7696,16 @@ "dev": true }, "browserslist": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.3.tgz", - "integrity": "sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", + "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001264", - "electron-to-chromium": "^1.3.857", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.77", - "picocolors": "^0.2.1" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "buffer": { @@ -6616,15 +7785,15 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", "dev": true }, "caniuse-lite": { - "version": "1.0.30001265", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", - "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", + "version": "1.0.30001280", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001280.tgz", + "integrity": "sha512-kFXwYvHe5rix25uwueBxC569o53J6TpnGu0BEEn+6Lhl2vsnAumRFWEBhDft1fwyo6m1r4i+RqA4+163FpeFcA==", "dev": true }, "chalk": { @@ -6635,17 +7804,6 @@ "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "chardet": { @@ -6797,6 +7955,14 @@ "dev": true, "requires": { "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "cosmiconfig": { @@ -6842,14 +8008,6 @@ "dev": true, "requires": { "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "decamelize": { @@ -6887,6 +8045,12 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -6948,6 +8112,15 @@ "path-type": "^4.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -6964,9 +8137,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.864", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", - "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "version": "1.3.897", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.897.tgz", + "integrity": "sha512-nRNZhAZ7hVCe75jrCUG7xLOqHMwloJMj6GEXEzY4OMahRGgwerAo+ls/qbqUwFH+E20eaSncKkQ4W8KP5SOiAg==", "dev": true }, "emoji-regex": { @@ -6984,6 +8157,15 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -7012,17 +8194,198 @@ "dev": true }, "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.2.0.tgz", + "integrity": "sha512-erw7XmM+CLxTOickrimJ1SiF55jiNlVSp2qqm0NuBWPtHYQCegD5ZMaW0c3i5ytPqL+SSLaCxdvQXFPLJn+ABw==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.0.4", + "@humanwhocodes/config-array": "^0.6.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^6.0.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.2.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-6.0.0.tgz", + "integrity": "sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", "dev": true }, + "espree": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", + "integrity": "sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==", + "dev": true, + "requires": { + "acorn": "^8.5.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.0.0" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -7051,6 +8414,12 @@ "tmp": "^0.0.33" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", @@ -7064,6 +8433,18 @@ "micromatch": "^4.0.4" } }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -7080,14 +8461,15 @@ "dev": true, "requires": { "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" } }, "fill-range": { @@ -7132,6 +8514,22 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -7178,6 +8576,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "generic-pool": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", @@ -7238,9 +8642,9 @@ } }, "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7270,10 +8674,21 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } }, "globby": { "version": "11.0.4", @@ -7376,6 +8791,14 @@ "requires": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "he": { @@ -7428,9 +8851,9 @@ "dev": true }, "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", "dev": true }, "import-cwd": { @@ -7450,14 +8873,6 @@ "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } } }, "import-from": { @@ -7467,6 +8882,14 @@ "dev": true, "requires": { "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } } }, "import-lazy": { @@ -7562,9 +8985,9 @@ } }, "is-core-module": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", - "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "dev": true, "requires": { "has": "^1.0.3" @@ -7710,9 +9133,9 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true }, "istanbul-lib-hook": { @@ -7734,6 +9157,14 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "istanbul-lib-processinfo": { @@ -7749,6 +9180,14 @@ "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "istanbul-lib-report": { @@ -7760,23 +9199,12 @@ "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -7793,9 +9221,9 @@ } }, "istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.5.tgz", + "integrity": "sha512-5+19PlhnGabNWB7kOFnuxT8H3T/iIyQzIbQMxXsURmmvKg86P2sbkrGOT77VnHw0Qr0gc2XzRaRfMZYYbSQCJQ==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -7835,6 +9263,18 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -7857,9 +9297,9 @@ "dev": true }, "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", + "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", "dev": true, "requires": { "json-buffer": "3.0.1" @@ -7874,6 +9314,16 @@ "package-json": "^6.3.0" } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -7907,6 +9357,12 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -7924,20 +9380,12 @@ "dev": true }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } + "yallist": "^4.0.0" } }, "lunr": { @@ -7959,6 +9407,14 @@ "dev": true, "requires": { "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "make-error": { @@ -7968,9 +9424,9 @@ "dev": true }, "marked": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.7.tgz", - "integrity": "sha512-ctKqbnLuNbsHbI26cfMyOlKgXGfl1orOv1AvWWDX7AkgfMOwCWvmuYc+mVLeWhQ9W6hdWVBynOs96VkcscKo0Q==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.8.tgz", + "integrity": "sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==", "dev": true }, "merge-stream": { @@ -8038,9 +9494,9 @@ "dev": true }, "mocha": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.2.tgz", - "integrity": "sha512-ta3LtJ+63RIBP03VBjMGtSqbe6cWXRejF9SyM9Zyli1CKZJZ+vfCTj3oW24V7wAphMJdpOFLoMI3hjJ1LWbs0w==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", + "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -8067,12 +9523,76 @@ "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "glob": { + "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", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } } }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "mute-stream": { @@ -8087,6 +9607,12 @@ "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -8124,9 +9650,9 @@ } }, "node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", "dev": true, "requires": { "whatwg-url": "^5.0.0" @@ -8142,9 +9668,9 @@ } }, "node-releases": { - "version": "1.1.77", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", - "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", "dev": true }, "normalize-path": { @@ -8203,6 +9729,12 @@ "yargs": "^15.0.2" }, "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -8251,6 +9783,12 @@ "p-limit": "^2.2.0" } }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -8330,6 +9868,23 @@ "dev": true, "requires": { "lru-cache": "^5.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, "open": { @@ -8342,6 +9897,20 @@ "is-wsl": "^2.1.1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -8573,6 +10142,12 @@ "dev": true } } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -8661,9 +10236,9 @@ "dev": true }, "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "picomatch": { @@ -8720,6 +10295,12 @@ } } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -8735,6 +10316,12 @@ "fromentries": "^1.2.0" } }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "protocols": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", @@ -8751,6 +10338,12 @@ "once": "^1.3.1" } }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, "pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -8819,12 +10412,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true } } }, @@ -8870,6 +10457,12 @@ "redis-errors": "^1.0.0" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "registry-auth-token": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", @@ -8889,9 +10482,9 @@ } }, "release-it": { - "version": "14.11.6", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.11.6.tgz", - "integrity": "sha512-6BNcuzFZHThBUBJ/xYw/bxZ+58CAwrwf1zgmjq2Ibl3nlDZbjphHG6iqxkJu7mZ8TIWs6NjloEAhqpjeXoN//Q==", + "version": "14.11.7", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.11.7.tgz", + "integrity": "sha512-m4p9+x6AEQPczc96Jyg6dGFeovpJVgRCtA1lxeIgTmQVt9dutYPkkjZeJngZgUJ17/Lb1bx6ZzW2qsKmopKnbQ==", "dev": true, "requires": { "@iarna/toml": "2.2.5", @@ -8923,38 +10516,6 @@ "uuid": "8.3.2", "yaml": "1.10.2", "yargs-parser": "20.2.9" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } } }, "release-zalgo": { @@ -8995,9 +10556,9 @@ "dev": true }, "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "responselike": { @@ -9065,9 +10626,9 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "safer-buffer": { @@ -9077,10 +10638,13 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "semver-diff": { "version": "3.1.1", @@ -9089,6 +10653,14 @@ "dev": true, "requires": { "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "serialize-javascript": { @@ -9133,9 +10705,9 @@ } }, "shiki": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.11.tgz", - "integrity": "sha512-tjruNTLFhU0hruCPoJP0y+B9LKOmcqUhTpxn7pcJB3fa+04gFChuEmxmrUfOJ7ZO6Jd+HwMnDHgY3lv3Tqonuw==", + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.12.tgz", + "integrity": "sha512-VXcROdldv0/Qu0w2XvzU4IrvTeBNs/Kj/FCmtcEXGz7Tic/veQzliJj6tEiAgoKianhQstpYmbPDStHU5Opqcw==", "dev": true, "requires": { "jsonc-parser": "^3.0.0", @@ -9161,26 +10733,26 @@ "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": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "@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": { - "has-flag": "^4.0.0" + "@sinonjs/commons": "^1.7.0" } } } @@ -9254,14 +10826,6 @@ "dev": true, "requires": { "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } } }, "string-width": { @@ -9297,15 +10861,15 @@ "dev": true }, "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -9322,6 +10886,12 @@ "minimatch": "^3.0.4" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9365,9 +10935,9 @@ "dev": true }, "ts-node": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.0.tgz", - "integrity": "sha512-RYIy3i8IgpFH45AX4fQHExrT8BxDeKTdC83QFJkNzkvt8uFB6QJ8XMyhynYiKMLxt9a7yuXaDBZNOYS3XjDcYw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", "dev": true, "requires": { "@cspotcode/source-map-support": "0.7.0", @@ -9398,6 +10968,32 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", "dev": true }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -9405,9 +11001,9 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, "typedarray-to-buffer": { @@ -9420,32 +11016,16 @@ } }, "typedoc": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.5.tgz", - "integrity": "sha512-KFrWGU1iKiTGw0RcyjLNYDmhd7uICU14HgBNPmFKY/sT4Pm/fraaLyWyisst9vGTUAKxqibqoDITR7+ZcAkhHg==", + "version": "0.22.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.9.tgz", + "integrity": "sha512-84PjudoXVcap6bwdZFbYIUWlgdz/iLV09ZHwrCzhtHWXaDQG6mlosJ8te6DSThuRkRvQjp46HO+qY/P7Gpm78g==", "dev": true, "requires": { "glob": "^7.2.0", "lunr": "^2.3.9", - "marked": "^3.0.4", + "marked": "^3.0.8", "minimatch": "^3.0.4", - "shiki": "^0.9.11" - }, - "dependencies": { - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } + "shiki": "^0.9.12" } }, "typedoc-github-wiki-theme": { @@ -9456,24 +11036,24 @@ "requires": {} }, "typedoc-plugin-markdown": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.3.tgz", - "integrity": "sha512-rWiHbEIe0oZetDIsBR24XJVxGOJ91kDcHoj2KhFKxCLoJGX659EKBQkHne9QJ4W2stGhu1fRgFyQaouSBnxukA==", + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.11.6.tgz", + "integrity": "sha512-CV1BuxL7HR/EE1ctnPXOWzf4/Exl0FzkwtFVYaKTVWTnD/dkFLgABOfWuOL4lPmzLUOsAL85pmq+/PB6cdRppw==", "dev": true, "requires": { "handlebars": "^4.7.7" } }, "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true }, "uglify-js": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", - "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", "dev": true, "optional": true }, @@ -9528,27 +11108,18 @@ "requires": { "ci-info": "^2.0.0" } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } } } }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -9571,9 +11142,15 @@ "dev": true }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "vscode-textmate": { @@ -9674,6 +11251,12 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -9739,9 +11322,9 @@ "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", "dev": true, "requires": { "cliui": "^7.0.2", @@ -9754,9 +11337,9 @@ } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true }, "yargs-unparser": { @@ -9771,12 +11354,6 @@ "is-plain-obj": "^2.1.0" }, "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", diff --git a/package.json b/package.json index 7f8720f47bf..49339e44d26 100644 --- a/package.json +++ b/package.json @@ -1,66 +1,37 @@ { "name": "redis", - "version": "4.0.0-rc.3", - "description": "A high performance Redis client.", - "keywords": [ - "database", - "redis", - "pubsub" - ], - "author": "Matt Ranney ", - "contributors": [ - { - "name": "Mike Diarmid (Salakar)", - "url": "https://github.com/salakar" - }, - { - "name": "Ruben Bridgewater (BridgeAR)", - "url": "https://github.com/BridgeAR" - } - ], + "version": "4.0.0-rc.4", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", + "workspaces": [ + "./packages/*" + ], "scripts": { - "test": "nyc -r text-summary -r html mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "test": "npm run test -ws --if-present", + "build:client": "npm run build -w ./packages/client", + "build:test-utils": "npm run build -w ./packages/test-utils", + "build:tests-tools": "npm run build:client && npm run build:test-utils", + "build:modules": "find ./packages -mindepth 1 -maxdepth 1 -type d ! -name 'client' ! -name 'test-utils' -exec npm run build -w {} \\;", "build": "tsc", - "documentation": "typedoc" + "build-all": "npm run build:client && npm run build:test-utils && npm run build:modules && npm run build" }, "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" + "@node-redis/client": "^1.0.0-rc.0", + "@node-redis/json": "^1.0.0-rc.0", + "@node-redis/search": "^1.0.0-rc.0" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.10.3", - "@types/sinon": "^10.0.4", - "@types/which": "^2.0.1", - "@types/yallist": "^4.0.1", - "mocha": "^9.1.2", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.3.0", - "typedoc": "^0.22.5", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.3", - "which": "^2.0.2" - }, - "engines": { - "node": ">=12" + "release-it": "^14.11.7", + "typescript": "^4.4.4" }, "repository": { "type": "git", - "url": "git://github.com/NodeRedis/node-redis.git" + "url": "git://github.com/redis/node-redis.git" }, "bugs": { - "url": "https://github.com/NodeRedis/node-redis/issues" + "url": "https://github.com/redis/node-redis/issues" }, - "homepage": "https://github.com/NodeRedis/node-redis" + "homepage": "https://github.com/redis/node-redis" } diff --git a/packages/client/.eslintrc.json b/packages/client/.eslintrc.json new file mode 100644 index 00000000000..4536bc31338 --- /dev/null +++ b/packages/client/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "semi": [2, "always"] + } + } diff --git a/packages/client/.gitignore b/packages/client/.gitignore new file mode 100644 index 00000000000..2d7ddbc106e --- /dev/null +++ b/packages/client/.gitignore @@ -0,0 +1 @@ +documentation/ diff --git a/packages/client/.npmignore b/packages/client/.npmignore new file mode 100644 index 00000000000..d064e1d0db6 --- /dev/null +++ b/packages/client/.npmignore @@ -0,0 +1,10 @@ +.nyc_output/ +coverage/ +documentation/ +lib/ +.eslintrc.json +.nycrc.json +.release-it.json +dump.rdb +index.ts +tsconfig.json diff --git a/packages/client/.nycrc.json b/packages/client/.nycrc.json new file mode 100644 index 00000000000..dd42463d9cb --- /dev/null +++ b/packages/client/.nycrc.json @@ -0,0 +1,4 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "exclude": ["**/*.spec.ts", "lib/test-utils.ts", "examples/*"] +} diff --git a/packages/client/.release-it.json b/packages/client/.release-it.json new file mode 100644 index 00000000000..035124348ca --- /dev/null +++ b/packages/client/.release-it.json @@ -0,0 +1,10 @@ +{ + "git": { + "tagName": "client@${version}", + "commitMessage": "Release ${tagName}", + "tagAnnotation": "Release ${tagName}" + }, + "npm": { + "publishArgs": ["--access", "public"] + } +} diff --git a/CHANGELOG.md b/packages/client/CHANGELOG.md similarity index 98% rename from CHANGELOG.md rename to packages/client/CHANGELOG.md index d0095714010..21b7177e8b6 100644 --- a/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -2,7 +2,7 @@ ## v4.0.0 -This version is a major change and refactor, adding modern JavaScript capabilities and multiple breaking changes. See the [migration guide](./docs/v3-to-v4.md) for tips on how to upgrade. +This version is a major change and refactor, adding modern JavaScript capabilities and multiple breaking changes. See the [migration guide](../../docs/v3-to-v4.md) for tips on how to upgrade. ### Breaking Changes @@ -17,12 +17,35 @@ This version is a major change and refactor, adding modern JavaScript capabiliti - Added support for Promises - Added built-in TypeScript declaration files enabling code completion -- Added support for [clustering](./README.md#cluster) -- Added idiomatic arguments and responses to [Redis commands](./README.md#redis-commands) -- Added full support for [Lua Scripts](./README.md#lua-scripts) -- Added support for [SCAN iterators](./README.md#scan-iterator) +- Added support for [clustering](../../.github/README.md#cluster) +- Added idiomatic arguments and responses to [Redis commands](../../.github/README.md#redis-commands) +- Added full support for [Lua Scripts](../../.github/README.md#lua-scripts) +- Added support for [SCAN iterators](../../.github/README.md#scan-iterator) - Added the ability to extend Node Redis with Redis Module commands +## v3.1.2 + +### Fixes + +- Exclude unnecessary files from tarball + +## v3.1.1 + +### Enhancements + +- Upgrade node and dependencies + +### Fixes + +- Fix a potential exponential regex in monitor mode + +## v3.1.0 - 31 Mar, 2021 + +### Enhancements + +- Upgrade node and dependencies and redis-commands to support Redis 6 +- Add support for Redis 6 `auth pass [user]` + ## v3.0.0 - 09 Feb, 2020 This version is mainly a release to distribute all the unreleased changes on master since 2017 and additionally removes diff --git a/packages/client/README.md b/packages/client/README.md new file mode 100644 index 00000000000..37c326fc42e --- /dev/null +++ b/packages/client/README.md @@ -0,0 +1,2 @@ +# @node-redis/client +The sources and docs for this package are in the main [node-redis](https://github.com/redis/node-redis) repo. diff --git a/packages/client/index.ts b/packages/client/index.ts new file mode 100644 index 00000000000..408cbe3b996 --- /dev/null +++ b/packages/client/index.ts @@ -0,0 +1,10 @@ +import RedisClient from './lib/client'; +import RedisCluster from './lib/cluster'; + +export const createClient = RedisClient.create; + +export const commandOptions = RedisClient.commandOptions; + +export const createCluster = RedisCluster.create; + +export { defineScript } from './lib/lua-script'; diff --git a/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts similarity index 92% rename from lib/client/commands-queue.ts rename to packages/client/lib/client/commands-queue.ts index 791c7638bad..4fcae1e8b63 100644 --- a/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,25 +1,29 @@ -import LinkedList from 'yallist'; -import RedisParser from 'redis-parser'; +import * as LinkedList from 'yallist'; import { AbortError } from '../errors'; -import { RedisCommandRawReply } from '../commands'; +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; - signal?: any; // TODO: `AbortSignal` type is incorrect + signal?: AbortSignal; } interface CommandWaitingToBeSent extends CommandWaitingForReply { - args: Array; + args: RedisCommandArguments; chainId?: symbol; abort?: { - signal: any; // TODO: `AbortSignal` type is incorrect + signal: AbortSignal; listener(): void; }; } interface CommandWaitingForReply { - resolve(reply?: any): void; + resolve(reply?: unknown): void; reject(err: Error): void; channelsCounter?: number; bufferMode?: boolean; @@ -107,7 +111,7 @@ export default class RedisCommandsQueue { this.#maxLength = maxLength; } - addCommand(args: Array, options?: QueueCommandOptions, bufferMode?: boolean): Promise { + addCommand(args: RedisCommandArguments, options?: QueueCommandOptions, bufferMode?: boolean): Promise { if (this.#pubSubState.subscribing || this.#pubSubState.subscribed) { return Promise.reject(new Error('Cannot send commands in PubSub mode')); } else if (this.#maxLength && this.#waitingToBeSent.length + this.#waitingForReply.length >= this.#maxLength) { @@ -135,7 +139,8 @@ export default class RedisCommandsQueue { signal: options.signal, listener }; - options.signal.addEventListener('abort', listener, { + // AbortSignal type is incorrent + (options.signal as any).addEventListener('abort', listener, { once: true }); } @@ -246,7 +251,7 @@ export default class RedisCommandsQueue { ]); } - getCommandToSend(): Array | undefined { + getCommandToSend(): RedisCommandArguments | undefined { const toSend = this.#waitingToBeSent.shift(); if (toSend) { diff --git a/lib/client/commands.ts b/packages/client/lib/client/commands.ts similarity index 99% rename from lib/client/commands.ts rename to packages/client/lib/client/commands.ts index c34f34be4fa..de901152f11 100644 --- a/lib/client/commands.ts +++ b/packages/client/lib/client/commands.ts @@ -229,5 +229,5 @@ export default { UNWATCH, unwatch: UNWATCH, WAIT, - wait: WAIT, + wait: WAIT }; diff --git a/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts similarity index 51% rename from lib/client/index.spec.ts rename to packages/client/lib/client/index.spec.ts index e98814d0582..3f0bca45e27 100644 --- a/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -1,11 +1,12 @@ -import { strict as assert, AssertionError } from 'assert'; -import { once } from 'events'; -import { itWithClient, TEST_REDIS_SERVERS, TestRedisServers, waitTillBeenCalled, isRedisVersionGreaterThan } from '../test-utils'; -import RedisClient from '.'; -import { AbortError, ClientClosedError, ConnectionTimeoutError, WatchError } from '../errors'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; +import RedisClient, { ClientLegacyCommandArguments, RedisClientType } from '.'; +import { RedisClientMultiCommandType } from './multi-command'; +import { RedisCommandArguments, RedisCommandRawReply, RedisModules, RedisScripts } from '../commands'; +import { AbortError, ClientClosedError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; import { spy } from 'sinon'; -import { RedisNetSocketOptions } from '../client/socket'; +import { once } from 'events'; export const SQUARE_SCRIPT = defineScript({ NUMBER_OF_KEYS: 0, @@ -75,204 +76,242 @@ describe('Client', () => { } ); }); - - it('createClient with url', async () => { - const client = RedisClient.create({ - url: `redis://localhost:${(TEST_REDIS_SERVERS[TestRedisServers.OPEN].socket as RedisNetSocketOptions)!.port!.toString()}/1` - }); - - await client.connect(); - - try { - assert.equal( - await client.ping(), - 'PONG' - ); - } finally { - await client.disconnect(); - } - }) }); describe('authentication', () => { - itWithClient(TestRedisServers.PASSWORD, 'Client should be authenticated', async client => { + testUtils.testWithClient('Client should be authenticated', async client => { assert.equal( await client.ping(), 'PONG' ); - }); - - it('should not retry connecting if failed due to wrong auth', async () => { - const client = RedisClient.create({ - ...TEST_REDIS_SERVERS[TestRedisServers.PASSWORD], - password: 'wrongpassword' - }); + }, GLOBAL.SERVERS.PASSWORD); + + testUtils.testWithClient('should not retry connecting if failed due to wrong auth', async client => { + let message; + if (testUtils.isVersionGreaterThan([6, 2])) { + message = 'WRONGPASS invalid username-password pair or user is disabled.'; + } else if (testUtils.isVersionGreaterThan([6])) { + message = 'WRONGPASS invalid username-password pair'; + } else { + message = 'ERR invalid password'; + } await assert.rejects( client.connect(), - { - message: isRedisVersionGreaterThan([6]) ? - 'WRONGPASS invalid username-password pair or user is disabled.' : - 'ERR invalid password' - } + { message } ); assert.equal(client.isOpen, false); + }, { + ...GLOBAL.SERVERS.PASSWORD, + clientOptions: { + password: 'wrongpassword' + }, + disableClientSetup: true }); - }); - describe('legacyMode', () => { - const client = RedisClient.create({ - ...TEST_REDIS_SERVERS[TestRedisServers.OPEN], - scripts: { - square: SQUARE_SCRIPT + testUtils.testWithClient('should execute AUTH before SELECT', async client => { + assert.equal( + (await client.clientInfo()).db, + 2 + ); + }, { + ...GLOBAL.SERVERS.PASSWORD, + clientOptions: { + ...GLOBAL.SERVERS.PASSWORD.clientOptions, + database: 2 }, - legacyMode: true + minimumDockerVersion: [6, 2] }); + }); - before(() => client.connect()); - afterEach(() => client.v4.flushAll()); - after(() => client.disconnect()); - - it('client.sendCommand should call the callback', done => { - (client as any).sendCommand('PING', (err?: Error, reply?: string) => { - if (err) { - return done(err); - } + describe('legacyMode', () => { + function sendCommandAsync(client: RedisClientType, args: RedisCommandArguments): Promise { + return new Promise((resolve, reject) => { + (client as any).sendCommand(args, (err: Error | undefined, reply: RedisCommandRawReply) => { + if (err) return reject(err); - try { - assert.equal(reply, 'PONG'); - done(); - } catch (err) { - done(err); - } + resolve(reply); + }); }); + } + + testUtils.testWithClient('client.sendCommand should call the callback', async client => { + assert.equal( + await sendCommandAsync(client, ['PING']), + 'PONG' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.sendCommand should work without callback', async () => { - (client as any).sendCommand('PING'); + testUtils.testWithClient('client.sendCommand should work without callback', async client => { + client.sendCommand(['PING']); await client.v4.ping(); // make sure the first command was replied + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.v4.sendCommand should return a promise', async () => { + testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { assert.equal( await client.v4.sendCommand(['PING']), 'PONG' ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.{command} should accept vardict arguments', done => { - (client as any).set('a', 'b', (err?: Error, reply?: string) => { - if (err) { - return done(err); - } + function setAsync(client: RedisClientType, ...args: ClientLegacyCommandArguments): Promise { + return new Promise((resolve, reject) => { + (client as any).set(...args, (err: Error | undefined, reply: RedisCommandRawReply) => { + if (err) return reject(err); - try { - assert.equal(reply, 'OK'); - done(); - } catch (err) { - done(err); - } + resolve(reply); + }); }); - }); - - it('client.{command} should accept arguments array', done => { - (client as any).set(['a', 'b'], (err?: Error, reply?: string) => { - if (err) { - return done(err); - } + } - try { - assert.equal(reply, 'OK'); - done(); - } catch (err) { - done(err); - } - }); + testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { + assert.equal( + await setAsync(client, 'a', 'b'), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.{command} should accept mix of strings and array of strings', done => { - (client as any).set(['a'], 'b', ['XX'], (err?: Error, reply?: string) => { - if (err) { - return done(err); - } + testUtils.testWithClient('client.{command} should accept arguments array', async client => { + assert.equal( + await setAsync(client, ['a', 'b']), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } + }); - try { - assert.equal(reply, null); - done(); - } catch (err) { - done(err); - } - }); + testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { + assert.equal( + await setAsync(client, ['a'], 'b', ['EX', 1]), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.multi.ping.exec should call the callback', done => { - (client as any).multi() - .ping() - .exec((err?: Error, reply?: string) => { - if (err) { - return done(err); - } + function multiExecAsync(multi: RedisClientMultiCommandType): Promise> { + return new Promise((resolve, reject) => { + (multi as any).exec((err: Error | undefined, replies: Array) => { + if (err) return reject(err); - try { - assert.deepEqual(reply, ['PONG']); - done(); - } catch (err) { - done(err); - } + resolve(replies); }); + }); + } + + testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { + assert.deepEqual( + await multiExecAsync( + client.multi().ping() + ), + ['PONG'] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.multi.ping.exec should work without callback', async () => { - (client as any).multi() + testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { + client.multi() .ping() .exec(); await client.v4.ping(); // make sure the first command was replied + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.multi.ping.v4.ping.v4.exec should return a promise', async () => { + testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { assert.deepEqual( - await ((client as any).multi() + await client.multi() .ping() .v4.ping() - .v4.exec()), + .v4.exec(), ['PONG', 'PONG'] ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true + } }); - it('client.{script} should return a promise', async () => { - assert.equal(await client.square(2), 4); + testUtils.testWithClient('client.{script} should return a promise', async client => { + assert.equal( + await client.square(2), + 4 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + legacyMode: true, + scripts: { + square: SQUARE_SCRIPT + } + } }); }); describe('events', () => { - it('connect, ready, end', async () => { - const client = RedisClient.create(TEST_REDIS_SERVERS[TestRedisServers.OPEN]); - + testUtils.testWithClient('connect, ready, end', async client => { await Promise.all([ - client.connect(), once(client, 'connect'), - once(client, 'ready') + once(client, 'ready'), + client.connect() ]); await Promise.all([ - client.disconnect(), - once(client, 'end') + once(client, 'end'), + client.disconnect() ]); + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true }); }); describe('sendCommand', () => { - itWithClient(TestRedisServers.OPEN, 'PING', async client => { + testUtils.testWithClient('PING', async client => { assert.equal(await client.sendCommand(['PING']), 'PONG'); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'bufferMode', async client => { + testUtils.testWithClient('bufferMode', async client => { assert.deepEqual( await client.sendCommand(['PING'], undefined, true), Buffer.from('PONG') ); - }); + }, GLOBAL.SERVERS.OPEN); describe('AbortController', () => { before(function () { @@ -281,13 +320,13 @@ describe('Client', () => { } }); - itWithClient(TestRedisServers.OPEN, 'success', async client => { + testUtils.testWithClient('success', async client => { await client.sendCommand(['PING'], { signal: new AbortController().signal }); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'AbortError', client => { + testUtils.testWithClient('AbortError', client => { const controller = new AbortController(); controller.abort(); @@ -297,12 +336,12 @@ describe('Client', () => { }), AbortError ); - }); + }, GLOBAL.SERVERS.OPEN); }); }); describe('multi', () => { - itWithClient(TestRedisServers.OPEN, 'simple', async client => { + testUtils.testWithClient('simple', async client => { assert.deepEqual( await client.multi() .ping() @@ -311,44 +350,35 @@ describe('Client', () => { .exec(), ['PONG', 'OK', 'value'] ); - }); - - itWithClient(TestRedisServers.OPEN, 'should reject the whole chain on error', client => { - client.on('error', () => { - // ignore errors - }); + }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('should reject the whole chain on error', client => { return assert.rejects( client.multi() .ping() - .addCommand(['DEBUG', 'RESTART']) + .addCommand(['INVALID COMMAND']) .ping() .exec() ); - }); + }, GLOBAL.SERVERS.OPEN); - it('with script', async () => { - const client = RedisClient.create({ + testUtils.testWithClient('with script', async client => { + assert.deepEqual( + await client.multi() + .square(2) + .exec(), + [4] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { scripts: { square: SQUARE_SCRIPT } - }); - - await client.connect(); - - try { - assert.deepEqual( - await client.multi() - .square(2) - .exec(), - [4] - ); - } finally { - await client.disconnect(); } }); - itWithClient(TestRedisServers.OPEN, 'WatchError', async client => { + testUtils.testWithClient('WatchError', async client => { await client.watch('key'); await client.set( @@ -365,39 +395,40 @@ describe('Client', () => { .exec(), WatchError ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'execAsPipeline', async client => { + testUtils.testWithClient('execAsPipeline', async client => { assert.deepEqual( await client.multi() .ping() .exec(true), ['PONG'] ); - }); + }, GLOBAL.SERVERS.OPEN); }); - it('scripts', async () => { - const client = RedisClient.create({ + testUtils.testWithClient('scripts', async client => { + assert.equal( + await client.square(2), + 4 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { scripts: { square: SQUARE_SCRIPT } - }); - - await client.connect(); - - try { - assert.equal( - await client.square(2), - 4 - ); - } finally { - await client.disconnect(); } }); - it('modules', async () => { - const client = RedisClient.create({ + testUtils.testWithClient('modules', async client => { + assert.equal( + await client.module.echo('message'), + 'message' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { modules: { module: { echo: { @@ -410,21 +441,10 @@ describe('Client', () => { } } } - }); - - await client.connect(); - - try { - assert.equal( - await client.module.echo('message'), - 'message' - ); - } finally { - await client.disconnect(); } }); - itWithClient(TestRedisServers.OPEN, 'executeIsolated', async client => { + testUtils.testWithClient('executeIsolated', async client => { await client.sendCommand(['CLIENT', 'SETNAME', 'client']); assert.equal( @@ -433,35 +453,35 @@ describe('Client', () => { ), null ); - }); - - itWithClient(TestRedisServers.OPEN, 'should reconnect after DEBUG RESTART', async client => { - client.on('error', () => { - // ignore errors - }); - - await client.sendCommand(['CLIENT', 'SETNAME', 'client']); - await assert.rejects(client.sendCommand(['DEBUG', 'RESTART'])); - assert.ok(await client.sendCommand(['CLIENT', 'GETNAME']) === null); - }); + }, GLOBAL.SERVERS.OPEN); + + async function killClient(client: RedisClientType): Promise { + const onceErrorPromise = once(client, 'error'); + await client.sendCommand(['QUIT']); + await Promise.all([ + onceErrorPromise, + assert.rejects(client.ping(), SocketClosedUnexpectedlyError) + ]); + } - itWithClient(TestRedisServers.OPEN, 'should SELECT db after reconnection', async client => { - client.on('error', () => { - // ignore errors - }); + testUtils.testWithClient('should reconnect when socket disconnects', async client => { + await killClient(client); + await assert.doesNotReject(client.ping()); + }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('should remember selected db', async client => { await client.select(1); - await assert.rejects(client.sendCommand(['DEBUG', 'RESTART'])); + await killClient(client); assert.equal( (await client.clientInfo()).db, 1 ); }, { - // because of CLIENT INFO - minimumRedisVersion: [6, 2] + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] // CLIENT INFO }); - itWithClient(TestRedisServers.OPEN, 'scanIterator', async client => { + testUtils.testWithClient('scanIterator', async client => { const promises = [], keys = new Set(); for (let i = 0; i < 100; i++) { @@ -478,9 +498,9 @@ describe('Client', () => { } assert.deepEqual(keys, results); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'hScanIterator', async client => { + testUtils.testWithClient('hScanIterator', async client => { const hash: Record = {}; for (let i = 0; i < 100; i++) { hash[i.toString()] = i.toString(); @@ -494,9 +514,9 @@ describe('Client', () => { } assert.deepEqual(hash, results); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'sScanIterator', async client => { + testUtils.testWithClient('sScanIterator', async client => { const members = new Set(); for (let i = 0; i < 100; i++) { members.add(i.toString()); @@ -510,9 +530,9 @@ describe('Client', () => { } assert.deepEqual(members, results); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'zScanIterator', async client => { + testUtils.testWithClient('zScanIterator', async client => { const members = []; for (let i = 0; i < 100; i++) { members.push({ @@ -538,9 +558,9 @@ describe('Client', () => { [...map.entries()].sort(sort), members.map(member => [member.value, member.score]).sort(sort) ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'PubSub', async publisher => { + testUtils.testWithClient('PubSub', async publisher => { const subscriber = publisher.duplicate(); await subscriber.connect(); @@ -603,49 +623,59 @@ describe('Client', () => { } finally { await subscriber.disconnect(); } - }); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('ConnectionTimeoutError', async client => { + const promise = assert.rejects(client.connect(), ConnectionTimeoutError), + start = process.hrtime.bigint(); - it('ConnectionTimeoutError', async () => { - const client = RedisClient.create({ + while (process.hrtime.bigint() - start < 1_000_000) { + // block the event loop for 1ms, to make sure the connection will timeout + } + + await promise; + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { socket: { - ...TEST_REDIS_SERVERS[TestRedisServers.OPEN], connectTimeout: 1 } - }); + }, + disableClientSetup: true + }); - try { - const promise = assert.rejects(client.connect(), ConnectionTimeoutError), - start = process.hrtime.bigint(); + testUtils.testWithClient('client.quit', async client => { + await client.connect(); - // block the event loop for 1ms, to make sure the connection will timeout - while (process.hrtime.bigint() - start < 1_000_000) {} + const pingPromise = client.ping(), + quitPromise = client.quit(); + assert.equal(client.isOpen, false); - await promise; - } catch (err) { - if (err instanceof AssertionError) { - await client.disconnect(); - } + const [ping] = await Promise.all([ + pingPromise, + assert.doesNotReject(quitPromise), + assert.rejects(client.ping(), ClientClosedError) + ]); - throw err; - } + assert.equal(ping, 'PONG'); + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true }); - it('client.quit', async () => { - const client = RedisClient.create(TEST_REDIS_SERVERS[TestRedisServers.OPEN]); - + testUtils.testWithClient('client.disconnect', async client => { await client.connect(); - try { - const quitPromise = client.quit(); - assert.equal(client.isOpen, false); - await Promise.all([ - quitPromise, - assert.rejects(client.ping(), ClientClosedError) - ]); - } finally { - if (client.isOpen) { - await client.disconnect(); - } - } + const pingPromise = client.ping(), + disconnectPromise = client.disconnect(); + assert.equal(client.isOpen, false); + await Promise.all([ + assert.rejects(pingPromise, DisconnectsClientError), + assert.doesNotReject(disconnectPromise), + assert.rejects(client.ping(), ClientClosedError) + ]); + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true }); }); diff --git a/lib/client/index.ts b/packages/client/lib/client/index.ts similarity index 80% rename from lib/client/index.ts rename to packages/client/lib/client/index.ts index 1a5384f509f..8802631eda1 100644 --- a/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -4,14 +4,14 @@ 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'; import { HScanTuple } from '../commands/HSCAN'; -import { encodeCommand, extendWithCommands, extendWithModulesAndScripts, transformCommandArguments, transformCommandReply } from '../commander'; +import { extendWithCommands, extendWithModulesAndScripts, LegacyCommandArguments, transformCommandArguments, transformCommandReply, transformLegacyCommandArguments } from '../commander'; import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; -import { ClientClosedError } from '../errors'; +import { ClientClosedError, DisconnectsClientError } from '../errors'; import { URL } from 'url'; export interface RedisClientOptions extends RedisPlugins { @@ -34,16 +34,16 @@ type WithCommands = { }; export type WithModules = { - [P in keyof M]: { + [P in keyof M as M[P] extends never ? never : P]: { [C in keyof M[P]]: RedisClientCommandSignature; }; }; export type WithScripts = { - [P in keyof S]: RedisClientCommandSignature; + [P in keyof S as S[P] extends never ? never : P]: RedisClientCommandSignature; }; -export type RedisClientType = +export type RedisClientType, S extends RedisScripts = Record> = RedisClient & WithCommands & WithModules & WithScripts; export type InstantiableRedisClient = @@ -53,12 +53,15 @@ export interface ClientCommandOptions extends QueueCommandOptions { isolated?: boolean; } +type ClientLegacyCallback = (err: Error | null, reply?: RedisCommandRawReply) => void; + +export type ClientLegacyCommandArguments = LegacyCommandArguments | [...LegacyCommandArguments, ClientLegacyCallback]; export default class RedisClient extends EventEmitter { static commandOptions(options: ClientCommandOptions): CommandOptions { return commandOptions(options); } - static extend(plugins?: RedisPlugins): InstantiableRedisClient { + static extend, S extends RedisScripts = Record>(plugins?: RedisPlugins): InstantiableRedisClient { const Client = extendWithModulesAndScripts({ BaseClass: RedisClient, modules: plugins?.modules, @@ -74,14 +77,14 @@ export default class RedisClient return Client; } - static create(options?: RedisClientOptions): RedisClientType { + static create, S extends RedisScripts = Record>(options?: RedisClientOptions): RedisClientType { return new (RedisClient.extend(options))(options); } - static parseURL(url: string): RedisClientOptions<{}, {}> { + static parseURL(url: string): RedisClientOptions, Record> { // https://www.iana.org/assignments/uri-schemes/prov/redis const { hostname, port, protocol, username, password, pathname } = new URL(url), - parsed: RedisClientOptions<{}, {}> = { + parsed: RedisClientOptions, Record> = { socket: { host: hostname } @@ -98,11 +101,11 @@ export default class RedisClient } if (username) { - parsed.username = username; + parsed.username = decodeURIComponent(username); } if (password) { - parsed.password = password; + parsed.password = decodeURIComponent(password); } if (pathname.length > 1) { @@ -177,28 +180,47 @@ export default class RedisClient #initiateSocket(): RedisSocket { const socketInitiator = async (): Promise => { - const v4Commands = this.#options?.legacyMode ? this.#v4 : this, - promises = []; + const promises = []; if (this.#selectedDB !== 0) { - promises.push(v4Commands.select(RedisClient.commandOptions({ asap: true }), this.#selectedDB)); + promises.push( + this.#queue.addCommand( + ['SELECT', this.#selectedDB.toString()], + { asap: true } + ) + ); } if (this.#options?.readonly) { - promises.push(v4Commands.readonly(RedisClient.commandOptions({ asap: true }))); + promises.push( + this.#queue.addCommand( + COMMANDS.READONLY.transformArguments(), + { asap: true } + ) + ); } if (this.#options?.username || this.#options?.password) { - promises.push(v4Commands.auth(RedisClient.commandOptions({ asap: true }), this.#options)); + promises.push( + this.#queue.addCommand( + COMMANDS.AUTH.transformArguments({ + username: this.#options.username, + password: this.#options.password ?? '' + }), + { asap: true } + ) + ); } const resubscribePromise = this.#queue.resubscribe(); if (resubscribePromise) { promises.push(resubscribePromise); - this.#tick(); } - await Promise.all(promises); + if (promises.length) { + this.#tick(true); + await Promise.all(promises); + } }; return new RedisSocket(socketInitiator, this.#options?.socket) @@ -213,6 +235,7 @@ export default class RedisClient this.#tick(); }) .on('reconnecting', () => this.emit('reconnecting')) + .on('drain', () => this.#tick()) .on('end', () => this.emit('end')); } @@ -224,11 +247,14 @@ export default class RedisClient if (!this.#options?.legacyMode) return; (this as any).#v4.sendCommand = this.#sendCommand.bind(this); - (this as any).sendCommand = (...args: Array): void => { - const callback = typeof args[args.length - 1] === 'function' ? args[args.length - 1] as Function : undefined, - actualArgs = !callback ? args : args.slice(0, -1); - this.#sendCommand(actualArgs.flat() as Array) - .then((reply: unknown) => { + (this as any).sendCommand = (...args: ClientLegacyCommandArguments): void => { + let callback: ClientLegacyCallback; + if (typeof args[args.length - 1] === 'function') { + callback = args.pop() as ClientLegacyCallback; + } + + this.#sendCommand(transformLegacyCommandArguments(args as LegacyCommandArguments)) + .then((reply: RedisCommandRawReply) => { if (!callback) return; // https://github.com/NodeRedis/node-redis#commands:~:text=minimal%20parsing @@ -297,9 +323,9 @@ export default class RedisClient } // using `#sendCommand` cause `sendCommand` is overwritten in legacy mode - async #sendCommand(args: RedisCommandArguments, options?: ClientCommandOptions, bufferMode?: boolean): Promise { + #sendCommand(args: RedisCommandArguments, options?: ClientCommandOptions, bufferMode?: boolean): Promise { if (!this.#socket.isOpen) { - throw new ClientClosedError(); + return Promise.reject(new ClientClosedError()); } if (options?.isolated) { @@ -313,7 +339,7 @@ export default class RedisClient const promise = this.#queue.addCommand(args, options, bufferMode); this.#tick(); - return await promise; + return promise; } async scriptsExecutor(script: RedisScript, args: Array): Promise> { @@ -400,33 +426,29 @@ export default class RedisClient QUIT(): Promise { return this.#socket.quit(() => { - const promise = this.#queue.addCommand(['QUIT']); + const quitPromise = this.#queue.addCommand(['QUIT']); this.#tick(); - return promise; + return Promise.all([ + quitPromise, + this.#destroyIsolationPool() + ]); }); } quit = this.QUIT; - #tick(): void { - if (!this.#socket.isSocketExists) { + #tick(force = false): void { + if (this.#socket.writableNeedDrain || (!force && !this.#socket.isReady)) { return; } this.#socket.cork(); - while (true) { + while (!this.#socket.writableNeedDrain) { const args = this.#queue.getCommandToSend(); if (args === undefined) break; - let writeResult; - for (const toWrite of encodeCommand(args)) { - writeResult = this.#socket.write(toWrite); - } - - if (!writeResult) { - break; - } + this.#socket.writeCommand(args); } } @@ -463,7 +485,7 @@ export default class RedisClient for (const key of reply.keys) { yield key; } - } while (cursor !== 0) + } while (cursor !== 0); } async* hScanIterator(key: string, options?: ScanOptions): AsyncIterable { @@ -474,7 +496,7 @@ export default class RedisClient for (const tuple of reply.tuples) { yield tuple; } - } while (cursor !== 0) + } while (cursor !== 0); } async* sScanIterator(key: string, options?: ScanOptions): AsyncIterable { @@ -485,7 +507,7 @@ export default class RedisClient for (const member of reply.members) { yield member; } - } while (cursor !== 0) + } while (cursor !== 0); } async* zScanIterator(key: string, options?: ScanOptions): AsyncIterable { @@ -496,15 +518,13 @@ export default class RedisClient for (const member of reply.members) { yield member; } - } while (cursor !== 0) + } while (cursor !== 0); } async disconnect(): Promise { - this.#queue.flushAll(new Error('Disconnecting')); - await Promise.all([ - this.#socket.disconnect(), - this.#destroyIsolationPool() - ]); + this.#queue.flushAll(new DisconnectsClientError()); + this.#socket.disconnect(); + await this.#destroyIsolationPool(); } async #destroyIsolationPool(): Promise { diff --git a/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts similarity index 89% rename from lib/client/multi-command.ts rename to packages/client/lib/client/multi-command.ts index ba02c2b9aa8..9c19d3d0687 100644 --- a/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,7 +1,7 @@ import COMMANDS from './commands'; import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisModules, RedisPlugins, RedisScript, RedisScripts } from '../commands'; import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -import { extendWithCommands, extendWithModulesAndScripts } from '../commander'; +import { extendWithCommands, extendWithModulesAndScripts, LegacyCommandArguments, transformLegacyCommandArguments } from '../commander'; type RedisClientMultiCommandSignature = (...args: Parameters) => RedisClientMultiCommandType; @@ -11,16 +11,16 @@ type WithCommands = { }; type WithModules = { - [P in keyof M]: { + [P in keyof M as M[P] extends never ? never : P]: { [C in keyof M[P]]: RedisClientMultiCommandSignature; }; }; type WithScripts = { - [P in keyof S]: RedisClientMultiCommandSignature + [P in keyof S as S[P] extends never ? never : P]: RedisClientMultiCommandSignature }; -export type RedisClientMultiCommandType = +export type RedisClientMultiCommandType, S extends RedisScripts = Record> = RedisClientMultiCommand & WithCommands & WithModules & WithScripts; export type RedisClientMultiExecutor = (queue: Array, chainId?: symbol) => Promise>; @@ -52,8 +52,8 @@ export default class RedisClientMultiCommand { #legacyMode(): void { this.v4.addCommand = this.addCommand.bind(this); - (this as any).addCommand = (...args: Array>): this => { - this.#multi.addCommand(args.flat()); + (this as any).addCommand = (...args: LegacyCommandArguments): this => { + this.#multi.addCommand(transformLegacyCommandArguments(args)); return this; }; this.v4.exec = this.exec.bind(this); diff --git a/lib/client/socket.spec.ts b/packages/client/lib/client/socket.spec.ts similarity index 98% rename from lib/client/socket.spec.ts rename to packages/client/lib/client/socket.spec.ts index 11c02d0885c..263320bbf72 100644 --- a/lib/client/socket.spec.ts +++ b/packages/client/lib/client/socket.spec.ts @@ -33,6 +33,6 @@ describe('Socket', () => { return assert.rejects(socket.connect(), { message: '50' }); - }) + }); }); }); diff --git a/lib/client/socket.ts b/packages/client/lib/client/socket.ts similarity index 76% rename from lib/client/socket.ts rename to packages/client/lib/client/socket.ts index ca48ad4d542..d42b42d64d6 100644 --- a/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -1,7 +1,9 @@ -import EventEmitter from 'events'; -import net from 'net'; -import tls from 'tls'; -import { ConnectionTimeoutError, ClientClosedError } from '../errors'; +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'; import { promiseTimeout } from '../utils'; export interface RedisSocketCommonOptions { @@ -20,7 +22,7 @@ export interface RedisUnixSocketOptions extends RedisSocketCommonOptions { path: string; } -export interface RedisTlsSocketOptions extends RedisNetSocketOptions, tls.SecureContextOptions { +export interface RedisTlsSocketOptions extends RedisNetSocketOptions, tls.SecureContextOptions, tls.CommonConnectionOptions { tls: true; } @@ -72,8 +74,18 @@ export default class RedisSocket extends EventEmitter { return this.#isOpen; } - get isSocketExists(): boolean { - return !!this.#socket; + #isReady = false; + + get isReady(): boolean { + return this.#isReady; + } + + // `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used + // https://nodejs.org/api/stream.html#stream_writable_writableneeddrain + #writableNeedDrain = false; + + get writableNeedDrain(): boolean { + return this.#writableNeedDrain; } constructor(initiator?: RedisSocketInitiator, options?: RedisSocketOptions) { @@ -85,33 +97,39 @@ export default class RedisSocket extends EventEmitter { async connect(): Promise { if (this.#isOpen) { - throw new Error('Socket is connection/connecting'); + throw new Error('Socket already opened'); } - this.#isOpen = true; - - try { - await this.#connect(); - } catch (err) { - this.#isOpen = false; - throw err; - } + return this.#connect(); } async #connect(hadError?: boolean): Promise { + this.#isOpen = true; this.#socket = await this.#retryConnection(0, hadError); + this.#writableNeedDrain = false; + + if (!this.#isOpen) { + this.disconnect(); + return; + } + this.emit('connect'); if (this.#initiator) { try { await this.#initiator(); } catch (err) { - this.#socket.end(); + this.#socket.destroy(); this.#socket = undefined; + this.#isOpen = false; throw err; } + + if (!this.#isOpen) return; } + this.#isReady = true; + this.emit('ready'); } @@ -160,10 +178,13 @@ export default class RedisSocket extends EventEmitter { .once('error', (err: Error) => this.#onSocketError(err)) .once('close', hadError => { if (!hadError && this.#isOpen) { - this.#onSocketError(new Error('Socket closed unexpectedly')); + this.#onSocketError(new SocketClosedUnexpectedlyError()); } }) - .on('drain', () => this.emit('drain')) + .on('drain', () => { + this.#writableNeedDrain = false; + this.emit('drain'); + }) .on('data', (data: Buffer) => this.emit('data', data)); resolve(socket); @@ -186,30 +207,32 @@ export default class RedisSocket extends EventEmitter { } #onSocketError(err: Error): void { - this.#socket = undefined; + this.#isReady = false; this.emit('error', err); - this.#connect(true) - .catch(err => this.emit('error', err)); + this.#connect(true).catch(() => { + // the error was already emitted, silently ignore it + }); } - write(toWrite: string | Buffer): boolean { + writeCommand(args: RedisCommandArguments): void { if (!this.#socket) { throw new ClientClosedError(); } - return this.#socket.write(toWrite); + for (const toWrite of encodeCommand(args)) { + this.#writableNeedDrain = !this.#socket.write(toWrite); + } } - async disconnect(ignoreIsOpen = false): Promise { - if ((!ignoreIsOpen && !this.#isOpen) || !this.#socket) { + disconnect(): void { + if (!this.#socket) { throw new ClientClosedError(); } else { - this.#isOpen = false; + this.#isOpen = this.#isReady = false; } - this.#socket.end(); - await EventEmitter.once(this.#socket, 'end'); + this.#socket.destroy(); this.#socket = undefined; this.emit('end'); } @@ -220,15 +243,8 @@ export default class RedisSocket extends EventEmitter { } this.#isOpen = false; - - - try { - await fn(); - await this.disconnect(true); - } catch (err) { - this.#isOpen = true; - throw err; - } + await fn(); + this.disconnect(); } #isCorked = false; diff --git a/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts similarity index 94% rename from lib/cluster/cluster-slots.ts rename to packages/client/lib/cluster/cluster-slots.ts index 63834d4b4ca..ff4c79b4d36 100644 --- a/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; @@ -69,7 +73,7 @@ export default class RedisClusterSlots): Promise { - // Override this.#slots and add not existing clients to this.#clientByKey + // Override this.#slots and add not existing clients to this.#nodeByUrl const promises: Array> = [], clientsInUse = new Set(); for (const master of masters) { @@ -82,13 +86,13 @@ export default class RedisClusterSlots { + testUtils.testWithCluster('sendCommand', async cluster => { + await cluster.connect(); + + try { + await cluster.publish('channel', 'message'); + 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(); + } + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('multi', async cluster => { + const key = 'key'; + assert.deepEqual( + await cluster.multi() + .set(key, 'value') + .get(key) + .exec(), + ['OK', 'value'] + ); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('scripts', async cluster => { + assert.equal( + await cluster.square(2), + 4 + ); + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + scripts: { + square: SQUARE_SCRIPT + } + } + }); + + testUtils.testWithCluster('should handle live resharding', async cluster => { + const key = 'key', + value = 'value'; + await cluster.set(key, value); + + const slot = calculateSlot(key), + source = cluster.getSlotMaster(slot), + destination = cluster.getMasters().find(node => node.id !== source.id)!; + + await Promise.all([ + source.client.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, destination.id), + destination.client.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, destination.id) + ]); + + // should be able to get the key from the source node using "ASKING" + assert.equal( + await cluster.get(key), + value + ); + + await Promise.all([ + source.client.migrate( + '127.0.0.1', + (destination.client.options).socket.port, + key, + 0, + 10 + ) + ]); + + // should be able to get the key from the destination node using the "ASKING" command + assert.equal( + await cluster.get(key), + value + ); + + await Promise.all( + cluster.getMasters().map(({ client }) => { + return client.clusterSetSlot(slot, ClusterSlotStates.NODE, destination.id); + }) + ); + + // should handle "MOVED" errors + assert.equal( + await cluster.get(key), + value + ); + }, { + serverArguments: [], + numberOfNodes: 2 + }); +}); diff --git a/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts similarity index 91% rename from lib/cluster/index.ts rename to packages/client/lib/cluster/index.ts index aeaabecae35..fcf6d4754bb 100644 --- a/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,5 +1,5 @@ import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArguments, RedisCommandReply, RedisModules, RedisScript, RedisScripts } from '../commands'; +import { RedisCommand, RedisCommandArguments, RedisCommandReply, RedisModules, RedisPlugins, RedisScript, RedisScripts } from '../commands'; import { ClientCommandOptions, RedisClientCommandSignature, RedisClientOptions, RedisClientType, WithModules, WithScripts } from '../client'; import RedisClusterSlots, { ClusterNode } from './cluster-slots'; import { extendWithModulesAndScripts, transformCommandArguments, transformCommandReply, extendWithCommands } from '../commander'; @@ -7,14 +7,9 @@ import { EventEmitter } from 'events'; import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; -export type RedisClusterClientOptions = Omit, 'modules' | 'scripts'>; +export type RedisClusterClientOptions = Omit, Record>, 'modules' | 'scripts'>; -export interface RedisClusterPlugins { - modules?: M; - scripts?: S; -} - -export interface RedisClusterOptions extends RedisClusterPlugins { +export interface RedisClusterOptions extends RedisPlugins { rootNodes: Array; defaults?: Partial; useReplicas?: boolean; @@ -25,10 +20,10 @@ type WithCommands = { [P in keyof typeof COMMANDS]: RedisClientCommandSignature<(typeof COMMANDS)[P]>; }; -export type RedisClusterType = +export type RedisClusterType, S extends RedisScripts = Record> = RedisCluster & WithCommands & WithModules & WithScripts; -export default class RedisCluster extends EventEmitter { +export default class RedisCluster, S extends RedisScripts = Record> extends EventEmitter { static extractFirstKey(command: RedisCommand, originalArgs: Array, redisArgs: RedisCommandArguments): string | Buffer | undefined { if (command.FIRST_KEY_INDEX === undefined) { return undefined; @@ -39,7 +34,7 @@ export default class RedisCluster(options?: RedisClusterOptions): RedisClusterType { + static create, S extends RedisScripts = Record>(options?: RedisClusterOptions): RedisClusterType { return new (extendWithModulesAndScripts({ BaseClass: RedisCluster, modules: options?.modules, diff --git a/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts similarity index 94% rename from lib/cluster/multi-command.ts rename to packages/client/lib/cluster/multi-command.ts index 8ffd39a90e0..8a798ca9092 100644 --- a/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -12,16 +12,16 @@ type WithCommands = { }; type WithModules = { - [P in keyof M]: { + [P in keyof M as M[P] extends never ? never : P]: { [C in keyof M[P]]: RedisClusterMultiCommandSignature; }; }; type WithScripts = { - [P in keyof S]: RedisClusterMultiCommandSignature + [P in keyof S as S[P] extends never ? never : P]: RedisClusterMultiCommandSignature }; -export type RedisClusterMultiCommandType = +export type RedisClusterMultiCommandType, S extends RedisScripts = Record> = RedisClusterMultiCommand & WithCommands & WithModules & WithScripts; export type RedisClusterMultiExecutor = (queue: Array, firstKey?: string | Buffer, chainId?: symbol) => Promise>; diff --git a/lib/command-options.ts b/packages/client/lib/command-options.ts similarity index 100% rename from lib/command-options.ts rename to packages/client/lib/command-options.ts diff --git a/lib/commander.spec.ts b/packages/client/lib/commander.spec.ts similarity index 100% rename from lib/commander.spec.ts rename to packages/client/lib/commander.spec.ts diff --git a/lib/commander.ts b/packages/client/lib/commander.ts similarity index 88% rename from lib/commander.ts rename to packages/client/lib/commander.ts index 5871c2f235b..50d416f5b5c 100644 --- a/lib/commander.ts +++ b/packages/client/lib/commander.ts @@ -113,3 +113,18 @@ export function transformCommandReply( return command.transformReply(rawReply, preserved); } + +export type LegacyCommandArguments = Array; + +export function transformLegacyCommandArguments(args: LegacyCommandArguments, flat: RedisCommandArguments = []): RedisCommandArguments { + for (const arg of args) { + if (Array.isArray(arg)) { + transformLegacyCommandArguments(arg, flat); + continue; + } + + flat.push(typeof arg === 'number' ? arg.toString() : arg); + } + + return flat; +} diff --git a/lib/commands/ACL_CAT.spec.ts b/packages/client/lib/commands/ACL_CAT.spec.ts similarity index 82% rename from lib/commands/ACL_CAT.spec.ts rename to packages/client/lib/commands/ACL_CAT.spec.ts index 77ed1cb7a07..521871a1c6b 100644 --- a/lib/commands/ACL_CAT.spec.ts +++ b/packages/client/lib/commands/ACL_CAT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_CAT'; describe('ACL CAT', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('simple', () => { diff --git a/lib/commands/ACL_CAT.ts b/packages/client/lib/commands/ACL_CAT.ts similarity index 100% rename from lib/commands/ACL_CAT.ts rename to packages/client/lib/commands/ACL_CAT.ts diff --git a/lib/commands/ACL_DELUSER.spec.ts b/packages/client/lib/commands/ACL_DELUSER.spec.ts similarity index 73% rename from lib/commands/ACL_DELUSER.spec.ts rename to packages/client/lib/commands/ACL_DELUSER.spec.ts index c64e8db1965..5c5ea2fa2a3 100644 --- a/lib/commands/ACL_DELUSER.spec.ts +++ b/packages/client/lib/commands/ACL_DELUSER.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion, itWithClient, TestRedisServers } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ACL_DELUSER'; describe('ACL DELUSER', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('string', () => { @@ -21,10 +21,10 @@ describe('ACL DELUSER', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.aclDelUser', async client => { + testUtils.testWithClient('client.aclDelUser', async client => { assert.equal( await client.aclDelUser('dosenotexists'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ACL_DELUSER.ts b/packages/client/lib/commands/ACL_DELUSER.ts similarity index 100% rename from lib/commands/ACL_DELUSER.ts rename to packages/client/lib/commands/ACL_DELUSER.ts diff --git a/lib/commands/ACL_GENPASS.spec.ts b/packages/client/lib/commands/ACL_GENPASS.spec.ts similarity index 82% rename from lib/commands/ACL_GENPASS.spec.ts rename to packages/client/lib/commands/ACL_GENPASS.spec.ts index a288a4f7142..3b2a022f972 100644 --- a/lib/commands/ACL_GENPASS.spec.ts +++ b/packages/client/lib/commands/ACL_GENPASS.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_GENPASS'; describe('ACL GENPASS', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('simple', () => { diff --git a/lib/commands/ACL_GENPASS.ts b/packages/client/lib/commands/ACL_GENPASS.ts similarity index 100% rename from lib/commands/ACL_GENPASS.ts rename to packages/client/lib/commands/ACL_GENPASS.ts diff --git a/packages/client/lib/commands/ACL_GETUSER.spec.ts b/packages/client/lib/commands/ACL_GETUSER.spec.ts new file mode 100644 index 00000000000..fcc10768e61 --- /dev/null +++ b/packages/client/lib/commands/ACL_GETUSER.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ACL_GETUSER'; + +describe('ACL GETUSER', () => { + testUtils.isVersionGreaterThanHook([6]); + + it('transformArguments', () => { + assert.deepEqual( + transformArguments('username'), + ['ACL', 'GETUSER', 'username'] + ); + }); + + testUtils.testWithClient('client.aclGetUser', async client => { + assert.deepEqual( + await client.aclGetUser('default'), + { + passwords: [], + commands: '+@all', + keys: ['*'], + ...(testUtils.isVersionGreaterThan([6, 2]) ? { + flags: ['on', 'allkeys', 'allchannels', 'allcommands', 'nopass'], + channels: ['*'] + } : { + flags: ['on', 'allkeys', 'allcommands', 'nopass'], + channels: undefined + }) + } + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/lib/commands/ACL_GETUSER.ts b/packages/client/lib/commands/ACL_GETUSER.ts similarity index 100% rename from lib/commands/ACL_GETUSER.ts rename to packages/client/lib/commands/ACL_GETUSER.ts diff --git a/lib/commands/ACL_LIST.spec.ts b/packages/client/lib/commands/ACL_LIST.spec.ts similarity index 70% rename from lib/commands/ACL_LIST.spec.ts rename to packages/client/lib/commands/ACL_LIST.spec.ts index ab6bae762f1..9f9156db7a2 100644 --- a/lib/commands/ACL_LIST.spec.ts +++ b/packages/client/lib/commands/ACL_LIST.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_LIST'; describe('ACL LIST', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_LIST.ts b/packages/client/lib/commands/ACL_LIST.ts similarity index 100% rename from lib/commands/ACL_LIST.ts rename to packages/client/lib/commands/ACL_LIST.ts diff --git a/lib/commands/ACL_LOAD.spec.ts b/packages/client/lib/commands/ACL_LOAD.spec.ts similarity index 70% rename from lib/commands/ACL_LOAD.spec.ts rename to packages/client/lib/commands/ACL_LOAD.spec.ts index d173d7f1355..703d5eeb252 100644 --- a/lib/commands/ACL_LOAD.spec.ts +++ b/packages/client/lib/commands/ACL_LOAD.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_SAVE'; describe('ACL SAVE', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_LOAD.ts b/packages/client/lib/commands/ACL_LOAD.ts similarity index 100% rename from lib/commands/ACL_LOAD.ts rename to packages/client/lib/commands/ACL_LOAD.ts diff --git a/lib/commands/ACL_LOG.spec.ts b/packages/client/lib/commands/ACL_LOG.spec.ts similarity index 93% rename from lib/commands/ACL_LOG.spec.ts rename to packages/client/lib/commands/ACL_LOG.spec.ts index 3ce76ce4563..a8296d31da6 100644 --- a/lib/commands/ACL_LOG.spec.ts +++ b/packages/client/lib/commands/ACL_LOG.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments, transformReply } from './ACL_LOG'; describe('ACL LOG', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('simple', () => { diff --git a/lib/commands/ACL_LOG.ts b/packages/client/lib/commands/ACL_LOG.ts similarity index 100% rename from lib/commands/ACL_LOG.ts rename to packages/client/lib/commands/ACL_LOG.ts diff --git a/lib/commands/ACL_LOG_RESET.spec.ts b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts similarity index 72% rename from lib/commands/ACL_LOG_RESET.spec.ts rename to packages/client/lib/commands/ACL_LOG_RESET.spec.ts index 3f0e628d9f0..5d26e45d04f 100644 --- a/lib/commands/ACL_LOG_RESET.spec.ts +++ b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_LOG_RESET'; describe('ACL LOG RESET', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_LOG_RESET.ts b/packages/client/lib/commands/ACL_LOG_RESET.ts similarity index 100% rename from lib/commands/ACL_LOG_RESET.ts rename to packages/client/lib/commands/ACL_LOG_RESET.ts diff --git a/lib/commands/ACL_SAVE.spec.ts b/packages/client/lib/commands/ACL_SAVE.spec.ts similarity index 70% rename from lib/commands/ACL_SAVE.spec.ts rename to packages/client/lib/commands/ACL_SAVE.spec.ts index b34c7bb0e6f..f4de312bb7a 100644 --- a/lib/commands/ACL_SAVE.spec.ts +++ b/packages/client/lib/commands/ACL_SAVE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_LOAD'; describe('ACL LOAD', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_SAVE.ts b/packages/client/lib/commands/ACL_SAVE.ts similarity index 100% rename from lib/commands/ACL_SAVE.ts rename to packages/client/lib/commands/ACL_SAVE.ts diff --git a/lib/commands/ACL_SETUSER.spec.ts b/packages/client/lib/commands/ACL_SETUSER.spec.ts similarity index 84% rename from lib/commands/ACL_SETUSER.spec.ts rename to packages/client/lib/commands/ACL_SETUSER.spec.ts index f3badfcdca8..9c8ea8a59e0 100644 --- a/lib/commands/ACL_SETUSER.spec.ts +++ b/packages/client/lib/commands/ACL_SETUSER.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_SETUSER'; describe('ACL SETUSER', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('string', () => { diff --git a/lib/commands/ACL_SETUSER.ts b/packages/client/lib/commands/ACL_SETUSER.ts similarity index 100% rename from lib/commands/ACL_SETUSER.ts rename to packages/client/lib/commands/ACL_SETUSER.ts diff --git a/lib/commands/ACL_USERS.spec.ts b/packages/client/lib/commands/ACL_USERS.spec.ts similarity index 71% rename from lib/commands/ACL_USERS.spec.ts rename to packages/client/lib/commands/ACL_USERS.spec.ts index 14b76725fcd..35e06ce8494 100644 --- a/lib/commands/ACL_USERS.spec.ts +++ b/packages/client/lib/commands/ACL_USERS.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_USERS'; describe('ACL USERS', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_USERS.ts b/packages/client/lib/commands/ACL_USERS.ts similarity index 100% rename from lib/commands/ACL_USERS.ts rename to packages/client/lib/commands/ACL_USERS.ts diff --git a/lib/commands/ACL_WHOAMI.spec.ts b/packages/client/lib/commands/ACL_WHOAMI.spec.ts similarity index 71% rename from lib/commands/ACL_WHOAMI.spec.ts rename to packages/client/lib/commands/ACL_WHOAMI.spec.ts index a933057ea9d..32eb327beea 100644 --- a/lib/commands/ACL_WHOAMI.spec.ts +++ b/packages/client/lib/commands/ACL_WHOAMI.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils from '../test-utils'; import { transformArguments } from './ACL_WHOAMI'; describe('ACL WHOAMI', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); it('transformArguments', () => { assert.deepEqual( diff --git a/lib/commands/ACL_WHOAMI.ts b/packages/client/lib/commands/ACL_WHOAMI.ts similarity index 100% rename from lib/commands/ACL_WHOAMI.ts rename to packages/client/lib/commands/ACL_WHOAMI.ts diff --git a/lib/commands/APPEND.spec.ts b/packages/client/lib/commands/APPEND.spec.ts similarity index 90% rename from lib/commands/APPEND.spec.ts rename to packages/client/lib/commands/APPEND.spec.ts index 283ab807956..23353866843 100644 --- a/lib/commands/APPEND.spec.ts +++ b/packages/client/lib/commands/APPEND.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'assert'; import { transformArguments } from './APPEND'; -describe('AUTH', () => { +describe('APPEND', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('key', 'value'), diff --git a/lib/commands/APPEND.ts b/packages/client/lib/commands/APPEND.ts similarity index 100% rename from lib/commands/APPEND.ts rename to packages/client/lib/commands/APPEND.ts diff --git a/lib/commands/ASKING.spec.ts b/packages/client/lib/commands/ASKING.spec.ts similarity index 100% rename from lib/commands/ASKING.spec.ts rename to packages/client/lib/commands/ASKING.spec.ts diff --git a/lib/commands/ASKING.ts b/packages/client/lib/commands/ASKING.ts similarity index 100% rename from lib/commands/ASKING.ts rename to packages/client/lib/commands/ASKING.ts diff --git a/lib/commands/AUTH.spec.ts b/packages/client/lib/commands/AUTH.spec.ts similarity index 100% rename from lib/commands/AUTH.spec.ts rename to packages/client/lib/commands/AUTH.spec.ts diff --git a/lib/commands/AUTH.ts b/packages/client/lib/commands/AUTH.ts similarity index 100% rename from lib/commands/AUTH.ts rename to packages/client/lib/commands/AUTH.ts diff --git a/lib/commands/BGREWRITEAOF.spec.ts b/packages/client/lib/commands/BGREWRITEAOF.spec.ts similarity index 100% rename from lib/commands/BGREWRITEAOF.spec.ts rename to packages/client/lib/commands/BGREWRITEAOF.spec.ts diff --git a/lib/commands/BGREWRITEAOF.ts b/packages/client/lib/commands/BGREWRITEAOF.ts similarity index 100% rename from lib/commands/BGREWRITEAOF.ts rename to packages/client/lib/commands/BGREWRITEAOF.ts diff --git a/lib/commands/BGSAVE.spec.ts b/packages/client/lib/commands/BGSAVE.spec.ts similarity index 100% rename from lib/commands/BGSAVE.spec.ts rename to packages/client/lib/commands/BGSAVE.spec.ts diff --git a/lib/commands/BGSAVE.ts b/packages/client/lib/commands/BGSAVE.ts similarity index 100% rename from lib/commands/BGSAVE.ts rename to packages/client/lib/commands/BGSAVE.ts diff --git a/lib/commands/BITCOUNT.spec.ts b/packages/client/lib/commands/BITCOUNT.spec.ts similarity index 82% rename from lib/commands/BITCOUNT.spec.ts rename to packages/client/lib/commands/BITCOUNT.spec.ts index bf4cf39cab6..8919957cf92 100644 --- a/lib/commands/BITCOUNT.spec.ts +++ b/packages/client/lib/commands/BITCOUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BITCOUNT'; describe('BITCOUNT', () => { @@ -22,10 +22,10 @@ describe('BITCOUNT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.bitCount', async client => { + testUtils.testWithClient('client.bitCount', async client => { assert.equal( await client.bitCount('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/BITCOUNT.ts b/packages/client/lib/commands/BITCOUNT.ts similarity index 100% rename from lib/commands/BITCOUNT.ts rename to packages/client/lib/commands/BITCOUNT.ts diff --git a/lib/commands/BITFIELD.spec.ts b/packages/client/lib/commands/BITFIELD.spec.ts similarity index 88% rename from lib/commands/BITFIELD.spec.ts rename to packages/client/lib/commands/BITFIELD.spec.ts index 4d6d9d11c1a..93a5cb08a63 100644 --- a/lib/commands/BITFIELD.spec.ts +++ b/packages/client/lib/commands/BITFIELD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BITFIELD'; describe('BITFIELD', () => { @@ -33,10 +33,10 @@ describe('BITFIELD', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.bitField', async client => { + testUtils.testWithClient('client.bitField', async client => { assert.deepEqual( await client.bitField('key', []), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/BITFIELD.ts b/packages/client/lib/commands/BITFIELD.ts similarity index 100% rename from lib/commands/BITFIELD.ts rename to packages/client/lib/commands/BITFIELD.ts diff --git a/lib/commands/BITOP.spec.ts b/packages/client/lib/commands/BITOP.spec.ts similarity index 75% rename from lib/commands/BITOP.spec.ts rename to packages/client/lib/commands/BITOP.spec.ts index aa863e5f2d2..554530d56f4 100644 --- a/lib/commands/BITOP.spec.ts +++ b/packages/client/lib/commands/BITOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BITOP'; describe('BITOP', () => { @@ -19,17 +19,17 @@ describe('BITOP', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.bitOp', async client => { + testUtils.testWithClient('client.bitOp', async client => { assert.equal( await client.bitOp('AND', 'destKey', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.bitOp', async cluster => { + testUtils.testWithCluster('cluster.bitOp', async cluster => { assert.equal( await cluster.bitOp('AND', '{tag}destKey', '{tag}key'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BITOP.ts b/packages/client/lib/commands/BITOP.ts similarity index 100% rename from lib/commands/BITOP.ts rename to packages/client/lib/commands/BITOP.ts diff --git a/lib/commands/BITPOS.spec.ts b/packages/client/lib/commands/BITPOS.spec.ts similarity index 77% rename from lib/commands/BITPOS.spec.ts rename to packages/client/lib/commands/BITPOS.spec.ts index ad08e708c54..354deea6195 100644 --- a/lib/commands/BITPOS.spec.ts +++ b/packages/client/lib/commands/BITPOS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BITPOS'; describe('BITPOS', () => { @@ -26,17 +26,17 @@ describe('BITPOS', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.bitPos', async client => { + testUtils.testWithClient('client.bitPos', async client => { assert.equal( await client.bitPos('key', 1, 1), -1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.bitPos', async cluster => { + testUtils.testWithCluster('cluster.bitPos', async cluster => { assert.equal( await cluster.bitPos('key', 1, 1), -1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BITPOS.ts b/packages/client/lib/commands/BITPOS.ts similarity index 100% rename from lib/commands/BITPOS.ts rename to packages/client/lib/commands/BITPOS.ts diff --git a/lib/commands/BLMOVE.spec.ts b/packages/client/lib/commands/BLMOVE.spec.ts similarity index 75% rename from lib/commands/BLMOVE.spec.ts rename to packages/client/lib/commands/BLMOVE.spec.ts index b942864758f..3b86c1ec91e 100644 --- a/lib/commands/BLMOVE.spec.ts +++ b/packages/client/lib/commands/BLMOVE.spec.ts @@ -1,10 +1,10 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BLMOVE'; import { commandOptions } from '../../index'; describe('BLMOVE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -13,7 +13,7 @@ describe('BLMOVE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.blMove', async client => { + testUtils.testWithClient('client.blMove', async client => { const [blMoveReply] = await Promise.all([ client.blMove(commandOptions({ isolated: true @@ -25,9 +25,9 @@ describe('BLMOVE', () => { blMoveReply, 'element' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.blMove', async cluster => { + testUtils.testWithCluster('cluster.blMove', async cluster => { const [blMoveReply] = await Promise.all([ cluster.blMove(commandOptions({ isolated: true @@ -39,5 +39,5 @@ describe('BLMOVE', () => { blMoveReply, 'element' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BLMOVE.ts b/packages/client/lib/commands/BLMOVE.ts similarity index 100% rename from lib/commands/BLMOVE.ts rename to packages/client/lib/commands/BLMOVE.ts diff --git a/lib/commands/BLPOP.spec.ts b/packages/client/lib/commands/BLPOP.spec.ts similarity index 87% rename from lib/commands/BLPOP.spec.ts rename to packages/client/lib/commands/BLPOP.spec.ts index 651dd09eaf3..4b93c0b43b8 100644 --- a/lib/commands/BLPOP.spec.ts +++ b/packages/client/lib/commands/BLPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './BLPOP'; import { commandOptions } from '../../index'; @@ -39,7 +39,7 @@ describe('BLPOP', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.blPop', async client => { + testUtils.testWithClient('client.blPop', async client => { const [ blPopReply ] = await Promise.all([ client.blPop( commandOptions({ isolated: true }), @@ -56,9 +56,9 @@ describe('BLPOP', () => { element: 'element' } ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.blPop', async cluster => { + testUtils.testWithCluster('cluster.blPop', async cluster => { const [ blPopReply ] = await Promise.all([ cluster.blPop( commandOptions({ isolated: true }), @@ -75,5 +75,5 @@ describe('BLPOP', () => { element: 'element' } ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BLPOP.ts b/packages/client/lib/commands/BLPOP.ts similarity index 100% rename from lib/commands/BLPOP.ts rename to packages/client/lib/commands/BLPOP.ts diff --git a/lib/commands/BRPOP.spec.ts b/packages/client/lib/commands/BRPOP.spec.ts similarity index 87% rename from lib/commands/BRPOP.spec.ts rename to packages/client/lib/commands/BRPOP.spec.ts index 9a7d0bbc37d..fc203e1abdf 100644 --- a/lib/commands/BRPOP.spec.ts +++ b/packages/client/lib/commands/BRPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './BRPOP'; import { commandOptions } from '../../index'; @@ -39,7 +39,7 @@ describe('BRPOP', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.brPop', async client => { + testUtils.testWithClient('client.brPop', async client => { const [ brPopReply ] = await Promise.all([ client.brPop( commandOptions({ isolated: true }), @@ -56,9 +56,9 @@ describe('BRPOP', () => { element: 'element' } ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.brPop', async cluster => { + testUtils.testWithCluster('cluster.brPop', async cluster => { const [ brPopReply ] = await Promise.all([ cluster.brPop( commandOptions({ isolated: true }), @@ -75,5 +75,5 @@ describe('BRPOP', () => { element: 'element' } ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BRPOP.ts b/packages/client/lib/commands/BRPOP.ts similarity index 100% rename from lib/commands/BRPOP.ts rename to packages/client/lib/commands/BRPOP.ts diff --git a/lib/commands/BRPOPLPUSH.spec.ts b/packages/client/lib/commands/BRPOPLPUSH.spec.ts similarity index 80% rename from lib/commands/BRPOPLPUSH.spec.ts rename to packages/client/lib/commands/BRPOPLPUSH.spec.ts index 08bcf5e4d94..214af4553ac 100644 --- a/lib/commands/BRPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/BRPOPLPUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './BRPOPLPUSH'; import { commandOptions } from '../../index'; @@ -11,7 +11,7 @@ describe('BRPOPLPUSH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.brPopLPush', async client => { + testUtils.testWithClient('client.brPopLPush', async client => { const [ popReply ] = await Promise.all([ client.brPopLPush( commandOptions({ isolated: true }), @@ -26,9 +26,9 @@ describe('BRPOPLPUSH', () => { popReply, 'element' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.brPopLPush', async cluster => { + testUtils.testWithCluster('cluster.brPopLPush', async cluster => { const [ popReply ] = await Promise.all([ cluster.brPopLPush( commandOptions({ isolated: true }), @@ -43,5 +43,5 @@ describe('BRPOPLPUSH', () => { popReply, 'element' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/BRPOPLPUSH.ts b/packages/client/lib/commands/BRPOPLPUSH.ts similarity index 100% rename from lib/commands/BRPOPLPUSH.ts rename to packages/client/lib/commands/BRPOPLPUSH.ts diff --git a/lib/commands/BZPOPMAX.spec.ts b/packages/client/lib/commands/BZPOPMAX.spec.ts similarity index 91% rename from lib/commands/BZPOPMAX.spec.ts rename to packages/client/lib/commands/BZPOPMAX.spec.ts index 090dfba096d..e1c37478469 100644 --- a/lib/commands/BZPOPMAX.spec.ts +++ b/packages/client/lib/commands/BZPOPMAX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './BZPOPMAX'; import { commandOptions } from '../../index'; @@ -40,7 +40,7 @@ describe('BZPOPMAX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.bzPopMax', async client => { + testUtils.testWithClient('client.bzPopMax', async client => { const [ bzPopMaxReply ] = await Promise.all([ client.bzPopMax( commandOptions({ isolated: true }), @@ -61,5 +61,5 @@ describe('BZPOPMAX', () => { score: 1 } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/BZPOPMAX.ts b/packages/client/lib/commands/BZPOPMAX.ts similarity index 100% rename from lib/commands/BZPOPMAX.ts rename to packages/client/lib/commands/BZPOPMAX.ts diff --git a/lib/commands/BZPOPMIN.spec.ts b/packages/client/lib/commands/BZPOPMIN.spec.ts similarity index 91% rename from lib/commands/BZPOPMIN.spec.ts rename to packages/client/lib/commands/BZPOPMIN.spec.ts index 8b8977f9b3a..4cd1ec1b220 100644 --- a/lib/commands/BZPOPMIN.spec.ts +++ b/packages/client/lib/commands/BZPOPMIN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './BZPOPMIN'; import { commandOptions } from '../../index'; @@ -40,7 +40,7 @@ describe('BZPOPMIN', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.bzPopMin', async client => { + testUtils.testWithClient('client.bzPopMin', async client => { const [ bzPopMinReply ] = await Promise.all([ client.bzPopMin( commandOptions({ isolated: true }), @@ -61,5 +61,5 @@ describe('BZPOPMIN', () => { score: 1 } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/BZPOPMIN.ts b/packages/client/lib/commands/BZPOPMIN.ts similarity index 100% rename from lib/commands/BZPOPMIN.ts rename to packages/client/lib/commands/BZPOPMIN.ts diff --git a/lib/commands/CLIENT_ID.spec.ts b/packages/client/lib/commands/CLIENT_ID.spec.ts similarity index 71% rename from lib/commands/CLIENT_ID.spec.ts rename to packages/client/lib/commands/CLIENT_ID.spec.ts index cb7dfd9f730..6792a8c31be 100644 --- a/lib/commands/CLIENT_ID.spec.ts +++ b/packages/client/lib/commands/CLIENT_ID.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './CLIENT_ID'; describe('CLIENT ID', () => { @@ -10,10 +10,10 @@ describe('CLIENT ID', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.clientId', async client => { + testUtils.testWithClient('client.clientId', async client => { assert.equal( typeof (await client.clientId()), 'number' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/CLIENT_ID.ts b/packages/client/lib/commands/CLIENT_ID.ts similarity index 100% rename from lib/commands/CLIENT_ID.ts rename to packages/client/lib/commands/CLIENT_ID.ts diff --git a/lib/commands/CLIENT_INFO.spec.ts b/packages/client/lib/commands/CLIENT_INFO.spec.ts similarity index 100% rename from lib/commands/CLIENT_INFO.spec.ts rename to packages/client/lib/commands/CLIENT_INFO.spec.ts diff --git a/lib/commands/CLIENT_INFO.ts b/packages/client/lib/commands/CLIENT_INFO.ts similarity index 100% rename from lib/commands/CLIENT_INFO.ts rename to packages/client/lib/commands/CLIENT_INFO.ts diff --git a/lib/commands/CLUSTER_ADDSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts similarity index 100% rename from lib/commands/CLUSTER_ADDSLOTS.spec.ts rename to packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts diff --git a/lib/commands/CLUSTER_ADDSLOTS.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts similarity index 100% rename from lib/commands/CLUSTER_ADDSLOTS.ts rename to packages/client/lib/commands/CLUSTER_ADDSLOTS.ts diff --git a/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts similarity index 100% rename from lib/commands/CLUSTER_FLUSHSLOTS.spec.ts rename to packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts diff --git a/lib/commands/CLUSTER_FLUSHSLOTS.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts similarity index 100% rename from lib/commands/CLUSTER_FLUSHSLOTS.ts rename to packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts diff --git a/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts similarity index 100% rename from lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts rename to packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts diff --git a/lib/commands/CLUSTER_GETKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts similarity index 100% rename from lib/commands/CLUSTER_GETKEYSINSLOT.ts rename to packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts diff --git a/lib/commands/CLUSTER_INFO.spec.ts b/packages/client/lib/commands/CLUSTER_INFO.spec.ts similarity index 100% rename from lib/commands/CLUSTER_INFO.spec.ts rename to packages/client/lib/commands/CLUSTER_INFO.spec.ts diff --git a/lib/commands/CLUSTER_INFO.ts b/packages/client/lib/commands/CLUSTER_INFO.ts similarity index 100% rename from lib/commands/CLUSTER_INFO.ts rename to packages/client/lib/commands/CLUSTER_INFO.ts diff --git a/lib/commands/CLUSTER_MEET.spec.ts b/packages/client/lib/commands/CLUSTER_MEET.spec.ts similarity index 100% rename from lib/commands/CLUSTER_MEET.spec.ts rename to packages/client/lib/commands/CLUSTER_MEET.spec.ts diff --git a/lib/commands/CLUSTER_MEET.ts b/packages/client/lib/commands/CLUSTER_MEET.ts similarity index 100% rename from lib/commands/CLUSTER_MEET.ts rename to packages/client/lib/commands/CLUSTER_MEET.ts diff --git a/lib/commands/CLUSTER_NODES.spec.ts b/packages/client/lib/commands/CLUSTER_NODES.spec.ts similarity index 100% rename from lib/commands/CLUSTER_NODES.spec.ts rename to packages/client/lib/commands/CLUSTER_NODES.spec.ts diff --git a/lib/commands/CLUSTER_NODES.ts b/packages/client/lib/commands/CLUSTER_NODES.ts similarity index 100% rename from lib/commands/CLUSTER_NODES.ts rename to packages/client/lib/commands/CLUSTER_NODES.ts diff --git a/lib/commands/CLUSTER_RESET.spec.ts b/packages/client/lib/commands/CLUSTER_RESET.spec.ts similarity index 100% rename from lib/commands/CLUSTER_RESET.spec.ts rename to packages/client/lib/commands/CLUSTER_RESET.spec.ts diff --git a/lib/commands/CLUSTER_RESET.ts b/packages/client/lib/commands/CLUSTER_RESET.ts similarity index 100% rename from lib/commands/CLUSTER_RESET.ts rename to packages/client/lib/commands/CLUSTER_RESET.ts diff --git a/lib/commands/CLUSTER_SETSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts similarity index 100% rename from lib/commands/CLUSTER_SETSLOT.spec.ts rename to packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts diff --git a/lib/commands/CLUSTER_SETSLOT.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.ts similarity index 100% rename from lib/commands/CLUSTER_SETSLOT.ts rename to packages/client/lib/commands/CLUSTER_SETSLOT.ts diff --git a/lib/commands/CLUSTER_SLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts similarity index 99% rename from lib/commands/CLUSTER_SLOTS.spec.ts rename to packages/client/lib/commands/CLUSTER_SLOTS.spec.ts index ec6773bcdd4..6efbfe13ce1 100644 --- a/lib/commands/CLUSTER_SLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts @@ -71,6 +71,6 @@ describe('CLUSTER SLOTS', () => { id: '58e6e48d41228013e5d9c1c37c5060693925e97e' }] }] - ) + ); }); }); diff --git a/lib/commands/CLUSTER_SLOTS.ts b/packages/client/lib/commands/CLUSTER_SLOTS.ts similarity index 100% rename from lib/commands/CLUSTER_SLOTS.ts rename to packages/client/lib/commands/CLUSTER_SLOTS.ts diff --git a/packages/client/lib/commands/COMMAND.spec.ts b/packages/client/lib/commands/COMMAND.spec.ts new file mode 100644 index 00000000000..baad79845ab --- /dev/null +++ b/packages/client/lib/commands/COMMAND.spec.ts @@ -0,0 +1,17 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './COMMAND'; +import { assertPingCommand } from './COMMAND_INFO.spec'; + +describe('COMMAND', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['COMMAND'] + ); + }); + + testUtils.testWithClient('client.command', async client => { + assertPingCommand((await client.command()).find(command => command.name === 'ping')); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/lib/commands/COMMAND.ts b/packages/client/lib/commands/COMMAND.ts similarity index 100% rename from lib/commands/COMMAND.ts rename to packages/client/lib/commands/COMMAND.ts diff --git a/lib/commands/COMMAND_COUNT.spec.ts b/packages/client/lib/commands/COMMAND_COUNT.spec.ts similarity index 71% rename from lib/commands/COMMAND_COUNT.spec.ts rename to packages/client/lib/commands/COMMAND_COUNT.spec.ts index 23e83c71cec..71482382f67 100644 --- a/lib/commands/COMMAND_COUNT.spec.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './COMMAND_COUNT'; describe('COMMAND COUNT', () => { @@ -10,10 +10,10 @@ describe('COMMAND COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.commandCount', async client => { + testUtils.testWithClient('client.commandCount', async client => { assert.equal( typeof await client.commandCount(), 'number' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/COMMAND_COUNT.ts b/packages/client/lib/commands/COMMAND_COUNT.ts similarity index 77% rename from lib/commands/COMMAND_COUNT.ts rename to packages/client/lib/commands/COMMAND_COUNT.ts index 5b8283bcc66..34c6a088da6 100644 --- a/lib/commands/COMMAND_COUNT.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.ts @@ -6,4 +6,4 @@ export function transformArguments(): RedisCommandArguments { return ['COMMAND', 'COUNT']; } -declare function transformReply(): number; +export declare function transformReply(): number; diff --git a/lib/commands/COMMAND_GETKEYS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts similarity index 73% rename from lib/commands/COMMAND_GETKEYS.spec.ts rename to packages/client/lib/commands/COMMAND_GETKEYS.spec.ts index f2630db9afa..a92d032c5d6 100644 --- a/lib/commands/COMMAND_GETKEYS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './COMMAND_GETKEYS'; describe('COMMAND GETKEYS', () => { @@ -10,10 +10,10 @@ describe('COMMAND GETKEYS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.commandGetKeys', async client => { + testUtils.testWithClient('client.commandGetKeys', async client => { assert.deepEqual( await client.commandGetKeys(['GET', 'key']), ['key'] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/COMMAND_GETKEYS.ts b/packages/client/lib/commands/COMMAND_GETKEYS.ts similarity index 78% rename from lib/commands/COMMAND_GETKEYS.ts rename to packages/client/lib/commands/COMMAND_GETKEYS.ts index caf342088fb..1c38515aef9 100644 --- a/lib/commands/COMMAND_GETKEYS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.ts @@ -6,4 +6,4 @@ export function transformArguments(args: Array): RedisCommandArguments { return ['COMMAND', 'GETKEYS', ...args]; } -declare function transformReply(): Array; +export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/COMMAND_INFO.spec.ts b/packages/client/lib/commands/COMMAND_INFO.spec.ts new file mode 100644 index 00000000000..d6488460484 --- /dev/null +++ b/packages/client/lib/commands/COMMAND_INFO.spec.ts @@ -0,0 +1,45 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './COMMAND_INFO'; +import { CommandCategories, CommandFlags, CommandReply } from './generic-transformers'; + +export function assertPingCommand(commandInfo: CommandReply | null | undefined): void { + assert.deepEqual( + commandInfo, + { + name: 'ping', + arity: -1, + flags: new Set([CommandFlags.STALE, CommandFlags.FAST]), + firstKeyIndex: 0, + lastKeyIndex: 0, + step: 0, + categories: new Set( + testUtils.isVersionGreaterThan([6]) ? + [CommandCategories.FAST, CommandCategories.CONNECTION] : + [] + ) + } + ); +} + +describe('COMMAND INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(['PING']), + ['COMMAND', 'INFO', 'PING'] + ); + }); + + describe('client.commandInfo', () => { + testUtils.testWithClient('PING', async client => { + assertPingCommand((await client.commandInfo(['PING']))[0]); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('DOSE_NOT_EXISTS', async client => { + assert.deepEqual( + await client.commandInfo(['DOSE_NOT_EXISTS']), + [null] + ); + }, GLOBAL.SERVERS.OPEN); + }); +}); diff --git a/lib/commands/COMMAND_INFO.ts b/packages/client/lib/commands/COMMAND_INFO.ts similarity index 100% rename from lib/commands/COMMAND_INFO.ts rename to packages/client/lib/commands/COMMAND_INFO.ts diff --git a/lib/commands/CONFIG_GET.spec.ts b/packages/client/lib/commands/CONFIG_GET.spec.ts similarity index 100% rename from lib/commands/CONFIG_GET.spec.ts rename to packages/client/lib/commands/CONFIG_GET.spec.ts diff --git a/packages/client/lib/commands/CONFIG_GET.ts b/packages/client/lib/commands/CONFIG_GET.ts new file mode 100644 index 00000000000..35907742e25 --- /dev/null +++ b/packages/client/lib/commands/CONFIG_GET.ts @@ -0,0 +1,5 @@ +export function transformArguments(parameter: string): Array { + return ['CONFIG', 'GET', parameter]; +} + +export { transformReplyTuples as transformReply } from './generic-transformers'; diff --git a/lib/commands/CONFIG_RESETSTAT.spec.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts similarity index 100% rename from lib/commands/CONFIG_RESETSTAT.spec.ts rename to packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts diff --git a/lib/commands/CONFIG_RESETSTAT.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.ts similarity index 100% rename from lib/commands/CONFIG_RESETSTAT.ts rename to packages/client/lib/commands/CONFIG_RESETSTAT.ts diff --git a/lib/commands/CONFIG_REWRITE.spec.ts b/packages/client/lib/commands/CONFIG_REWRITE.spec.ts similarity index 100% rename from lib/commands/CONFIG_REWRITE.spec.ts rename to packages/client/lib/commands/CONFIG_REWRITE.spec.ts diff --git a/lib/commands/CONFIG_REWRITE.ts b/packages/client/lib/commands/CONFIG_REWRITE.ts similarity index 100% rename from lib/commands/CONFIG_REWRITE.ts rename to packages/client/lib/commands/CONFIG_REWRITE.ts diff --git a/lib/commands/CONFIG_SET.spec.ts b/packages/client/lib/commands/CONFIG_SET.spec.ts similarity index 100% rename from lib/commands/CONFIG_SET.spec.ts rename to packages/client/lib/commands/CONFIG_SET.spec.ts diff --git a/lib/commands/CONFIG_SET.ts b/packages/client/lib/commands/CONFIG_SET.ts similarity index 100% rename from lib/commands/CONFIG_SET.ts rename to packages/client/lib/commands/CONFIG_SET.ts diff --git a/lib/commands/COPY.spec.ts b/packages/client/lib/commands/COPY.spec.ts similarity index 88% rename from lib/commands/COPY.spec.ts rename to packages/client/lib/commands/COPY.spec.ts index fb35be863ab..0d68e969cdb 100644 --- a/lib/commands/COPY.spec.ts +++ b/packages/client/lib/commands/COPY.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './COPY'; describe('COPY', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('simple', () => { @@ -58,10 +58,10 @@ describe('COPY', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.copy', async client => { + testUtils.testWithClient('client.copy', async client => { assert.equal( await client.copy('source', 'destination'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/COPY.ts b/packages/client/lib/commands/COPY.ts similarity index 80% rename from lib/commands/COPY.ts rename to packages/client/lib/commands/COPY.ts index 534b0d9c48c..c7a44e45c3c 100644 --- a/lib/commands/COPY.ts +++ b/packages/client/lib/commands/COPY.ts @@ -1,5 +1,3 @@ -import { transformReplyBoolean } from './generic-transformers'; - interface CopyCommandOptions { destinationDb?: number; replace?: boolean; @@ -21,4 +19,4 @@ export function transformArguments(source: string, destination: string, options? return args; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/DBSIZE.spec.ts b/packages/client/lib/commands/DBSIZE.spec.ts similarity index 70% rename from lib/commands/DBSIZE.spec.ts rename to packages/client/lib/commands/DBSIZE.spec.ts index 36f591dbd29..a014a46e6e2 100644 --- a/lib/commands/DBSIZE.spec.ts +++ b/packages/client/lib/commands/DBSIZE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './DBSIZE'; describe('DBSIZE', () => { @@ -10,10 +10,10 @@ describe('DBSIZE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.dbSize', async client => { + testUtils.testWithClient('client.dbSize', async client => { assert.equal( await client.dbSize(), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/DBSIZE.ts b/packages/client/lib/commands/DBSIZE.ts similarity index 100% rename from lib/commands/DBSIZE.ts rename to packages/client/lib/commands/DBSIZE.ts diff --git a/lib/commands/DECR.spec.ts b/packages/client/lib/commands/DECR.spec.ts similarity index 70% rename from lib/commands/DECR.spec.ts rename to packages/client/lib/commands/DECR.spec.ts index 5b4b4f0fd33..75e1205feda 100644 --- a/lib/commands/DECR.spec.ts +++ b/packages/client/lib/commands/DECR.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './DECR'; describe('DECR', () => { @@ -10,10 +10,10 @@ describe('DECR', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.decr', async client => { + testUtils.testWithClient('client.decr', async client => { assert.equal( await client.decr('key'), -1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/DECR.ts b/packages/client/lib/commands/DECR.ts similarity index 100% rename from lib/commands/DECR.ts rename to packages/client/lib/commands/DECR.ts diff --git a/lib/commands/DECRBY.spec.ts b/packages/client/lib/commands/DECRBY.spec.ts similarity index 71% rename from lib/commands/DECRBY.spec.ts rename to packages/client/lib/commands/DECRBY.spec.ts index 1c9ac69bb96..d2c23e94728 100644 --- a/lib/commands/DECRBY.spec.ts +++ b/packages/client/lib/commands/DECRBY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './DECRBY'; describe('DECRBY', () => { @@ -10,10 +10,10 @@ describe('DECRBY', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.decrBy', async client => { + testUtils.testWithClient('client.decrBy', async client => { assert.equal( await client.decrBy('key', 2), -2 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/DECRBY.ts b/packages/client/lib/commands/DECRBY.ts similarity index 100% rename from lib/commands/DECRBY.ts rename to packages/client/lib/commands/DECRBY.ts diff --git a/lib/commands/DEL.spec.ts b/packages/client/lib/commands/DEL.spec.ts similarity index 80% rename from lib/commands/DEL.spec.ts rename to packages/client/lib/commands/DEL.spec.ts index ec780de67a0..75a29a8f641 100644 --- a/lib/commands/DEL.spec.ts +++ b/packages/client/lib/commands/DEL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './DEL'; describe('DEL', () => { @@ -19,10 +19,10 @@ describe('DEL', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.del', async client => { + testUtils.testWithClient('client.del', async client => { assert.equal( await client.del('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/DEL.ts b/packages/client/lib/commands/DEL.ts similarity index 100% rename from lib/commands/DEL.ts rename to packages/client/lib/commands/DEL.ts diff --git a/lib/commands/DISCARD.spec.ts b/packages/client/lib/commands/DISCARD.spec.ts similarity index 100% rename from lib/commands/DISCARD.spec.ts rename to packages/client/lib/commands/DISCARD.spec.ts diff --git a/lib/commands/DISCARD.ts b/packages/client/lib/commands/DISCARD.ts similarity index 100% rename from lib/commands/DISCARD.ts rename to packages/client/lib/commands/DISCARD.ts diff --git a/lib/commands/DUMP.spec.ts b/packages/client/lib/commands/DUMP.spec.ts similarity index 52% rename from lib/commands/DUMP.spec.ts rename to packages/client/lib/commands/DUMP.spec.ts index e3f42c57578..aebbf4f3f7c 100644 --- a/lib/commands/DUMP.spec.ts +++ b/packages/client/lib/commands/DUMP.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; describe('DUMP', () => { - itWithClient(TestRedisServers.OPEN, 'client.dump', async client => { + testUtils.testWithClient('client.dump', async client => { assert.equal( await client.dump('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/DUMP.ts b/packages/client/lib/commands/DUMP.ts similarity index 100% rename from lib/commands/DUMP.ts rename to packages/client/lib/commands/DUMP.ts diff --git a/lib/commands/ECHO.spec.ts b/packages/client/lib/commands/ECHO.spec.ts similarity index 72% rename from lib/commands/ECHO.spec.ts rename to packages/client/lib/commands/ECHO.spec.ts index d91b7373950..27f6b2a17d3 100644 --- a/lib/commands/ECHO.spec.ts +++ b/packages/client/lib/commands/ECHO.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ECHO'; describe('ECHO', () => { @@ -10,10 +10,10 @@ describe('ECHO', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.echo', async client => { + testUtils.testWithClient('client.echo', async client => { assert.equal( await client.echo('message'), 'message' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ECHO.ts b/packages/client/lib/commands/ECHO.ts similarity index 100% rename from lib/commands/ECHO.ts rename to packages/client/lib/commands/ECHO.ts diff --git a/lib/commands/EVAL.spec.ts b/packages/client/lib/commands/EVAL.spec.ts similarity index 69% rename from lib/commands/EVAL.spec.ts rename to packages/client/lib/commands/EVAL.spec.ts index 2be1aedf08a..7aa029362fd 100644 --- a/lib/commands/EVAL.spec.ts +++ b/packages/client/lib/commands/EVAL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './EVAL'; describe('EVAL', () => { @@ -13,17 +13,17 @@ describe('EVAL', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.eval', async client => { + testUtils.testWithClient('client.eval', async client => { assert.equal( await client.eval('return 1'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.eval', async cluster => { + testUtils.testWithCluster('cluster.eval', async cluster => { assert.equal( await cluster.eval('return 1'), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/EVAL.ts b/packages/client/lib/commands/EVAL.ts similarity index 100% rename from lib/commands/EVAL.ts rename to packages/client/lib/commands/EVAL.ts diff --git a/lib/commands/EVALSHA.spec.ts b/packages/client/lib/commands/EVALSHA.spec.ts similarity index 100% rename from lib/commands/EVALSHA.spec.ts rename to packages/client/lib/commands/EVALSHA.spec.ts diff --git a/lib/commands/EVALSHA.ts b/packages/client/lib/commands/EVALSHA.ts similarity index 100% rename from lib/commands/EVALSHA.ts rename to packages/client/lib/commands/EVALSHA.ts diff --git a/lib/commands/EXISTS.spec.ts b/packages/client/lib/commands/EXISTS.spec.ts similarity index 80% rename from lib/commands/EXISTS.spec.ts rename to packages/client/lib/commands/EXISTS.spec.ts index 3cba44b563f..241a97c362e 100644 --- a/lib/commands/EXISTS.spec.ts +++ b/packages/client/lib/commands/EXISTS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './EXISTS'; describe('EXISTS', () => { @@ -19,10 +19,10 @@ describe('EXISTS', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.exists', async client => { + testUtils.testWithClient('client.exists', async client => { assert.equal( await client.exists('key'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/EXISTS.ts b/packages/client/lib/commands/EXISTS.ts similarity index 64% rename from lib/commands/EXISTS.ts rename to packages/client/lib/commands/EXISTS.ts index aac164fc953..5a9c0e3be66 100644 --- a/lib/commands/EXISTS.ts +++ b/packages/client/lib/commands/EXISTS.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments, transformReplyBoolean } from './generic-transformers'; +import { pushVerdictArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,4 +9,4 @@ export function transformArguments(keys: string | Array): RedisCommandAr return pushVerdictArguments(['EXISTS'], keys); } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/EXPIRE.spec.ts b/packages/client/lib/commands/EXPIRE.spec.ts similarity index 71% rename from lib/commands/EXPIRE.spec.ts rename to packages/client/lib/commands/EXPIRE.spec.ts index 6550532cab2..e2dc6e03123 100644 --- a/lib/commands/EXPIRE.spec.ts +++ b/packages/client/lib/commands/EXPIRE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './EXPIRE'; describe('EXPIRE', () => { @@ -10,10 +10,10 @@ describe('EXPIRE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.expire', async client => { + testUtils.testWithClient('client.expire', async client => { assert.equal( await client.expire('key', 0), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/EXPIRE.ts b/packages/client/lib/commands/EXPIRE.ts similarity index 52% rename from lib/commands/EXPIRE.ts rename to packages/client/lib/commands/EXPIRE.ts index 04b0504a6f7..36bcf8b882d 100644 --- a/lib/commands/EXPIRE.ts +++ b/packages/client/lib/commands/EXPIRE.ts @@ -1,7 +1,5 @@ -import { transformReplyBoolean } from './generic-transformers'; - export function transformArguments(key: string, seconds: number): Array { return ['EXPIRE', key, seconds.toString()]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/EXPIREAT.spec.ts b/packages/client/lib/commands/EXPIREAT.spec.ts similarity index 81% rename from lib/commands/EXPIREAT.spec.ts rename to packages/client/lib/commands/EXPIREAT.spec.ts index cefe9fa9b8b..1a11af1a735 100644 --- a/lib/commands/EXPIREAT.spec.ts +++ b/packages/client/lib/commands/EXPIREAT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './EXPIREAT'; describe('EXPIREAT', () => { @@ -10,7 +10,7 @@ describe('EXPIREAT', () => { ['EXPIREAT', 'key', '1'] ); }); - + it('date', () => { const d = new Date(); assert.deepEqual( @@ -20,10 +20,10 @@ describe('EXPIREAT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.expireAt', async client => { + testUtils.testWithClient('client.expireAt', async client => { assert.equal( await client.expireAt('key', 1), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/EXPIREAT.ts b/packages/client/lib/commands/EXPIREAT.ts similarity index 56% rename from lib/commands/EXPIREAT.ts rename to packages/client/lib/commands/EXPIREAT.ts index b7bfdcaa422..72142e4cb79 100644 --- a/lib/commands/EXPIREAT.ts +++ b/packages/client/lib/commands/EXPIREAT.ts @@ -1,4 +1,4 @@ -import { transformEXAT, transformReplyBoolean } from './generic-transformers'; +import { transformEXAT } from './generic-transformers'; export function transformArguments(key: string, timestamp: number | Date): Array { return [ @@ -8,4 +8,4 @@ export function transformArguments(key: string, timestamp: number | Date): Array ]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/FAILOVER.spec.ts b/packages/client/lib/commands/FAILOVER.spec.ts similarity index 100% rename from lib/commands/FAILOVER.spec.ts rename to packages/client/lib/commands/FAILOVER.spec.ts diff --git a/lib/commands/FAILOVER.ts b/packages/client/lib/commands/FAILOVER.ts similarity index 100% rename from lib/commands/FAILOVER.ts rename to packages/client/lib/commands/FAILOVER.ts diff --git a/lib/commands/FLUSHALL.spec.ts b/packages/client/lib/commands/FLUSHALL.spec.ts similarity index 84% rename from lib/commands/FLUSHALL.spec.ts rename to packages/client/lib/commands/FLUSHALL.spec.ts index 7f1c5ffd282..db5bb72e9cb 100644 --- a/lib/commands/FLUSHALL.spec.ts +++ b/packages/client/lib/commands/FLUSHALL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { RedisFlushModes, transformArguments } from './FLUSHALL'; describe('FLUSHALL', () => { @@ -26,10 +26,10 @@ describe('FLUSHALL', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.flushAll', async client => { + testUtils.testWithClient('client.flushAll', async client => { assert.equal( await client.flushAll(), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/FLUSHALL.ts b/packages/client/lib/commands/FLUSHALL.ts similarity index 100% rename from lib/commands/FLUSHALL.ts rename to packages/client/lib/commands/FLUSHALL.ts diff --git a/lib/commands/FLUSHDB.spec.ts b/packages/client/lib/commands/FLUSHDB.spec.ts similarity index 84% rename from lib/commands/FLUSHDB.spec.ts rename to packages/client/lib/commands/FLUSHDB.spec.ts index e237e527680..bf460e9e7a8 100644 --- a/lib/commands/FLUSHDB.spec.ts +++ b/packages/client/lib/commands/FLUSHDB.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { RedisFlushModes } from './FLUSHALL'; import { transformArguments } from './FLUSHDB'; @@ -27,10 +27,10 @@ describe('FLUSHDB', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.flushDb', async client => { + testUtils.testWithClient('client.flushDb', async client => { assert.equal( await client.flushDb(), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/FLUSHDB.ts b/packages/client/lib/commands/FLUSHDB.ts similarity index 100% rename from lib/commands/FLUSHDB.ts rename to packages/client/lib/commands/FLUSHDB.ts diff --git a/lib/commands/GEOADD.spec.ts b/packages/client/lib/commands/GEOADD.spec.ts similarity index 90% rename from lib/commands/GEOADD.spec.ts rename to packages/client/lib/commands/GEOADD.spec.ts index 673e962093f..6425c881c9d 100644 --- a/lib/commands/GEOADD.spec.ts +++ b/packages/client/lib/commands/GEOADD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GEOADD'; describe('GEOADD', () => { @@ -71,7 +71,7 @@ describe('GEOADD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.geoAdd', async client => { + testUtils.testWithClient('client.geoAdd', async client => { assert.equal( await client.geoAdd('key', { member: 'member', @@ -80,9 +80,9 @@ describe('GEOADD', () => { }), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoAdd', async cluster => { + testUtils.testWithCluster('cluster.geoAdd', async cluster => { assert.equal( await cluster.geoAdd('key', { member: 'member', @@ -91,5 +91,5 @@ describe('GEOADD', () => { }), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOADD.ts b/packages/client/lib/commands/GEOADD.ts similarity index 100% rename from lib/commands/GEOADD.ts rename to packages/client/lib/commands/GEOADD.ts diff --git a/lib/commands/GEODIST.spec.ts b/packages/client/lib/commands/GEODIST.spec.ts similarity index 78% rename from lib/commands/GEODIST.spec.ts rename to packages/client/lib/commands/GEODIST.spec.ts index 2cff8ecbd82..bbc62480ee1 100644 --- a/lib/commands/GEODIST.spec.ts +++ b/packages/client/lib/commands/GEODIST.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GEODIST'; describe('GEODIST', () => { @@ -20,14 +20,14 @@ describe('GEODIST', () => { }); describe('client.geoDist', () => { - itWithClient(TestRedisServers.OPEN, 'null', async client => { + testUtils.testWithClient('null', async client => { assert.equal( await client.geoDist('key', '1', '2'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'with value', async client => { + testUtils.testWithClient('with value', async client => { const [, dist] = await Promise.all([ client.geoAdd('key', [{ member: '1', @@ -45,13 +45,13 @@ describe('GEODIST', () => { dist, 157270.0561 ); - }); + }, GLOBAL.SERVERS.OPEN); }); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoDist', async cluster => { + testUtils.testWithCluster('cluster.geoDist', async cluster => { assert.equal( await cluster.geoDist('key', '1', '2'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEODIST.ts b/packages/client/lib/commands/GEODIST.ts similarity index 100% rename from lib/commands/GEODIST.ts rename to packages/client/lib/commands/GEODIST.ts diff --git a/lib/commands/GEOHASH.spec.ts b/packages/client/lib/commands/GEOHASH.spec.ts similarity index 74% rename from lib/commands/GEOHASH.spec.ts rename to packages/client/lib/commands/GEOHASH.spec.ts index b79de235557..c421c148f43 100644 --- a/lib/commands/GEOHASH.spec.ts +++ b/packages/client/lib/commands/GEOHASH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GEOHASH'; describe('GEOHASH', () => { @@ -19,17 +19,17 @@ describe('GEOHASH', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.geoHash', async client => { + testUtils.testWithClient('client.geoHash', async client => { assert.deepEqual( await client.geoHash('key', 'member'), [null] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoHash', async cluster => { + testUtils.testWithCluster('cluster.geoHash', async cluster => { assert.deepEqual( await cluster.geoHash('key', 'member'), [null] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOHASH.ts b/packages/client/lib/commands/GEOHASH.ts similarity index 100% rename from lib/commands/GEOHASH.ts rename to packages/client/lib/commands/GEOHASH.ts diff --git a/lib/commands/GEOPOS.spec.ts b/packages/client/lib/commands/GEOPOS.spec.ts similarity index 82% rename from lib/commands/GEOPOS.spec.ts rename to packages/client/lib/commands/GEOPOS.spec.ts index e15abeff516..9c08ccd08f5 100644 --- a/lib/commands/GEOPOS.spec.ts +++ b/packages/client/lib/commands/GEOPOS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './GEOPOS'; describe('GEOPOS', () => { @@ -39,14 +39,14 @@ describe('GEOPOS', () => { }); describe('client.geoPos', () => { - itWithClient(TestRedisServers.OPEN, 'null', async client => { + testUtils.testWithClient('null', async client => { assert.deepEqual( await client.geoPos('key', 'member'), [null] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'with member', async client => { + testUtils.testWithClient('with member', async client => { const coordinates = { longitude: '-122.06429868936538696', latitude: '37.37749628831998194' @@ -61,13 +61,13 @@ describe('GEOPOS', () => { await client.geoPos('key', 'member'), [coordinates] ); - }); + }, GLOBAL.SERVERS.OPEN); }); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoPos', async cluster => { + testUtils.testWithCluster('cluster.geoPos', async cluster => { assert.deepEqual( await cluster.geoPos('key', 'member'), [null] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOPOS.ts b/packages/client/lib/commands/GEOPOS.ts similarity index 100% rename from lib/commands/GEOPOS.ts rename to packages/client/lib/commands/GEOPOS.ts diff --git a/lib/commands/GEOSEARCH.spec.ts b/packages/client/lib/commands/GEOSEARCH.spec.ts similarity index 68% rename from lib/commands/GEOSEARCH.spec.ts rename to packages/client/lib/commands/GEOSEARCH.spec.ts index a8606b3f74c..ec0d4bcc4f8 100644 --- a/lib/commands/GEOSEARCH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GEOSEARCH'; describe('GEOSEARCH', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -15,7 +15,7 @@ describe('GEOSEARCH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.geoSearch', async client => { + testUtils.testWithClient('client.geoSearch', async client => { assert.deepEqual( await client.geoSearch('key', 'member', { radius: 1, @@ -23,9 +23,9 @@ describe('GEOSEARCH', () => { }), [] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoSearch', async cluster => { + testUtils.testWithCluster('cluster.geoSearch', async cluster => { assert.deepEqual( await cluster.geoSearch('key', 'member', { radius: 1, @@ -33,5 +33,5 @@ describe('GEOSEARCH', () => { }), [] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOSEARCH.ts b/packages/client/lib/commands/GEOSEARCH.ts similarity index 100% rename from lib/commands/GEOSEARCH.ts rename to packages/client/lib/commands/GEOSEARCH.ts diff --git a/lib/commands/GEOSEARCHSTORE.spec.ts b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts similarity index 85% rename from lib/commands/GEOSEARCHSTORE.spec.ts rename to packages/client/lib/commands/GEOSEARCHSTORE.spec.ts index ad33c62b78c..eb32fa134e4 100644 --- a/lib/commands/GEOSEARCHSTORE.spec.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './GEOSEARCHSTORE'; describe('GEOSEARCHSTORE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('simple', () => { @@ -47,7 +47,7 @@ describe('GEOSEARCHSTORE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.geoSearchStore', async client => { + testUtils.testWithClient('client.geoSearchStore', async client => { await client.geoAdd('source', { longitude: 1, latitude: 1, @@ -61,9 +61,9 @@ describe('GEOSEARCHSTORE', () => { }), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoSearchStore', async cluster => { + testUtils.testWithCluster('cluster.geoSearchStore', async cluster => { await cluster.geoAdd('{tag}source', { longitude: 1, latitude: 1, @@ -77,5 +77,5 @@ describe('GEOSEARCHSTORE', () => { }), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOSEARCHSTORE.ts b/packages/client/lib/commands/GEOSEARCHSTORE.ts similarity index 100% rename from lib/commands/GEOSEARCHSTORE.ts rename to packages/client/lib/commands/GEOSEARCHSTORE.ts diff --git a/lib/commands/GEOSEARCH_WITH.spec.ts b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts similarity index 74% rename from lib/commands/GEOSEARCH_WITH.spec.ts rename to packages/client/lib/commands/GEOSEARCH_WITH.spec.ts index 922c00d7194..c1f5213775a 100644 --- a/lib/commands/GEOSEARCH_WITH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; import { RedisCommandArguments } from '.'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; import { GeoReplyWith } from './generic-transformers'; import { transformArguments } from './GEOSEARCH_WITH'; describe('GEOSEARCH WITH', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST'] + const expectedReply: RedisCommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST']; expectedReply.preserve = ['WITHDIST']; assert.deepEqual( @@ -20,7 +20,7 @@ describe('GEOSEARCH WITH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.geoSearchWith', async client => { + testUtils.testWithClient('client.geoSearchWith', async client => { assert.deepEqual( await client.geoSearchWith('key', 'member', { radius: 1, @@ -28,9 +28,9 @@ describe('GEOSEARCH WITH', () => { }, [GeoReplyWith.DISTANCE]), [] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.geoSearchWith', async cluster => { + testUtils.testWithCluster('cluster.geoSearchWith', async cluster => { assert.deepEqual( await cluster.geoSearchWith('key', 'member', { radius: 1, @@ -38,5 +38,5 @@ describe('GEOSEARCH WITH', () => { }, [GeoReplyWith.DISTANCE]), [] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts similarity index 82% rename from lib/commands/GEOSEARCH_WITH.ts rename to packages/client/lib/commands/GEOSEARCH_WITH.ts index cd461c9677f..64c6d88e33c 100644 --- a/lib/commands/GEOSEARCH_WITH.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions, transformGeoMembersWithReply } from './generic-transformers'; +import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions } from './generic-transformers'; import { transformArguments as geoSearchTransformArguments } from './GEOSEARCH'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; @@ -20,4 +20,4 @@ export function transformArguments( return args; } -export const transformReply = transformGeoMembersWithReply; +export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/lib/commands/GET.spec.ts b/packages/client/lib/commands/GET.spec.ts similarity index 62% rename from lib/commands/GET.spec.ts rename to packages/client/lib/commands/GET.spec.ts index 303be60fe99..4c197f99a4e 100644 --- a/lib/commands/GET.spec.ts +++ b/packages/client/lib/commands/GET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GET'; describe('GET', () => { @@ -10,17 +10,17 @@ describe('GET', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.get', async client => { + testUtils.testWithClient('client.get', async client => { assert.equal( await client.get('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.get', async cluster => { + testUtils.testWithCluster('cluster.get', async cluster => { assert.equal( await cluster.get('key'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GET.ts b/packages/client/lib/commands/GET.ts similarity index 100% rename from lib/commands/GET.ts rename to packages/client/lib/commands/GET.ts diff --git a/lib/commands/GETBIT.spec.ts b/packages/client/lib/commands/GETBIT.spec.ts similarity index 63% rename from lib/commands/GETBIT.spec.ts rename to packages/client/lib/commands/GETBIT.spec.ts index 7163b4ba255..4206084eced 100644 --- a/lib/commands/GETBIT.spec.ts +++ b/packages/client/lib/commands/GETBIT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GETBIT'; describe('GETBIT', () => { @@ -10,17 +10,17 @@ describe('GETBIT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.getBit', async client => { + testUtils.testWithClient('client.getBit', async client => { assert.equal( await client.getBit('key', 0), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.getBit', async cluster => { + testUtils.testWithCluster('cluster.getBit', async cluster => { assert.equal( await cluster.getBit('key', 0), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GETBIT.ts b/packages/client/lib/commands/GETBIT.ts similarity index 100% rename from lib/commands/GETBIT.ts rename to packages/client/lib/commands/GETBIT.ts diff --git a/lib/commands/GETDEL.spec.ts b/packages/client/lib/commands/GETDEL.spec.ts similarity index 56% rename from lib/commands/GETDEL.spec.ts rename to packages/client/lib/commands/GETDEL.spec.ts index 232c08b9500..db3a486696a 100644 --- a/lib/commands/GETDEL.spec.ts +++ b/packages/client/lib/commands/GETDEL.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GETDEL'; describe('GETDEL', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,18 +12,17 @@ describe('GETDEL', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.getDel', async client => { + testUtils.testWithClient('client.getDel', async client => { assert.equal( await client.getDel('key'), null ); - }); - + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.getDel', async cluster => { + testUtils.testWithCluster('cluster.getDel', async cluster => { assert.equal( await cluster.getDel('key'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GETDEL.ts b/packages/client/lib/commands/GETDEL.ts similarity index 100% rename from lib/commands/GETDEL.ts rename to packages/client/lib/commands/GETDEL.ts diff --git a/lib/commands/GETEX.spec.ts b/packages/client/lib/commands/GETEX.spec.ts similarity index 87% rename from lib/commands/GETEX.spec.ts rename to packages/client/lib/commands/GETEX.spec.ts index 830f12cedf8..1bf86089da1 100644 --- a/lib/commands/GETEX.spec.ts +++ b/packages/client/lib/commands/GETEX.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GETEX'; describe('GETEX', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('EX', () => { @@ -76,21 +76,21 @@ describe('GETEX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.getEx', async client => { + testUtils.testWithClient('client.getEx', async client => { assert.equal( await client.getEx('key', { PERSIST: true }), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.getEx', async cluster => { + testUtils.testWithCluster('cluster.getEx', async cluster => { assert.equal( await cluster.getEx('key', { PERSIST: true }), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GETEX.ts b/packages/client/lib/commands/GETEX.ts similarity index 100% rename from lib/commands/GETEX.ts rename to packages/client/lib/commands/GETEX.ts diff --git a/lib/commands/GETRANGE.spec.ts b/packages/client/lib/commands/GETRANGE.spec.ts similarity index 64% rename from lib/commands/GETRANGE.spec.ts rename to packages/client/lib/commands/GETRANGE.spec.ts index 726311e6844..0c9dbc2c70f 100644 --- a/lib/commands/GETRANGE.spec.ts +++ b/packages/client/lib/commands/GETRANGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GETRANGE'; describe('GETRANGE', () => { @@ -10,18 +10,17 @@ describe('GETRANGE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.getRange', async client => { + testUtils.testWithClient('client.getRange', async client => { assert.equal( await client.getRange('key', 0, -1), '' ); - }); - + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lTrim', async cluster => { + testUtils.testWithCluster('cluster.lTrim', async cluster => { assert.equal( await cluster.getRange('key', 0, -1), '' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GETRANGE.ts b/packages/client/lib/commands/GETRANGE.ts similarity index 100% rename from lib/commands/GETRANGE.ts rename to packages/client/lib/commands/GETRANGE.ts diff --git a/lib/commands/GETSET.spec.ts b/packages/client/lib/commands/GETSET.spec.ts similarity index 64% rename from lib/commands/GETSET.spec.ts rename to packages/client/lib/commands/GETSET.spec.ts index 4af5ab39ca2..73fbcec57ea 100644 --- a/lib/commands/GETSET.spec.ts +++ b/packages/client/lib/commands/GETSET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './GETSET'; describe('GETSET', () => { @@ -10,17 +10,17 @@ describe('GETSET', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.getSet', async client => { + testUtils.testWithClient('client.getSet', async client => { assert.equal( await client.getSet('key', 'value'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.getSet', async cluster => { + testUtils.testWithCluster('cluster.getSet', async cluster => { assert.equal( await cluster.getSet('key', 'value'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GETSET.ts b/packages/client/lib/commands/GETSET.ts similarity index 100% rename from lib/commands/GETSET.ts rename to packages/client/lib/commands/GETSET.ts diff --git a/lib/commands/GET_BUFFER.spec.ts b/packages/client/lib/commands/GET_BUFFER.spec.ts similarity index 62% rename from lib/commands/GET_BUFFER.spec.ts rename to packages/client/lib/commands/GET_BUFFER.spec.ts index 533eb808c49..1f1a86799f4 100644 --- a/lib/commands/GET_BUFFER.spec.ts +++ b/packages/client/lib/commands/GET_BUFFER.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; describe('GET_BUFFER', () => { - itWithClient(TestRedisServers.OPEN, 'client.getBuffer', async client => { + testUtils.testWithClient('client.getBuffer', async client => { const buffer = Buffer.from('string'); await client.set('key', buffer); assert.deepEqual( buffer, await client.getBuffer('key') ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.getBuffer', async cluster => { + testUtils.testWithCluster('cluster.getBuffer', async cluster => { const buffer = Buffer.from('string'); await cluster.set('key', buffer); assert.deepEqual( buffer, await cluster.getBuffer('key') ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/GET_BUFFER.ts b/packages/client/lib/commands/GET_BUFFER.ts similarity index 100% rename from lib/commands/GET_BUFFER.ts rename to packages/client/lib/commands/GET_BUFFER.ts diff --git a/lib/commands/HDEL.spec.ts b/packages/client/lib/commands/HDEL.spec.ts similarity index 81% rename from lib/commands/HDEL.spec.ts rename to packages/client/lib/commands/HDEL.spec.ts index 04191f51ada..eb24bcfacbd 100644 --- a/lib/commands/HDEL.spec.ts +++ b/packages/client/lib/commands/HDEL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HDEL'; describe('HDEL', () => { @@ -19,10 +19,10 @@ describe('HDEL', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hDel', async client => { + testUtils.testWithClient('client.hDel', async client => { assert.equal( await client.hDel('key', 'field'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HDEL.ts b/packages/client/lib/commands/HDEL.ts similarity index 100% rename from lib/commands/HDEL.ts rename to packages/client/lib/commands/HDEL.ts diff --git a/lib/commands/HELLO.spec.ts b/packages/client/lib/commands/HELLO.spec.ts similarity index 73% rename from lib/commands/HELLO.spec.ts rename to packages/client/lib/commands/HELLO.spec.ts index 7642f739d92..12d6d98c7c9 100644 --- a/lib/commands/HELLO.spec.ts +++ b/packages/client/lib/commands/HELLO.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { REDIS_VERSION, TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HELLO'; describe('HELLO', () => { - describeHandleMinimumRedisVersion([6]); + testUtils.isVersionGreaterThanHook([6]); describe('transformArguments', () => { it('simple', () => { @@ -60,18 +60,17 @@ describe('HELLO', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hello', async client => { - assert.deepEqual( - await client.hello(), - { - server: 'redis', - version: REDIS_VERSION.join('.'), - proto: 2, - id: await client.clientId(), - mode: 'standalone', - role: 'master', - modules: [] - } - ); + testUtils.testWithClient('client.hello', async client => { + const reply = await client.hello(); + assert.equal(reply.server, 'redis'); + assert.equal(typeof reply.version, 'string'); + assert.equal(reply.proto, 2); + assert.equal(typeof reply.id, 'number'); + assert.equal(reply.mode, 'standalone'); + assert.equal(reply.role, 'master'); + assert.deepEqual(reply.modules, []); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] }); }); diff --git a/lib/commands/HELLO.ts b/packages/client/lib/commands/HELLO.ts similarity index 100% rename from lib/commands/HELLO.ts rename to packages/client/lib/commands/HELLO.ts diff --git a/lib/commands/HEXISTS.spec.ts b/packages/client/lib/commands/HEXISTS.spec.ts similarity index 72% rename from lib/commands/HEXISTS.spec.ts rename to packages/client/lib/commands/HEXISTS.spec.ts index 26c411c432d..3764319c123 100644 --- a/lib/commands/HEXISTS.spec.ts +++ b/packages/client/lib/commands/HEXISTS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HEXISTS'; describe('HEXISTS', () => { @@ -10,10 +10,10 @@ describe('HEXISTS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hExists', async client => { + testUtils.testWithClient('client.hExists', async client => { assert.equal( await client.hExists('key', 'field'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HEXISTS.ts b/packages/client/lib/commands/HEXISTS.ts similarity index 56% rename from lib/commands/HEXISTS.ts rename to packages/client/lib/commands/HEXISTS.ts index 7cf0b158d92..0eae5e03e52 100644 --- a/lib/commands/HEXISTS.ts +++ b/packages/client/lib/commands/HEXISTS.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, field: string): Array { return ['HEXISTS', key, field]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/HGET.spec.ts b/packages/client/lib/commands/HGET.spec.ts similarity index 72% rename from lib/commands/HGET.spec.ts rename to packages/client/lib/commands/HGET.spec.ts index c78550c5179..6b6d0a3ee22 100644 --- a/lib/commands/HGET.spec.ts +++ b/packages/client/lib/commands/HGET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HGET'; describe('HGET', () => { @@ -10,10 +10,10 @@ describe('HGET', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hGet', async client => { + testUtils.testWithClient('client.hGet', async client => { assert.equal( await client.hGet('key', 'field'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HGET.ts b/packages/client/lib/commands/HGET.ts similarity index 100% rename from lib/commands/HGET.ts rename to packages/client/lib/commands/HGET.ts diff --git a/lib/commands/HGETALL.spec.ts b/packages/client/lib/commands/HGETALL.spec.ts similarity index 88% rename from lib/commands/HGETALL.spec.ts rename to packages/client/lib/commands/HGETALL.spec.ts index 68b51a2902b..fcd1a30457c 100644 --- a/lib/commands/HGETALL.spec.ts +++ b/packages/client/lib/commands/HGETALL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformReply } from './HGETALL'; describe('HGETALL', () => { @@ -32,10 +32,10 @@ describe('HGETALL', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hGetAll', async client => { + testUtils.testWithClient('client.hGetAll', async client => { assert.deepEqual( await client.hGetAll('key'), Object.create(null) ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HGETALL.ts b/packages/client/lib/commands/HGETALL.ts similarity index 53% rename from lib/commands/HGETALL.ts rename to packages/client/lib/commands/HGETALL.ts index 8ac14ec4963..55c6d3456a1 100644 --- a/lib/commands/HGETALL.ts +++ b/packages/client/lib/commands/HGETALL.ts @@ -1,9 +1,7 @@ -import { transformReplyTuples } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string): Array { return ['HGETALL', key]; } -export const transformReply = transformReplyTuples; +export { transformReplyTuples as transformReply } from './generic-transformers'; diff --git a/lib/commands/HINCRBY.spec.ts b/packages/client/lib/commands/HINCRBY.spec.ts similarity index 73% rename from lib/commands/HINCRBY.spec.ts rename to packages/client/lib/commands/HINCRBY.spec.ts index 898dfd1172f..de406217921 100644 --- a/lib/commands/HINCRBY.spec.ts +++ b/packages/client/lib/commands/HINCRBY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HINCRBY'; describe('HINCRBY', () => { @@ -10,10 +10,10 @@ describe('HINCRBY', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hIncrBy', async client => { + testUtils.testWithClient('client.hIncrBy', async client => { assert.equal( await client.hIncrBy('key', 'field', 1), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HINCRBY.ts b/packages/client/lib/commands/HINCRBY.ts similarity index 100% rename from lib/commands/HINCRBY.ts rename to packages/client/lib/commands/HINCRBY.ts diff --git a/lib/commands/HINCRBYFLOAT.spec.ts b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts similarity index 73% rename from lib/commands/HINCRBYFLOAT.spec.ts rename to packages/client/lib/commands/HINCRBYFLOAT.spec.ts index 83e87538c54..bd0147a3481 100644 --- a/lib/commands/HINCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HINCRBYFLOAT'; describe('HINCRBYFLOAT', () => { @@ -10,10 +10,10 @@ describe('HINCRBYFLOAT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hIncrByFloat', async client => { + testUtils.testWithClient('client.hIncrByFloat', async client => { assert.equal( await client.hIncrByFloat('key', 'field', 1.5), '1.5' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HINCRBYFLOAT.ts b/packages/client/lib/commands/HINCRBYFLOAT.ts similarity index 100% rename from lib/commands/HINCRBYFLOAT.ts rename to packages/client/lib/commands/HINCRBYFLOAT.ts diff --git a/lib/commands/HKEYS.spec.ts b/packages/client/lib/commands/HKEYS.spec.ts similarity index 71% rename from lib/commands/HKEYS.spec.ts rename to packages/client/lib/commands/HKEYS.spec.ts index 12190668b0b..f94538f67d3 100644 --- a/lib/commands/HKEYS.spec.ts +++ b/packages/client/lib/commands/HKEYS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HKEYS'; describe('HKEYS', () => { @@ -10,10 +10,10 @@ describe('HKEYS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hKeys', async client => { + testUtils.testWithClient('client.hKeys', async client => { assert.deepEqual( await client.hKeys('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HKEYS.ts b/packages/client/lib/commands/HKEYS.ts similarity index 100% rename from lib/commands/HKEYS.ts rename to packages/client/lib/commands/HKEYS.ts diff --git a/lib/commands/HLEN.spec.ts b/packages/client/lib/commands/HLEN.spec.ts similarity index 70% rename from lib/commands/HLEN.spec.ts rename to packages/client/lib/commands/HLEN.spec.ts index e9aaa64e6e5..be9d4b13a7d 100644 --- a/lib/commands/HLEN.spec.ts +++ b/packages/client/lib/commands/HLEN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HLEN'; describe('HLEN', () => { @@ -10,10 +10,10 @@ describe('HLEN', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hLen', async client => { + testUtils.testWithClient('client.hLen', async client => { assert.equal( await client.hLen('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HLEN.ts b/packages/client/lib/commands/HLEN.ts similarity index 100% rename from lib/commands/HLEN.ts rename to packages/client/lib/commands/HLEN.ts diff --git a/lib/commands/HMGET.spec.ts b/packages/client/lib/commands/HMGET.spec.ts similarity index 81% rename from lib/commands/HMGET.spec.ts rename to packages/client/lib/commands/HMGET.spec.ts index 3b1c286e748..a7c934b760d 100644 --- a/lib/commands/HMGET.spec.ts +++ b/packages/client/lib/commands/HMGET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HMGET'; describe('HMGET', () => { @@ -19,10 +19,10 @@ describe('HMGET', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hmGet', async client => { + testUtils.testWithClient('client.hmGet', async client => { assert.deepEqual( await client.hmGet('key', 'field'), [null] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HMGET.ts b/packages/client/lib/commands/HMGET.ts similarity index 100% rename from lib/commands/HMGET.ts rename to packages/client/lib/commands/HMGET.ts diff --git a/lib/commands/HRANDFIELD.spec.ts b/packages/client/lib/commands/HRANDFIELD.spec.ts similarity index 62% rename from lib/commands/HRANDFIELD.spec.ts rename to packages/client/lib/commands/HRANDFIELD.spec.ts index 70e2585cf93..df0a4fc7a1d 100644 --- a/lib/commands/HRANDFIELD.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HRANDFIELD'; describe('HRANDFIELD', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('HRANDFIELD', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hRandField', async client => { + testUtils.testWithClient('client.hRandField', async client => { assert.equal( await client.hRandField('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HRANDFIELD.ts b/packages/client/lib/commands/HRANDFIELD.ts similarity index 100% rename from lib/commands/HRANDFIELD.ts rename to packages/client/lib/commands/HRANDFIELD.ts diff --git a/lib/commands/HRANDFIELD_COUNT.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts similarity index 63% rename from lib/commands/HRANDFIELD_COUNT.spec.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts index 6954bd484af..4bfce0f7e23 100644 --- a/lib/commands/HRANDFIELD_COUNT.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HRANDFIELD_COUNT'; describe('HRANDFIELD COUNT', () => { - describeHandleMinimumRedisVersion([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('HRANDFIELD COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hRandFieldCount', async client => { + testUtils.testWithClient('client.hRandFieldCount', async client => { assert.deepEqual( await client.hRandFieldCount('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HRANDFIELD_COUNT.ts b/packages/client/lib/commands/HRANDFIELD_COUNT.ts similarity index 100% rename from lib/commands/HRANDFIELD_COUNT.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT.ts diff --git a/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts similarity index 65% rename from lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts index 0c26cbc7938..c4e6409a726 100644 --- a/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HRANDFIELD_COUNT_WITHVALUES'; describe('HRANDFIELD COUNT WITHVALUES', () => { - describeHandleMinimumRedisVersion([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('HRANDFIELD COUNT WITHVALUES', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hRandFieldCountWithValues', async client => { + testUtils.testWithClient('client.hRandFieldCountWithValues', async client => { assert.deepEqual( await client.hRandFieldCountWithValues('key', 1), Object.create(null) ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts similarity index 74% rename from lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts index 53856c1984e..1769cae0b76 100644 --- a/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts @@ -1,4 +1,3 @@ -import { transformReplyTuples } from './generic-transformers'; import { transformArguments as transformHRandFieldCountArguments } from './HRANDFIELD_COUNT'; export { FIRST_KEY_INDEX } from './HRANDFIELD_COUNT'; @@ -10,4 +9,4 @@ export function transformArguments(key: string, count: number): Array { ]; } -export const transformReply = transformReplyTuples; +export { transformReplyTuples as transformReply } from './generic-transformers'; diff --git a/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts similarity index 93% rename from lib/commands/HSCAN.spec.ts rename to packages/client/lib/commands/HSCAN.spec.ts index 7441dd48d52..b426763b99b 100644 --- a/lib/commands/HSCAN.spec.ts +++ b/packages/client/lib/commands/HSCAN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './HSCAN'; describe('HSCAN', () => { @@ -65,7 +65,7 @@ describe('HSCAN', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hScan', async client => { + testUtils.testWithClient('client.hScan', async client => { assert.deepEqual( await client.hScan('key', 0), { @@ -73,5 +73,5 @@ describe('HSCAN', () => { tuples: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HSCAN.ts b/packages/client/lib/commands/HSCAN.ts similarity index 100% rename from lib/commands/HSCAN.ts rename to packages/client/lib/commands/HSCAN.ts diff --git a/lib/commands/HSET.spec.ts b/packages/client/lib/commands/HSET.spec.ts similarity index 81% rename from lib/commands/HSET.spec.ts rename to packages/client/lib/commands/HSET.spec.ts index e8dfe7865d3..507c7bbbf74 100644 --- a/lib/commands/HSET.spec.ts +++ b/packages/client/lib/commands/HSET.spec.ts @@ -1,6 +1,6 @@ import { strict as assert } from 'assert'; import { transformArguments } from './HSET'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; describe('HSET', () => { describe('transformArguments', () => { @@ -33,17 +33,17 @@ describe('HSET', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.hSet', async client => { + testUtils.testWithClient('client.hSet', async client => { assert.equal( await client.hSet('key', 'field', 'value'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.hSet', async cluster => { + testUtils.testWithCluster('cluster.hSet', async cluster => { assert.equal( await cluster.hSet('key', { field: 'value' }), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); \ No newline at end of file diff --git a/lib/commands/HSET.ts b/packages/client/lib/commands/HSET.ts similarity index 92% rename from lib/commands/HSET.ts rename to packages/client/lib/commands/HSET.ts index 1d4acd6c018..f7c56c5768d 100644 --- a/lib/commands/HSET.ts +++ b/packages/client/lib/commands/HSET.ts @@ -23,7 +23,7 @@ export function transformArguments(...[ key, value, fieldValue ]: SingleFieldArg pushMap(args, value); } else if (Array.isArray(value)) { pushTuples(args, value); - } else if (typeof value === 'object' && value !== null) { + } else { pushObject(args, value); } @@ -46,4 +46,4 @@ function pushObject(args: Array, object: HSETObject): void { } } -export declare function transformReply(): string; +export declare function transformReply(): number; diff --git a/lib/commands/HSETNX.spec.ts b/packages/client/lib/commands/HSETNX.spec.ts similarity index 73% rename from lib/commands/HSETNX.spec.ts rename to packages/client/lib/commands/HSETNX.spec.ts index f810c5e2b9a..190fa50ae97 100644 --- a/lib/commands/HSETNX.spec.ts +++ b/packages/client/lib/commands/HSETNX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HSETNX'; describe('HSETNX', () => { @@ -10,10 +10,10 @@ describe('HSETNX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hSetNX', async client => { + testUtils.testWithClient('client.hSetNX', async client => { assert.equal( await client.hSetNX('key', 'field', 'value'), true ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HSETNX.ts b/packages/client/lib/commands/HSETNX.ts similarity index 59% rename from lib/commands/HSETNX.ts rename to packages/client/lib/commands/HSETNX.ts index 0eef8752529..83112f8945e 100644 --- a/lib/commands/HSETNX.ts +++ b/packages/client/lib/commands/HSETNX.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, field: string, value: string): Array { return ['HSETNX', key, field, value]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/HSTRLEN.spec.ts b/packages/client/lib/commands/HSTRLEN.spec.ts similarity index 72% rename from lib/commands/HSTRLEN.spec.ts rename to packages/client/lib/commands/HSTRLEN.spec.ts index 35bf08d54c4..79c3150211e 100644 --- a/lib/commands/HSTRLEN.spec.ts +++ b/packages/client/lib/commands/HSTRLEN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HSTRLEN'; describe('HSTRLEN', () => { @@ -10,10 +10,10 @@ describe('HSTRLEN', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hStrLen', async client => { + testUtils.testWithClient('client.hStrLen', async client => { assert.equal( await client.hStrLen('key', 'field'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HSTRLEN.ts b/packages/client/lib/commands/HSTRLEN.ts similarity index 100% rename from lib/commands/HSTRLEN.ts rename to packages/client/lib/commands/HSTRLEN.ts diff --git a/lib/commands/HVALS.spec.ts b/packages/client/lib/commands/HVALS.spec.ts similarity index 71% rename from lib/commands/HVALS.spec.ts rename to packages/client/lib/commands/HVALS.spec.ts index 9e6451f500e..d0a6c39ce5f 100644 --- a/lib/commands/HVALS.spec.ts +++ b/packages/client/lib/commands/HVALS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './HVALS'; describe('HVALS', () => { @@ -10,10 +10,10 @@ describe('HVALS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.hVals', async client => { + testUtils.testWithClient('client.hVals', async client => { assert.deepEqual( await client.hVals('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/HVALS.ts b/packages/client/lib/commands/HVALS.ts similarity index 100% rename from lib/commands/HVALS.ts rename to packages/client/lib/commands/HVALS.ts diff --git a/lib/commands/INCR.spec.ts b/packages/client/lib/commands/INCR.spec.ts similarity index 70% rename from lib/commands/INCR.spec.ts rename to packages/client/lib/commands/INCR.spec.ts index d64c3696af4..321d83edc54 100644 --- a/lib/commands/INCR.spec.ts +++ b/packages/client/lib/commands/INCR.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './INCR'; describe('INCR', () => { @@ -10,10 +10,10 @@ describe('INCR', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.incr', async client => { + testUtils.testWithClient('client.incr', async client => { assert.equal( await client.incr('key'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/INCR.ts b/packages/client/lib/commands/INCR.ts similarity index 100% rename from lib/commands/INCR.ts rename to packages/client/lib/commands/INCR.ts diff --git a/lib/commands/INCRBY.spec.ts b/packages/client/lib/commands/INCRBY.spec.ts similarity index 71% rename from lib/commands/INCRBY.spec.ts rename to packages/client/lib/commands/INCRBY.spec.ts index 875277570cb..a671d0ec259 100644 --- a/lib/commands/INCRBY.spec.ts +++ b/packages/client/lib/commands/INCRBY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './INCRBY'; describe('INCR', () => { @@ -10,10 +10,10 @@ describe('INCR', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.incrBy', async client => { + testUtils.testWithClient('client.incrBy', async client => { assert.equal( await client.incrBy('key', 1), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/INCRBY.ts b/packages/client/lib/commands/INCRBY.ts similarity index 100% rename from lib/commands/INCRBY.ts rename to packages/client/lib/commands/INCRBY.ts diff --git a/lib/commands/INCRBYFLOAT.spec.ts b/packages/client/lib/commands/INCRBYFLOAT.spec.ts similarity index 72% rename from lib/commands/INCRBYFLOAT.spec.ts rename to packages/client/lib/commands/INCRBYFLOAT.spec.ts index fe062b62905..b2dd5aa5da9 100644 --- a/lib/commands/INCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/INCRBYFLOAT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './INCRBYFLOAT'; describe('INCRBYFLOAT', () => { @@ -10,10 +10,10 @@ describe('INCRBYFLOAT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.incrByFloat', async client => { + testUtils.testWithClient('client.incrByFloat', async client => { assert.equal( await client.incrByFloat('key', 1.5), '1.5' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/INCRBYFLOAT.ts b/packages/client/lib/commands/INCRBYFLOAT.ts similarity index 100% rename from lib/commands/INCRBYFLOAT.ts rename to packages/client/lib/commands/INCRBYFLOAT.ts diff --git a/lib/commands/INFO.spec.ts b/packages/client/lib/commands/INFO.spec.ts similarity index 100% rename from lib/commands/INFO.spec.ts rename to packages/client/lib/commands/INFO.spec.ts diff --git a/lib/commands/INFO.ts b/packages/client/lib/commands/INFO.ts similarity index 100% rename from lib/commands/INFO.ts rename to packages/client/lib/commands/INFO.ts diff --git a/lib/commands/KEYS.spec.ts b/packages/client/lib/commands/KEYS.spec.ts similarity index 53% rename from lib/commands/KEYS.spec.ts rename to packages/client/lib/commands/KEYS.spec.ts index d11e8a0f58b..c066331ea7c 100644 --- a/lib/commands/KEYS.spec.ts +++ b/packages/client/lib/commands/KEYS.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; describe('KEYS', () => { - itWithClient(TestRedisServers.OPEN, 'client.keys', async client => { + testUtils.testWithClient('client.keys', async client => { assert.deepEqual( await client.keys('pattern'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/KEYS.ts b/packages/client/lib/commands/KEYS.ts similarity index 100% rename from lib/commands/KEYS.ts rename to packages/client/lib/commands/KEYS.ts diff --git a/lib/commands/LASTSAVE.spec.ts b/packages/client/lib/commands/LASTSAVE.spec.ts similarity index 68% rename from lib/commands/LASTSAVE.spec.ts rename to packages/client/lib/commands/LASTSAVE.spec.ts index b8d801f70b5..a6b4863f39e 100644 --- a/lib/commands/LASTSAVE.spec.ts +++ b/packages/client/lib/commands/LASTSAVE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LASTSAVE'; describe('LASTSAVE', () => { @@ -10,7 +10,7 @@ describe('LASTSAVE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lastSave', async client => { + testUtils.testWithClient('client.lastSave', async client => { assert.ok((await client.lastSave()) instanceof Date); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/LASTSAVE.ts b/packages/client/lib/commands/LASTSAVE.ts similarity index 100% rename from lib/commands/LASTSAVE.ts rename to packages/client/lib/commands/LASTSAVE.ts diff --git a/lib/commands/LINDEX.spec.ts b/packages/client/lib/commands/LINDEX.spec.ts similarity index 65% rename from lib/commands/LINDEX.spec.ts rename to packages/client/lib/commands/LINDEX.spec.ts index 74a6706ecdc..5e0b1473ec4 100644 --- a/lib/commands/LINDEX.spec.ts +++ b/packages/client/lib/commands/LINDEX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LINDEX'; describe('LINDEX', () => { @@ -10,17 +10,17 @@ describe('LINDEX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lIndex', async client => { + testUtils.testWithClient('client.lIndex', async client => { assert.equal( await client.lIndex('key', 'element'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lIndex', async cluster => { + testUtils.testWithCluster('cluster.lIndex', async cluster => { assert.equal( await cluster.lIndex('key', 'element'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LINDEX.ts b/packages/client/lib/commands/LINDEX.ts similarity index 77% rename from lib/commands/LINDEX.ts rename to packages/client/lib/commands/LINDEX.ts index 9a89b41da55..4c283f0912c 100644 --- a/lib/commands/LINDEX.ts +++ b/packages/client/lib/commands/LINDEX.ts @@ -6,4 +6,4 @@ export function transformArguments(key: string, element: string): Array return ['LINDEX', key, element]; } -export declare function transformReply(): number | null; +export declare function transformReply(): string | null; diff --git a/lib/commands/LINSERT.spec.ts b/packages/client/lib/commands/LINSERT.spec.ts similarity index 68% rename from lib/commands/LINSERT.spec.ts rename to packages/client/lib/commands/LINSERT.spec.ts index 286e61d06d6..6cc429d6a2c 100644 --- a/lib/commands/LINSERT.spec.ts +++ b/packages/client/lib/commands/LINSERT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LINSERT'; describe('LINSERT', () => { @@ -10,17 +10,17 @@ describe('LINSERT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lInsert', async client => { + testUtils.testWithClient('client.lInsert', async client => { assert.equal( await client.lInsert('key', 'BEFORE', 'pivot', 'element'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lLen', async cluster => { + testUtils.testWithCluster('cluster.lLen', async cluster => { assert.equal( await cluster.lInsert('key', 'BEFORE', 'pivot', 'element'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LINSERT.ts b/packages/client/lib/commands/LINSERT.ts similarity index 100% rename from lib/commands/LINSERT.ts rename to packages/client/lib/commands/LINSERT.ts diff --git a/lib/commands/LLEN.spec.ts b/packages/client/lib/commands/LLEN.spec.ts similarity index 62% rename from lib/commands/LLEN.spec.ts rename to packages/client/lib/commands/LLEN.spec.ts index 6e4581ddd1f..fb126ddad55 100644 --- a/lib/commands/LLEN.spec.ts +++ b/packages/client/lib/commands/LLEN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LLEN'; describe('LLEN', () => { @@ -10,17 +10,17 @@ describe('LLEN', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lLen', async client => { + testUtils.testWithClient('client.lLen', async client => { assert.equal( await client.lLen('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lLen', async cluster => { + testUtils.testWithCluster('cluster.lLen', async cluster => { assert.equal( await cluster.lLen('key'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LLEN.ts b/packages/client/lib/commands/LLEN.ts similarity index 100% rename from lib/commands/LLEN.ts rename to packages/client/lib/commands/LLEN.ts diff --git a/lib/commands/LMOVE.spec.ts b/packages/client/lib/commands/LMOVE.spec.ts similarity index 63% rename from lib/commands/LMOVE.spec.ts rename to packages/client/lib/commands/LMOVE.spec.ts index bcb897f76ac..f1d418c394e 100644 --- a/lib/commands/LMOVE.spec.ts +++ b/packages/client/lib/commands/LMOVE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LMOVE'; describe('LMOVE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,17 +12,17 @@ describe('LMOVE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lMove', async client => { + testUtils.testWithClient('client.lMove', async client => { assert.equal( await client.lMove('source', 'destination', 'LEFT', 'RIGHT'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lMove', async cluster => { + testUtils.testWithCluster('cluster.lMove', async cluster => { assert.equal( await cluster.lMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LMOVE.ts b/packages/client/lib/commands/LMOVE.ts similarity index 100% rename from lib/commands/LMOVE.ts rename to packages/client/lib/commands/LMOVE.ts diff --git a/lib/commands/LOLWUT.spec.ts b/packages/client/lib/commands/LOLWUT.spec.ts similarity index 84% rename from lib/commands/LOLWUT.spec.ts rename to packages/client/lib/commands/LOLWUT.spec.ts index 8f4478aecc7..db335893302 100644 --- a/lib/commands/LOLWUT.spec.ts +++ b/packages/client/lib/commands/LOLWUT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LOLWUT'; describe('LOLWUT', () => { @@ -26,11 +26,10 @@ describe('LOLWUT', () => { }); }); - - itWithClient(TestRedisServers.OPEN, 'client.LOLWUT', async client => { + testUtils.testWithClient('client.LOLWUT', async client => { assert.equal( typeof (await client.LOLWUT()), 'string' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/LOLWUT.ts b/packages/client/lib/commands/LOLWUT.ts similarity index 100% rename from lib/commands/LOLWUT.ts rename to packages/client/lib/commands/LOLWUT.ts diff --git a/lib/commands/LPOP.spec.ts b/packages/client/lib/commands/LPOP.spec.ts similarity index 62% rename from lib/commands/LPOP.spec.ts rename to packages/client/lib/commands/LPOP.spec.ts index b593f657427..d694fb10588 100644 --- a/lib/commands/LPOP.spec.ts +++ b/packages/client/lib/commands/LPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPOP'; describe('LPOP', () => { @@ -10,17 +10,17 @@ describe('LPOP', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lPop', async client => { + testUtils.testWithClient('client.lPop', async client => { assert.equal( await client.lPop('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPop', async cluster => { + testUtils.testWithCluster('cluster.lPop', async cluster => { assert.equal( await cluster.lPop('key'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPOP.ts b/packages/client/lib/commands/LPOP.ts similarity index 100% rename from lib/commands/LPOP.ts rename to packages/client/lib/commands/LPOP.ts diff --git a/lib/commands/LPOP_COUNT.spec.ts b/packages/client/lib/commands/LPOP_COUNT.spec.ts similarity index 57% rename from lib/commands/LPOP_COUNT.spec.ts rename to packages/client/lib/commands/LPOP_COUNT.spec.ts index 89150dbf4de..9d87fad3862 100644 --- a/lib/commands/LPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOP_COUNT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPOP_COUNT'; describe('LPOP COUNT', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,17 +12,17 @@ describe('LPOP COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lPopCount', async client => { + testUtils.testWithClient('client.lPopCount', async client => { assert.equal( await client.lPopCount('key', 1), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPop', async cluster => { + testUtils.testWithCluster('cluster.lPopCount', async cluster => { assert.equal( await cluster.lPopCount('key', 1), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPOP_COUNT.ts b/packages/client/lib/commands/LPOP_COUNT.ts similarity index 100% rename from lib/commands/LPOP_COUNT.ts rename to packages/client/lib/commands/LPOP_COUNT.ts diff --git a/lib/commands/LPOS.spec.ts b/packages/client/lib/commands/LPOS.spec.ts similarity index 79% rename from lib/commands/LPOS.spec.ts rename to packages/client/lib/commands/LPOS.spec.ts index 1cf9e35209d..6b6050f2c3b 100644 --- a/lib/commands/LPOS.spec.ts +++ b/packages/client/lib/commands/LPOS.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPOS'; describe('LPOS', () => { - describeHandleMinimumRedisVersion([6, 0, 6]); + testUtils.isVersionGreaterThanHook([6, 0, 6]); describe('transformArguments', () => { it('simple', () => { @@ -42,17 +42,17 @@ describe('LPOS', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.lPos', async client => { + testUtils.testWithClient('client.lPos', async client => { assert.equal( await client.lPos('key', 'element'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPos', async cluster => { + testUtils.testWithCluster('cluster.lPos', async cluster => { assert.equal( await cluster.lPos('key', 'element'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPOS.ts b/packages/client/lib/commands/LPOS.ts similarity index 100% rename from lib/commands/LPOS.ts rename to packages/client/lib/commands/LPOS.ts diff --git a/lib/commands/LPOS_COUNT.spec.ts b/packages/client/lib/commands/LPOS_COUNT.spec.ts similarity index 80% rename from lib/commands/LPOS_COUNT.spec.ts rename to packages/client/lib/commands/LPOS_COUNT.spec.ts index 1d80bd45c3c..4b01f2f59b9 100644 --- a/lib/commands/LPOS_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOS_COUNT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPOS_COUNT'; describe('LPOS COUNT', () => { - describeHandleMinimumRedisVersion([6, 0, 6]); + testUtils.isVersionGreaterThanHook([6, 0, 6]); describe('transformArguments', () => { it('simple', () => { @@ -42,17 +42,17 @@ describe('LPOS COUNT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.lPosCount', async client => { + testUtils.testWithClient('client.lPosCount', async client => { assert.deepEqual( await client.lPosCount('key', 'element', 0), [] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPosCount', async cluster => { + testUtils.testWithCluster('cluster.lPosCount', async cluster => { assert.deepEqual( await cluster.lPosCount('key', 'element', 0), [] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPOS_COUNT.ts b/packages/client/lib/commands/LPOS_COUNT.ts similarity index 100% rename from lib/commands/LPOS_COUNT.ts rename to packages/client/lib/commands/LPOS_COUNT.ts diff --git a/lib/commands/LPUSH.spec.ts b/packages/client/lib/commands/LPUSH.spec.ts similarity index 73% rename from lib/commands/LPUSH.spec.ts rename to packages/client/lib/commands/LPUSH.spec.ts index 44cf8c12d5f..b5b1f5084eb 100644 --- a/lib/commands/LPUSH.spec.ts +++ b/packages/client/lib/commands/LPUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPUSH'; describe('LPUSH', () => { @@ -19,17 +19,17 @@ describe('LPUSH', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.lPush', async client => { + testUtils.testWithClient('client.lPush', async client => { assert.equal( await client.lPush('key', 'field'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPush', async cluster => { + testUtils.testWithCluster('cluster.lPush', async cluster => { assert.equal( await cluster.lPush('key', 'field'), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPUSH.ts b/packages/client/lib/commands/LPUSH.ts similarity index 100% rename from lib/commands/LPUSH.ts rename to packages/client/lib/commands/LPUSH.ts diff --git a/lib/commands/LPUSHX.spec.ts b/packages/client/lib/commands/LPUSHX.spec.ts similarity index 73% rename from lib/commands/LPUSHX.spec.ts rename to packages/client/lib/commands/LPUSHX.spec.ts index 1150c4d64dd..d978e5a588f 100644 --- a/lib/commands/LPUSHX.spec.ts +++ b/packages/client/lib/commands/LPUSHX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LPUSHX'; describe('LPUSHX', () => { @@ -19,17 +19,17 @@ describe('LPUSHX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.lPushX', async client => { + testUtils.testWithClient('client.lPushX', async client => { assert.equal( await client.lPushX('key', 'element'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lPushX', async cluster => { + testUtils.testWithCluster('cluster.lPushX', async cluster => { assert.equal( await cluster.lPushX('key', 'element'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LPUSHX.ts b/packages/client/lib/commands/LPUSHX.ts similarity index 100% rename from lib/commands/LPUSHX.ts rename to packages/client/lib/commands/LPUSHX.ts diff --git a/lib/commands/LRANGE.spec.ts b/packages/client/lib/commands/LRANGE.spec.ts similarity index 64% rename from lib/commands/LRANGE.spec.ts rename to packages/client/lib/commands/LRANGE.spec.ts index 843b7b8815e..dffe6087b80 100644 --- a/lib/commands/LRANGE.spec.ts +++ b/packages/client/lib/commands/LRANGE.spec.ts @@ -1,6 +1,6 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LRANGE'; describe('LRANGE', () => { @@ -11,17 +11,17 @@ describe('LRANGE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lRange', async client => { + testUtils.testWithClient('client.lRange', async client => { assert.deepEqual( await client.lRange('key', 0, -1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lRange', async cluster => { + testUtils.testWithCluster('cluster.lRange', async cluster => { assert.deepEqual( await cluster.lRange('key', 0, -1), [] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LRANGE.ts b/packages/client/lib/commands/LRANGE.ts similarity index 100% rename from lib/commands/LRANGE.ts rename to packages/client/lib/commands/LRANGE.ts diff --git a/lib/commands/LREM.spec.ts b/packages/client/lib/commands/LREM.spec.ts similarity index 65% rename from lib/commands/LREM.spec.ts rename to packages/client/lib/commands/LREM.spec.ts index e2f027ffeb8..3405f4beb07 100644 --- a/lib/commands/LREM.spec.ts +++ b/packages/client/lib/commands/LREM.spec.ts @@ -1,6 +1,6 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LREM'; describe('LREM', () => { @@ -11,17 +11,17 @@ describe('LREM', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lRem', async client => { + testUtils.testWithClient('client.lRem', async client => { assert.equal( await client.lRem('key', 0, 'element'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lRem', async cluster => { + testUtils.testWithCluster('cluster.lRem', async cluster => { assert.equal( await cluster.lRem('key', 0, 'element'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LREM.ts b/packages/client/lib/commands/LREM.ts similarity index 100% rename from lib/commands/LREM.ts rename to packages/client/lib/commands/LREM.ts diff --git a/lib/commands/LSET.spec.ts b/packages/client/lib/commands/LSET.spec.ts similarity index 69% rename from lib/commands/LSET.spec.ts rename to packages/client/lib/commands/LSET.spec.ts index a5fe78cf4c3..d7241032cc6 100644 --- a/lib/commands/LSET.spec.ts +++ b/packages/client/lib/commands/LSET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LSET'; describe('LSET', () => { @@ -10,19 +10,19 @@ describe('LSET', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lSet', async client => { + testUtils.testWithClient('client.lSet', async client => { await client.lPush('key', 'element'); assert.equal( await client.lSet('key', 0, 'element'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lSet', async cluster => { + testUtils.testWithCluster('cluster.lSet', async cluster => { await cluster.lPush('key', 'element'); assert.equal( await cluster.lSet('key', 0, 'element'), 'OK' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LSET.ts b/packages/client/lib/commands/LSET.ts similarity index 100% rename from lib/commands/LSET.ts rename to packages/client/lib/commands/LSET.ts diff --git a/lib/commands/LTRIM.spec.ts b/packages/client/lib/commands/LTRIM.spec.ts similarity index 64% rename from lib/commands/LTRIM.spec.ts rename to packages/client/lib/commands/LTRIM.spec.ts index 8092ba6af1e..5b6ac5d3660 100644 --- a/lib/commands/LTRIM.spec.ts +++ b/packages/client/lib/commands/LTRIM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './LTRIM'; describe('LTRIM', () => { @@ -10,17 +10,17 @@ describe('LTRIM', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.lTrim', async client => { + testUtils.testWithClient('client.lTrim', async client => { assert.equal( await client.lTrim('key', 0, -1), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.lTrim', async cluster => { + testUtils.testWithCluster('cluster.lTrim', async cluster => { assert.equal( await cluster.lTrim('key', 0, -1), 'OK' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/LTRIM.ts b/packages/client/lib/commands/LTRIM.ts similarity index 97% rename from lib/commands/LTRIM.ts rename to packages/client/lib/commands/LTRIM.ts index 018afd90a15..ab78e5305aa 100644 --- a/lib/commands/LTRIM.ts +++ b/packages/client/lib/commands/LTRIM.ts @@ -6,7 +6,7 @@ export function transformArguments(key: string, start: number, stop: number): Ar key, start.toString(), stop.toString() - ] + ]; } export declare function transformReply(): string; diff --git a/lib/commands/MEMORY_DOCTOR.spec.ts b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts similarity index 71% rename from lib/commands/MEMORY_DOCTOR.spec.ts rename to packages/client/lib/commands/MEMORY_DOCTOR.spec.ts index 1b4d16fa0db..ad97047606c 100644 --- a/lib/commands/MEMORY_DOCTOR.spec.ts +++ b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MEMORY_DOCTOR'; describe('MEMORY DOCTOR', () => { @@ -10,10 +10,10 @@ describe('MEMORY DOCTOR', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.memoryDoctor', async client => { + testUtils.testWithClient('client.memoryDoctor', async client => { assert.equal( typeof (await client.memoryDoctor()), 'string' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/MEMORY_DOCTOR.ts b/packages/client/lib/commands/MEMORY_DOCTOR.ts similarity index 100% rename from lib/commands/MEMORY_DOCTOR.ts rename to packages/client/lib/commands/MEMORY_DOCTOR.ts diff --git a/lib/commands/MEMORY_MALLOC-STATS.spec.ts b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts similarity index 72% rename from lib/commands/MEMORY_MALLOC-STATS.spec.ts rename to packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts index 034b94f7c66..ce866f1e116 100644 --- a/lib/commands/MEMORY_MALLOC-STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MEMORY_MALLOC-STATS'; describe('MEMORY MALLOC-STATS', () => { @@ -10,10 +10,10 @@ describe('MEMORY MALLOC-STATS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.memoryMallocStats', async client => { + testUtils.testWithClient('client.memoryMallocStats', async client => { assert.equal( typeof (await client.memoryDoctor()), 'string' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/MEMORY_MALLOC-STATS.ts b/packages/client/lib/commands/MEMORY_MALLOC-STATS.ts similarity index 100% rename from lib/commands/MEMORY_MALLOC-STATS.ts rename to packages/client/lib/commands/MEMORY_MALLOC-STATS.ts diff --git a/lib/commands/MEMORY_PURGE.spec.ts b/packages/client/lib/commands/MEMORY_PURGE.spec.ts similarity index 71% rename from lib/commands/MEMORY_PURGE.spec.ts rename to packages/client/lib/commands/MEMORY_PURGE.spec.ts index 97ca6feebf6..5d34331feb6 100644 --- a/lib/commands/MEMORY_PURGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_PURGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MEMORY_PURGE'; describe('MEMORY PURGE', () => { @@ -10,10 +10,10 @@ describe('MEMORY PURGE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.memoryPurge', async client => { + testUtils.testWithClient('client.memoryPurge', async client => { assert.equal( await client.memoryPurge(), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/MEMORY_PURGE.ts b/packages/client/lib/commands/MEMORY_PURGE.ts similarity index 100% rename from lib/commands/MEMORY_PURGE.ts rename to packages/client/lib/commands/MEMORY_PURGE.ts diff --git a/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts similarity index 100% rename from lib/commands/MEMORY_STATS.spec.ts rename to packages/client/lib/commands/MEMORY_STATS.spec.ts diff --git a/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts similarity index 100% rename from lib/commands/MEMORY_STATS.ts rename to packages/client/lib/commands/MEMORY_STATS.ts diff --git a/lib/commands/MEMORY_USAGE.spec.ts b/packages/client/lib/commands/MEMORY_USAGE.spec.ts similarity index 82% rename from lib/commands/MEMORY_USAGE.spec.ts rename to packages/client/lib/commands/MEMORY_USAGE.spec.ts index 90dff62c674..fe5ff404d93 100644 --- a/lib/commands/MEMORY_USAGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_USAGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MEMORY_USAGE'; describe('MEMORY USAGE', () => { @@ -21,10 +21,10 @@ describe('MEMORY USAGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.memoryUsage', async client => { + testUtils.testWithClient('client.memoryUsage', async client => { assert.equal( await client.memoryUsage('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/MEMORY_USAGE.ts b/packages/client/lib/commands/MEMORY_USAGE.ts similarity index 100% rename from lib/commands/MEMORY_USAGE.ts rename to packages/client/lib/commands/MEMORY_USAGE.ts diff --git a/lib/commands/MGET.spec.ts b/packages/client/lib/commands/MGET.spec.ts similarity index 64% rename from lib/commands/MGET.spec.ts rename to packages/client/lib/commands/MGET.spec.ts index c8c020fe433..9ff47895f4e 100644 --- a/lib/commands/MGET.spec.ts +++ b/packages/client/lib/commands/MGET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MGET'; describe('MGET', () => { @@ -10,17 +10,17 @@ describe('MGET', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.mGet', async client => { + testUtils.testWithClient('client.mGet', async client => { assert.deepEqual( await client.mGet(['key']), [null] ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.mGet', async cluster => { + testUtils.testWithCluster('cluster.mGet', async cluster => { assert.deepEqual( await cluster.mGet(['key']), [null] ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/MGET.ts b/packages/client/lib/commands/MGET.ts similarity index 100% rename from lib/commands/MGET.ts rename to packages/client/lib/commands/MGET.ts diff --git a/lib/commands/MIGRATE.spec.ts b/packages/client/lib/commands/MIGRATE.spec.ts similarity index 100% rename from lib/commands/MIGRATE.spec.ts rename to packages/client/lib/commands/MIGRATE.spec.ts diff --git a/lib/commands/MIGRATE.ts b/packages/client/lib/commands/MIGRATE.ts similarity index 100% rename from lib/commands/MIGRATE.ts rename to packages/client/lib/commands/MIGRATE.ts diff --git a/lib/commands/MODULE_LIST.spec.ts b/packages/client/lib/commands/MODULE_LIST.spec.ts similarity index 100% rename from lib/commands/MODULE_LIST.spec.ts rename to packages/client/lib/commands/MODULE_LIST.spec.ts diff --git a/lib/commands/MODULE_LIST.ts b/packages/client/lib/commands/MODULE_LIST.ts similarity index 100% rename from lib/commands/MODULE_LIST.ts rename to packages/client/lib/commands/MODULE_LIST.ts diff --git a/lib/commands/MODULE_LOAD.spec.ts b/packages/client/lib/commands/MODULE_LOAD.spec.ts similarity index 100% rename from lib/commands/MODULE_LOAD.spec.ts rename to packages/client/lib/commands/MODULE_LOAD.spec.ts diff --git a/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts similarity index 100% rename from lib/commands/MODULE_LOAD.ts rename to packages/client/lib/commands/MODULE_LOAD.ts diff --git a/lib/commands/MODULE_UNLOAD.spec.ts b/packages/client/lib/commands/MODULE_UNLOAD.spec.ts similarity index 100% rename from lib/commands/MODULE_UNLOAD.spec.ts rename to packages/client/lib/commands/MODULE_UNLOAD.spec.ts diff --git a/lib/commands/MODULE_UNLOAD.ts b/packages/client/lib/commands/MODULE_UNLOAD.ts similarity index 100% rename from lib/commands/MODULE_UNLOAD.ts rename to packages/client/lib/commands/MODULE_UNLOAD.ts diff --git a/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts similarity index 71% rename from lib/commands/MOVE.spec.ts rename to packages/client/lib/commands/MOVE.spec.ts index a05ca4613e9..f7fdc481cbf 100644 --- a/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MOVE'; describe('MOVE', () => { @@ -10,10 +10,10 @@ describe('MOVE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.move', async client => { + testUtils.testWithClient('client.move', async client => { assert.equal( await client.move('key', 1), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/MOVE.ts b/packages/client/lib/commands/MOVE.ts similarity index 50% rename from lib/commands/MOVE.ts rename to packages/client/lib/commands/MOVE.ts index 74bb88c5e74..93896a63054 100644 --- a/lib/commands/MOVE.ts +++ b/packages/client/lib/commands/MOVE.ts @@ -1,7 +1,5 @@ -import { transformReplyBoolean } from './generic-transformers'; - export function transformArguments(key: string, db: number): Array { return ['MOVE', key, db.toString()]; } -export const transformReply = transformReplyBoolean; \ No newline at end of file +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/MSET.spec.ts b/packages/client/lib/commands/MSET.spec.ts similarity index 81% rename from lib/commands/MSET.spec.ts rename to packages/client/lib/commands/MSET.spec.ts index 4445f4a7281..0568f38487e 100644 --- a/lib/commands/MSET.spec.ts +++ b/packages/client/lib/commands/MSET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MSET'; describe('MSET', () => { @@ -26,17 +26,17 @@ describe('MSET', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.mSet', async client => { + testUtils.testWithClient('client.mSet', async client => { assert.equal( await client.mSet(['key1', 'value1', 'key2', 'value2']), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.mSet', async cluster => { + testUtils.testWithCluster('cluster.mSet', async cluster => { assert.equal( await cluster.mSet(['{key}1', 'value1', '{key}2', 'value2']), 'OK' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/MSET.ts b/packages/client/lib/commands/MSET.ts similarity index 100% rename from lib/commands/MSET.ts rename to packages/client/lib/commands/MSET.ts diff --git a/lib/commands/MSETNX.spec.ts b/packages/client/lib/commands/MSETNX.spec.ts similarity index 81% rename from lib/commands/MSETNX.spec.ts rename to packages/client/lib/commands/MSETNX.spec.ts index 7f61a43e8d0..854a9affd8a 100644 --- a/lib/commands/MSETNX.spec.ts +++ b/packages/client/lib/commands/MSETNX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MSETNX'; describe('MSETNX', () => { @@ -26,17 +26,17 @@ describe('MSETNX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.mSetNX', async client => { + testUtils.testWithClient('client.mSetNX', async client => { assert.equal( await client.mSetNX(['key1', 'value1', 'key2', 'value2']), true ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.mSetNX', async cluster => { + testUtils.testWithCluster('cluster.mSetNX', async cluster => { assert.equal( await cluster.mSetNX(['{key}1', 'value1', '{key}2', 'value2']), true ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/MSETNX.ts b/packages/client/lib/commands/MSETNX.ts similarity index 77% rename from lib/commands/MSETNX.ts rename to packages/client/lib/commands/MSETNX.ts index c9c8c840374..fb7b028bc25 100644 --- a/lib/commands/MSETNX.ts +++ b/packages/client/lib/commands/MSETNX.ts @@ -1,5 +1,3 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(toSet: Array<[string, string]> | Array | Record): Array { @@ -16,4 +14,4 @@ export function transformArguments(toSet: Array<[string, string]> | Array { @@ -10,10 +10,10 @@ describe('PERSIST', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.persist', async client => { + testUtils.testWithClient('client.persist', async client => { assert.equal( await client.persist('key'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PERSIST.ts b/packages/client/lib/commands/PERSIST.ts similarity index 52% rename from lib/commands/PERSIST.ts rename to packages/client/lib/commands/PERSIST.ts index fc85a21c98c..b43310c136d 100644 --- a/lib/commands/PERSIST.ts +++ b/packages/client/lib/commands/PERSIST.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string): Array { return ['PERSIST', key]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/PEXPIRE.spec.ts b/packages/client/lib/commands/PEXPIRE.spec.ts similarity index 71% rename from lib/commands/PEXPIRE.spec.ts rename to packages/client/lib/commands/PEXPIRE.spec.ts index b7c4e1df461..4738edcf8f0 100644 --- a/lib/commands/PEXPIRE.spec.ts +++ b/packages/client/lib/commands/PEXPIRE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PEXPIRE'; describe('PEXPIRE', () => { @@ -10,10 +10,10 @@ describe('PEXPIRE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.pExpire', async client => { + testUtils.testWithClient('client.pExpire', async client => { assert.equal( await client.pExpire('key', 1), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PEXPIRE.ts b/packages/client/lib/commands/PEXPIRE.ts similarity index 60% rename from lib/commands/PEXPIRE.ts rename to packages/client/lib/commands/PEXPIRE.ts index d795f2fc0d0..f3b70279aa7 100644 --- a/lib/commands/PEXPIRE.ts +++ b/packages/client/lib/commands/PEXPIRE.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, milliseconds: number): Array { return ['PEXPIRE', key, milliseconds.toString()]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/PEXPIREAT.spec.ts b/packages/client/lib/commands/PEXPIREAT.spec.ts similarity index 81% rename from lib/commands/PEXPIREAT.spec.ts rename to packages/client/lib/commands/PEXPIREAT.spec.ts index 6e5fc37ed5c..19fc3b888d7 100644 --- a/lib/commands/PEXPIREAT.spec.ts +++ b/packages/client/lib/commands/PEXPIREAT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PEXPIREAT'; describe('PEXPIREAT', () => { @@ -10,7 +10,7 @@ describe('PEXPIREAT', () => { ['PEXPIREAT', 'key', '1'] ); }); - + it('date', () => { const d = new Date(); assert.deepEqual( @@ -20,10 +20,10 @@ describe('PEXPIREAT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pExpireAt', async client => { + testUtils.testWithClient('client.pExpireAt', async client => { assert.equal( await client.pExpireAt('key', 1), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PEXPIREAT.ts b/packages/client/lib/commands/PEXPIREAT.ts similarity index 63% rename from lib/commands/PEXPIREAT.ts rename to packages/client/lib/commands/PEXPIREAT.ts index 91f38f88946..5dded48d278 100644 --- a/lib/commands/PEXPIREAT.ts +++ b/packages/client/lib/commands/PEXPIREAT.ts @@ -1,4 +1,4 @@ -import { transformPXAT, transformReplyBoolean } from './generic-transformers'; +import { transformPXAT } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -10,4 +10,4 @@ export function transformArguments(key: string, millisecondsTimestamp: number | ]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/PFADD.spec.ts b/packages/client/lib/commands/PFADD.spec.ts similarity index 81% rename from lib/commands/PFADD.spec.ts rename to packages/client/lib/commands/PFADD.spec.ts index 74f03ea3ce2..8c0e752fd50 100644 --- a/lib/commands/PFADD.spec.ts +++ b/packages/client/lib/commands/PFADD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PFADD'; describe('PFADD', () => { @@ -19,10 +19,10 @@ describe('PFADD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pfAdd', async client => { + testUtils.testWithClient('client.pfAdd', async client => { assert.equal( await client.pfAdd('key', '1'), true ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PFADD.ts b/packages/client/lib/commands/PFADD.ts similarity index 62% rename from lib/commands/PFADD.ts rename to packages/client/lib/commands/PFADD.ts index 4328a18dfe5..e45e83c3ae0 100644 --- a/lib/commands/PFADD.ts +++ b/packages/client/lib/commands/PFADD.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments, transformReplyBoolean } from './generic-transformers'; +import { pushVerdictArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,4 +7,4 @@ export function transformArguments(key: string, element: string | Array) return pushVerdictArguments(['PFADD', key], element); } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/PFCOUNT.spec.ts b/packages/client/lib/commands/PFCOUNT.spec.ts similarity index 80% rename from lib/commands/PFCOUNT.spec.ts rename to packages/client/lib/commands/PFCOUNT.spec.ts index 049fa2c200c..a1ea06c4494 100644 --- a/lib/commands/PFCOUNT.spec.ts +++ b/packages/client/lib/commands/PFCOUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PFCOUNT'; describe('PFCOUNT', () => { @@ -19,10 +19,10 @@ describe('PFCOUNT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pfCount', async client => { + testUtils.testWithClient('client.pfCount', async client => { assert.equal( await client.pfCount('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PFCOUNT.ts b/packages/client/lib/commands/PFCOUNT.ts similarity index 100% rename from lib/commands/PFCOUNT.ts rename to packages/client/lib/commands/PFCOUNT.ts diff --git a/lib/commands/PFMERGE.spec.ts b/packages/client/lib/commands/PFMERGE.spec.ts similarity index 82% rename from lib/commands/PFMERGE.spec.ts rename to packages/client/lib/commands/PFMERGE.spec.ts index 1f6ed24bcd1..881fc5f5439 100644 --- a/lib/commands/PFMERGE.spec.ts +++ b/packages/client/lib/commands/PFMERGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PFMERGE'; describe('PFMERGE', () => { @@ -19,10 +19,10 @@ describe('PFMERGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pfMerge', async client => { + testUtils.testWithClient('client.pfMerge', async client => { assert.equal( await client.pfMerge('destination', 'source'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PFMERGE.ts b/packages/client/lib/commands/PFMERGE.ts similarity index 100% rename from lib/commands/PFMERGE.ts rename to packages/client/lib/commands/PFMERGE.ts diff --git a/lib/commands/PING.spec.ts b/packages/client/lib/commands/PING.spec.ts similarity index 52% rename from lib/commands/PING.spec.ts rename to packages/client/lib/commands/PING.spec.ts index 43b683f192d..85b48fec6b5 100644 --- a/lib/commands/PING.spec.ts +++ b/packages/client/lib/commands/PING.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; describe('PING', () => { - itWithClient(TestRedisServers.OPEN, 'client.ping', async client => { + testUtils.testWithClient('client.ping', async client => { assert.equal( await client.ping(), 'PONG' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PING.ts b/packages/client/lib/commands/PING.ts similarity index 100% rename from lib/commands/PING.ts rename to packages/client/lib/commands/PING.ts diff --git a/lib/commands/PSETEX.spec.ts b/packages/client/lib/commands/PSETEX.spec.ts similarity index 65% rename from lib/commands/PSETEX.spec.ts rename to packages/client/lib/commands/PSETEX.spec.ts index c98142effa9..61a6e682b08 100644 --- a/lib/commands/PSETEX.spec.ts +++ b/packages/client/lib/commands/PSETEX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PSETEX'; describe('PSETEX', () => { @@ -10,17 +10,17 @@ describe('PSETEX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.pSetEx', async client => { + testUtils.testWithClient('client.pSetEx', async client => { assert.equal( await client.pSetEx('key', 1, 'value'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.pSetEx', async cluster => { + testUtils.testWithCluster('cluster.pSetEx', async cluster => { assert.equal( await cluster.pSetEx('key', 1, 'value'), 'OK' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/PSETEX.ts b/packages/client/lib/commands/PSETEX.ts similarity index 100% rename from lib/commands/PSETEX.ts rename to packages/client/lib/commands/PSETEX.ts diff --git a/lib/commands/PTTL.spec.ts b/packages/client/lib/commands/PTTL.spec.ts similarity index 70% rename from lib/commands/PTTL.spec.ts rename to packages/client/lib/commands/PTTL.spec.ts index 35f48c2cc3e..e65421de590 100644 --- a/lib/commands/PTTL.spec.ts +++ b/packages/client/lib/commands/PTTL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PTTL'; describe('PTTL', () => { @@ -10,10 +10,10 @@ describe('PTTL', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.pTTL', async client => { + testUtils.testWithClient('client.pTTL', async client => { assert.equal( await client.pTTL('key'), -2 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PTTL.ts b/packages/client/lib/commands/PTTL.ts similarity index 100% rename from lib/commands/PTTL.ts rename to packages/client/lib/commands/PTTL.ts diff --git a/lib/commands/PUBLISH.spec.ts b/packages/client/lib/commands/PUBLISH.spec.ts similarity index 73% rename from lib/commands/PUBLISH.spec.ts rename to packages/client/lib/commands/PUBLISH.spec.ts index e746b9490e0..b2084e668ba 100644 --- a/lib/commands/PUBLISH.spec.ts +++ b/packages/client/lib/commands/PUBLISH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PUBLISH'; describe('PUBLISH', () => { @@ -10,10 +10,10 @@ describe('PUBLISH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.publish', async client => { + testUtils.testWithClient('client.publish', async client => { assert.equal( await client.publish('channel', 'message'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PUBLISH.ts b/packages/client/lib/commands/PUBLISH.ts similarity index 100% rename from lib/commands/PUBLISH.ts rename to packages/client/lib/commands/PUBLISH.ts diff --git a/lib/commands/PUBSUB_CHANNELS.spec.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts similarity index 80% rename from lib/commands/PUBSUB_CHANNELS.spec.ts rename to packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts index 9e148bc7fda..c427eab4850 100644 --- a/lib/commands/PUBSUB_CHANNELS.spec.ts +++ b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PUBSUB_CHANNELS'; describe('PUBSUB CHANNELS', () => { @@ -19,10 +19,10 @@ describe('PUBSUB CHANNELS', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pubSubChannels', async client => { + testUtils.testWithClient('client.pubSubChannels', async client => { assert.deepEqual( await client.pubSubChannels(), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PUBSUB_CHANNELS.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.ts similarity index 100% rename from lib/commands/PUBSUB_CHANNELS.ts rename to packages/client/lib/commands/PUBSUB_CHANNELS.ts diff --git a/lib/commands/PUBSUB_NUMPAT.spec.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts similarity index 70% rename from lib/commands/PUBSUB_NUMPAT.spec.ts rename to packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts index 55eef6a97de..d738b916c60 100644 --- a/lib/commands/PUBSUB_NUMPAT.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PUBSUB_NUMPAT'; describe('PUBSUB NUMPAT', () => { @@ -10,10 +10,10 @@ describe('PUBSUB NUMPAT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.pubSubNumPat', async client => { + testUtils.testWithClient('client.pubSubNumPat', async client => { assert.equal( await client.pubSubNumPat(), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PUBSUB_NUMPAT.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.ts similarity index 100% rename from lib/commands/PUBSUB_NUMPAT.ts rename to packages/client/lib/commands/PUBSUB_NUMPAT.ts diff --git a/lib/commands/PUBSUB_NUMSUB.spec.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts similarity index 84% rename from lib/commands/PUBSUB_NUMSUB.spec.ts rename to packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts index ef44faf2c0b..e35558ef865 100644 --- a/lib/commands/PUBSUB_NUMSUB.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './PUBSUB_NUMSUB'; describe('PUBSUB NUMSUB', () => { @@ -26,10 +26,10 @@ describe('PUBSUB NUMSUB', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.pubSubNumSub', async client => { + testUtils.testWithClient('client.pubSubNumSub', async client => { assert.deepEqual( await client.pubSubNumSub(), Object.create(null) ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/PUBSUB_NUMSUB.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.ts similarity index 100% rename from lib/commands/PUBSUB_NUMSUB.ts rename to packages/client/lib/commands/PUBSUB_NUMSUB.ts diff --git a/lib/commands/RANDOMKEY.spec.ts b/packages/client/lib/commands/RANDOMKEY.spec.ts similarity index 70% rename from lib/commands/RANDOMKEY.spec.ts rename to packages/client/lib/commands/RANDOMKEY.spec.ts index 171c42be116..81c42b2fd83 100644 --- a/lib/commands/RANDOMKEY.spec.ts +++ b/packages/client/lib/commands/RANDOMKEY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RANDOMKEY'; describe('RANDOMKEY', () => { @@ -10,10 +10,10 @@ describe('RANDOMKEY', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.randomKey', async client => { + testUtils.testWithClient('client.randomKey', async client => { assert.equal( await client.randomKey(), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/RANDOMKEY.ts b/packages/client/lib/commands/RANDOMKEY.ts similarity index 100% rename from lib/commands/RANDOMKEY.ts rename to packages/client/lib/commands/RANDOMKEY.ts diff --git a/lib/commands/READONLY.spec.ts b/packages/client/lib/commands/READONLY.spec.ts similarity index 100% rename from lib/commands/READONLY.spec.ts rename to packages/client/lib/commands/READONLY.spec.ts diff --git a/lib/commands/READONLY.ts b/packages/client/lib/commands/READONLY.ts similarity index 100% rename from lib/commands/READONLY.ts rename to packages/client/lib/commands/READONLY.ts diff --git a/lib/commands/READWRITE.spec.ts b/packages/client/lib/commands/READWRITE.spec.ts similarity index 100% rename from lib/commands/READWRITE.spec.ts rename to packages/client/lib/commands/READWRITE.spec.ts diff --git a/lib/commands/READWRITE.ts b/packages/client/lib/commands/READWRITE.ts similarity index 100% rename from lib/commands/READWRITE.ts rename to packages/client/lib/commands/READWRITE.ts diff --git a/lib/commands/RENAME.spec.ts b/packages/client/lib/commands/RENAME.spec.ts similarity index 74% rename from lib/commands/RENAME.spec.ts rename to packages/client/lib/commands/RENAME.spec.ts index 9d447c600b6..49e0af600f6 100644 --- a/lib/commands/RENAME.spec.ts +++ b/packages/client/lib/commands/RENAME.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RENAME'; describe('RENAME', () => { @@ -10,12 +10,12 @@ describe('RENAME', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.rename', async client => { + testUtils.testWithClient('client.rename', async client => { await client.set('from', 'value'); assert.equal( await client.rename('from', 'to'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/RENAME.ts b/packages/client/lib/commands/RENAME.ts similarity index 100% rename from lib/commands/RENAME.ts rename to packages/client/lib/commands/RENAME.ts diff --git a/lib/commands/RENAMENX.spec.ts b/packages/client/lib/commands/RENAMENX.spec.ts similarity index 74% rename from lib/commands/RENAMENX.spec.ts rename to packages/client/lib/commands/RENAMENX.spec.ts index f438834b90e..6345eb5bd09 100644 --- a/lib/commands/RENAMENX.spec.ts +++ b/packages/client/lib/commands/RENAMENX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RENAMENX'; describe('RENAMENX', () => { @@ -10,12 +10,12 @@ describe('RENAMENX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.renameNX', async client => { + testUtils.testWithClient('client.renameNX', async client => { await client.set('from', 'value'); assert.equal( await client.renameNX('from', 'to'), true ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts similarity index 57% rename from lib/commands/RENAMENX.ts rename to packages/client/lib/commands/RENAMENX.ts index 883d2ca2961..2cfec007741 100644 --- a/lib/commands/RENAMENX.ts +++ b/packages/client/lib/commands/RENAMENX.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, newKey: string): Array { return ['RENAMENX', key, newKey]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/REPLICAOF.spec.ts b/packages/client/lib/commands/REPLICAOF.spec.ts similarity index 100% rename from lib/commands/REPLICAOF.spec.ts rename to packages/client/lib/commands/REPLICAOF.spec.ts diff --git a/lib/commands/REPLICAOF.ts b/packages/client/lib/commands/REPLICAOF.ts similarity index 100% rename from lib/commands/REPLICAOF.ts rename to packages/client/lib/commands/REPLICAOF.ts diff --git a/lib/commands/RESTORE-ASKING.spec.ts b/packages/client/lib/commands/RESTORE-ASKING.spec.ts similarity index 100% rename from lib/commands/RESTORE-ASKING.spec.ts rename to packages/client/lib/commands/RESTORE-ASKING.spec.ts diff --git a/lib/commands/RESTORE-ASKING.ts b/packages/client/lib/commands/RESTORE-ASKING.ts similarity index 100% rename from lib/commands/RESTORE-ASKING.ts rename to packages/client/lib/commands/RESTORE-ASKING.ts diff --git a/lib/commands/ROLE.spec.ts b/packages/client/lib/commands/ROLE.spec.ts similarity index 93% rename from lib/commands/ROLE.spec.ts rename to packages/client/lib/commands/ROLE.spec.ts index 5b647e07ca6..2e6d9b163ae 100644 --- a/lib/commands/ROLE.spec.ts +++ b/packages/client/lib/commands/ROLE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient, TestRedisServers } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './ROLE'; describe('ROLE', () => { @@ -56,7 +56,7 @@ describe('ROLE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.role', async client => { + testUtils.testWithClient('client.role', async client => { assert.deepEqual( await client.role(), { @@ -65,5 +65,5 @@ describe('ROLE', () => { replicas: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ROLE.ts b/packages/client/lib/commands/ROLE.ts similarity index 100% rename from lib/commands/ROLE.ts rename to packages/client/lib/commands/ROLE.ts diff --git a/lib/commands/RPOP.spec.ts b/packages/client/lib/commands/RPOP.spec.ts similarity index 62% rename from lib/commands/RPOP.spec.ts rename to packages/client/lib/commands/RPOP.spec.ts index 2a753ff1a66..6e57afa3216 100644 --- a/lib/commands/RPOP.spec.ts +++ b/packages/client/lib/commands/RPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RPOP'; describe('RPOP', () => { @@ -10,17 +10,17 @@ describe('RPOP', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.rPop', async client => { + testUtils.testWithClient('client.rPop', async client => { assert.equal( await client.rPop('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.rPop', async cluster => { + testUtils.testWithCluster('cluster.rPop', async cluster => { assert.equal( await cluster.rPop('key'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/RPOP.ts b/packages/client/lib/commands/RPOP.ts similarity index 100% rename from lib/commands/RPOP.ts rename to packages/client/lib/commands/RPOP.ts diff --git a/lib/commands/RPOPLPUSH.spec.ts b/packages/client/lib/commands/RPOPLPUSH.spec.ts similarity index 66% rename from lib/commands/RPOPLPUSH.spec.ts rename to packages/client/lib/commands/RPOPLPUSH.spec.ts index 75b5f2e18f9..cef3049bd91 100644 --- a/lib/commands/RPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/RPOPLPUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RPOPLPUSH'; describe('RPOPLPUSH', () => { @@ -10,17 +10,17 @@ describe('RPOPLPUSH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.rPopLPush', async client => { + testUtils.testWithClient('client.rPopLPush', async client => { assert.equal( await client.rPopLPush('source', 'destination'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.rPopLPush', async cluster => { + testUtils.testWithCluster('cluster.rPopLPush', async cluster => { assert.equal( await cluster.rPopLPush('{tag}source', '{tag}destination'), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/RPOPLPUSH.ts b/packages/client/lib/commands/RPOPLPUSH.ts similarity index 100% rename from lib/commands/RPOPLPUSH.ts rename to packages/client/lib/commands/RPOPLPUSH.ts diff --git a/lib/commands/RPOP_COUNT.spec.ts b/packages/client/lib/commands/RPOP_COUNT.spec.ts similarity index 57% rename from lib/commands/RPOP_COUNT.spec.ts rename to packages/client/lib/commands/RPOP_COUNT.spec.ts index 2624540f124..3657a608039 100644 --- a/lib/commands/RPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/RPOP_COUNT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RPOP_COUNT'; describe('RPOP COUNT', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,17 +12,17 @@ describe('RPOP COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.rPopCount', async client => { + testUtils.testWithClient('client.rPopCount', async client => { assert.equal( await client.rPopCount('key', 1), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.rPopCount', async cluster => { + testUtils.testWithCluster('cluster.rPopCount', async cluster => { assert.equal( await cluster.rPopCount('key', 1), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/RPOP_COUNT.ts b/packages/client/lib/commands/RPOP_COUNT.ts similarity index 100% rename from lib/commands/RPOP_COUNT.ts rename to packages/client/lib/commands/RPOP_COUNT.ts diff --git a/lib/commands/RPUSH.spec.ts b/packages/client/lib/commands/RPUSH.spec.ts similarity index 73% rename from lib/commands/RPUSH.spec.ts rename to packages/client/lib/commands/RPUSH.spec.ts index 4336d10c9a3..afa5c1c6400 100644 --- a/lib/commands/RPUSH.spec.ts +++ b/packages/client/lib/commands/RPUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RPUSH'; describe('RPUSH', () => { @@ -19,17 +19,17 @@ describe('RPUSH', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.rPush', async client => { + testUtils.testWithClient('client.rPush', async client => { assert.equal( await client.rPush('key', 'element'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.rPush', async cluster => { + testUtils.testWithCluster('cluster.rPush', async cluster => { assert.equal( await cluster.rPush('key', 'element'), 1 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/RPUSH.ts b/packages/client/lib/commands/RPUSH.ts similarity index 100% rename from lib/commands/RPUSH.ts rename to packages/client/lib/commands/RPUSH.ts diff --git a/lib/commands/RPUSHX.spec.ts b/packages/client/lib/commands/RPUSHX.spec.ts similarity index 73% rename from lib/commands/RPUSHX.spec.ts rename to packages/client/lib/commands/RPUSHX.spec.ts index 18f91e8bef6..ee2041de6f2 100644 --- a/lib/commands/RPUSHX.spec.ts +++ b/packages/client/lib/commands/RPUSHX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RPUSHX'; describe('RPUSHX', () => { @@ -19,17 +19,17 @@ describe('RPUSHX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.rPushX', async client => { + testUtils.testWithClient('client.rPushX', async client => { assert.equal( await client.rPushX('key', 'element'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.rPushX', async cluster => { + testUtils.testWithCluster('cluster.rPushX', async cluster => { assert.equal( await cluster.rPushX('key', 'element'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/RPUSHX.ts b/packages/client/lib/commands/RPUSHX.ts similarity index 100% rename from lib/commands/RPUSHX.ts rename to packages/client/lib/commands/RPUSHX.ts diff --git a/lib/commands/SADD.spec.ts b/packages/client/lib/commands/SADD.spec.ts similarity index 81% rename from lib/commands/SADD.spec.ts rename to packages/client/lib/commands/SADD.spec.ts index bf1ee48fe7f..4533f6f9ad5 100644 --- a/lib/commands/SADD.spec.ts +++ b/packages/client/lib/commands/SADD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SADD'; describe('SADD', () => { @@ -19,10 +19,10 @@ describe('SADD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sAdd', async client => { + testUtils.testWithClient('client.sAdd', async client => { assert.equal( await client.sAdd('key', 'member'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SADD.ts b/packages/client/lib/commands/SADD.ts similarity index 100% rename from lib/commands/SADD.ts rename to packages/client/lib/commands/SADD.ts diff --git a/lib/commands/SAVE.spec.ts b/packages/client/lib/commands/SAVE.spec.ts similarity index 100% rename from lib/commands/SAVE.spec.ts rename to packages/client/lib/commands/SAVE.spec.ts diff --git a/lib/commands/SAVE.ts b/packages/client/lib/commands/SAVE.ts similarity index 100% rename from lib/commands/SAVE.ts rename to packages/client/lib/commands/SAVE.ts diff --git a/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts similarity index 93% rename from lib/commands/SCAN.spec.ts rename to packages/client/lib/commands/SCAN.spec.ts index 975c4cb6d2f..7657b744e02 100644 --- a/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './SCAN'; describe('SCAN', () => { @@ -72,7 +72,7 @@ describe('SCAN', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.scan', async client => { + testUtils.testWithClient('client.scan', async client => { assert.deepEqual( await client.scan(0), { @@ -80,5 +80,5 @@ describe('SCAN', () => { keys: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts similarity index 100% rename from lib/commands/SCAN.ts rename to packages/client/lib/commands/SCAN.ts diff --git a/lib/commands/SCARD.spec.ts b/packages/client/lib/commands/SCARD.spec.ts similarity index 70% rename from lib/commands/SCARD.spec.ts rename to packages/client/lib/commands/SCARD.spec.ts index b6681693814..afc21c6b00c 100644 --- a/lib/commands/SCARD.spec.ts +++ b/packages/client/lib/commands/SCARD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SCARD'; describe('SCARD', () => { @@ -10,10 +10,10 @@ describe('SCARD', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sCard', async client => { + testUtils.testWithClient('client.sCard', async client => { assert.equal( await client.sCard('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCARD.ts b/packages/client/lib/commands/SCARD.ts similarity index 100% rename from lib/commands/SCARD.ts rename to packages/client/lib/commands/SCARD.ts diff --git a/lib/commands/SCRIPT_DEBUG.spec.ts b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts similarity index 71% rename from lib/commands/SCRIPT_DEBUG.spec.ts rename to packages/client/lib/commands/SCRIPT_DEBUG.spec.ts index 9d2ad1af266..192f90f75a5 100644 --- a/lib/commands/SCRIPT_DEBUG.spec.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SCRIPT_DEBUG'; describe('SCRIPT DEBUG', () => { @@ -10,10 +10,10 @@ describe('SCRIPT DEBUG', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.scriptDebug', async client => { + testUtils.testWithClient('client.scriptDebug', async client => { assert.equal( await client.scriptDebug('NO'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCRIPT_DEBUG.ts b/packages/client/lib/commands/SCRIPT_DEBUG.ts similarity index 100% rename from lib/commands/SCRIPT_DEBUG.ts rename to packages/client/lib/commands/SCRIPT_DEBUG.ts diff --git a/lib/commands/SCRIPT_EXISTS.spec.ts b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts similarity index 80% rename from lib/commands/SCRIPT_EXISTS.spec.ts rename to packages/client/lib/commands/SCRIPT_EXISTS.spec.ts index b23380c7579..e0fbbcc5537 100644 --- a/lib/commands/SCRIPT_EXISTS.spec.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SCRIPT_EXISTS'; describe('SCRIPT EXISTS', () => { @@ -19,10 +19,10 @@ describe('SCRIPT EXISTS', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.scriptExists', async client => { + testUtils.testWithClient('client.scriptExists', async client => { assert.deepEqual( await client.scriptExists('sha1'), [false] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts similarity index 56% rename from lib/commands/SCRIPT_EXISTS.ts rename to packages/client/lib/commands/SCRIPT_EXISTS.ts index ee89f955e50..d4f65cfd72b 100644 --- a/lib/commands/SCRIPT_EXISTS.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.ts @@ -1,8 +1,8 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments, transformReplyBooleanArray } from './generic-transformers'; +import { pushVerdictArguments } from './generic-transformers'; export function transformArguments(sha1: string | Array): RedisCommandArguments { return pushVerdictArguments(['SCRIPT', 'EXISTS'], sha1); } -export const transformReply = transformReplyBooleanArray; +export { transformReplyBooleanArray as transformReply } from './generic-transformers'; diff --git a/lib/commands/SCRIPT_FLUSH.spec.ts b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts similarity index 80% rename from lib/commands/SCRIPT_FLUSH.spec.ts rename to packages/client/lib/commands/SCRIPT_FLUSH.spec.ts index c77accb50a9..ae156e937d1 100644 --- a/lib/commands/SCRIPT_FLUSH.spec.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SCRIPT_FLUSH'; describe('SCRIPT FLUSH', () => { @@ -19,10 +19,10 @@ describe('SCRIPT FLUSH', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.scriptFlush', async client => { + testUtils.testWithClient('client.scriptFlush', async client => { assert.equal( await client.scriptFlush(), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCRIPT_FLUSH.ts b/packages/client/lib/commands/SCRIPT_FLUSH.ts similarity index 100% rename from lib/commands/SCRIPT_FLUSH.ts rename to packages/client/lib/commands/SCRIPT_FLUSH.ts diff --git a/lib/commands/SCRIPT_KILL.spec.ts b/packages/client/lib/commands/SCRIPT_KILL.spec.ts similarity index 100% rename from lib/commands/SCRIPT_KILL.spec.ts rename to packages/client/lib/commands/SCRIPT_KILL.spec.ts diff --git a/lib/commands/SCRIPT_KILL.ts b/packages/client/lib/commands/SCRIPT_KILL.ts similarity index 100% rename from lib/commands/SCRIPT_KILL.ts rename to packages/client/lib/commands/SCRIPT_KILL.ts diff --git a/lib/commands/SCRIPT_LOAD.spec.ts b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts similarity index 77% rename from lib/commands/SCRIPT_LOAD.spec.ts rename to packages/client/lib/commands/SCRIPT_LOAD.spec.ts index 1d7da3e9c2d..062f3c201e1 100644 --- a/lib/commands/SCRIPT_LOAD.spec.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts @@ -1,6 +1,6 @@ import { strict as assert } from 'assert'; import { scriptSha1 } from '../lua-script'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SCRIPT_LOAD'; describe('SCRIPT LOAD', () => { @@ -14,10 +14,10 @@ describe('SCRIPT LOAD', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.scriptLoad', async client => { + testUtils.testWithClient('client.scriptLoad', async client => { assert.equal( await client.scriptLoad(SCRIPT), SCRIPT_SHA1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SCRIPT_LOAD.ts b/packages/client/lib/commands/SCRIPT_LOAD.ts similarity index 100% rename from lib/commands/SCRIPT_LOAD.ts rename to packages/client/lib/commands/SCRIPT_LOAD.ts diff --git a/lib/commands/SDIFF.spec.ts b/packages/client/lib/commands/SDIFF.spec.ts similarity index 80% rename from lib/commands/SDIFF.spec.ts rename to packages/client/lib/commands/SDIFF.spec.ts index 82ef2dac6fc..340906e9350 100644 --- a/lib/commands/SDIFF.spec.ts +++ b/packages/client/lib/commands/SDIFF.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SDIFF'; describe('SDIFF', () => { @@ -19,10 +19,10 @@ describe('SDIFF', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sDiff', async client => { + testUtils.testWithClient('client.sDiff', async client => { assert.deepEqual( await client.sDiff('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SDIFF.ts b/packages/client/lib/commands/SDIFF.ts similarity index 100% rename from lib/commands/SDIFF.ts rename to packages/client/lib/commands/SDIFF.ts diff --git a/lib/commands/SDIFFSTORE.spec.ts b/packages/client/lib/commands/SDIFFSTORE.spec.ts similarity index 82% rename from lib/commands/SDIFFSTORE.spec.ts rename to packages/client/lib/commands/SDIFFSTORE.spec.ts index 1e7f5f6f32c..263b4f43f64 100644 --- a/lib/commands/SDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/SDIFFSTORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SDIFFSTORE'; describe('SDIFFSTORE', () => { @@ -19,10 +19,10 @@ describe('SDIFFSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sDiffStore', async client => { + testUtils.testWithClient('client.sDiffStore', async client => { assert.equal( await client.sDiffStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SDIFFSTORE.ts b/packages/client/lib/commands/SDIFFSTORE.ts similarity index 100% rename from lib/commands/SDIFFSTORE.ts rename to packages/client/lib/commands/SDIFFSTORE.ts diff --git a/lib/commands/SET.spec.ts b/packages/client/lib/commands/SET.spec.ts similarity index 91% rename from lib/commands/SET.spec.ts rename to packages/client/lib/commands/SET.spec.ts index 32d138f2920..353885a3097 100644 --- a/lib/commands/SET.spec.ts +++ b/packages/client/lib/commands/SET.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SET'; describe('SET', () => { @@ -100,14 +100,14 @@ describe('SET', () => { }); describe('client.set', () => { - itWithClient(TestRedisServers.OPEN, 'simple', async client => { + testUtils.testWithClient('simple', async client => { assert.equal( await client.set('key', 'value'), 'OK' ); - }); - - itWithClient(TestRedisServers.OPEN, 'with GET on empty key', async client => { + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with GET on empty key', async client => { assert.equal( await client.set('key', 'value', { GET: true @@ -115,7 +115,8 @@ describe('SET', () => { null ); }, { - minimumRedisVersion: [6, 2] + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] }); }); }); diff --git a/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts similarity index 59% rename from lib/commands/SET.ts rename to packages/client/lib/commands/SET.ts index b19a1b2c5c2..fdc7eef1986 100644 --- a/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -2,43 +2,27 @@ import { RedisCommandArguments } from '.'; export const FIRST_KEY_INDEX = 1; -interface EX { - EX: number; -} - -interface PX { - PX: number -} +type MaximumOneOf = + K extends keyof T ? { [P in K]?: T[K] } & Partial, never>> : never; -interface EXAT { +type SetTTL = MaximumOneOf<{ + EX: number; + PX: number; EXAT: number; -} - -interface PXAT { PXAT: number; -} - -interface KEEPTTL { KEEPTTL: true; -} +}>; -type SetTTL = EX | PX | EXAT | PXAT | KEEPTTL | {}; - -interface NX { +type SetGuards = MaximumOneOf<{ NX: true; -} - -interface XX { XX: true; -} - -type SetGuards = NX | XX | {}; +}>; interface SetCommonOptions { - GET: true + GET?: true; } -type SetOptions = SetTTL & SetGuards & (SetCommonOptions | {}); +type SetOptions = SetTTL & SetGuards & SetCommonOptions; export function transformArguments(key: string | Buffer, value: string | Buffer, options?: SetOptions): RedisCommandArguments { const args = ['SET', key, value]; @@ -47,25 +31,25 @@ export function transformArguments(key: string | Buffer, value: string | Buffer, return args; } - if ('EX' in options) { + if (options.EX) { args.push('EX', options.EX.toString()); - } else if ('PX' in options) { + } else if (options.PX) { args.push('PX', options.PX.toString()); - } else if ('EXAT' in options) { + } else if (options.EXAT) { args.push('EXAT', options.EXAT.toString()); - } else if ('PXAT' in options) { + } else if (options.PXAT) { args.push('PXAT', options.PXAT.toString()); - } else if ((options).KEEPTTL) { + } else if (options.KEEPTTL) { args.push('KEEPTTL'); } - if ((options).NX) { + if (options.NX) { args.push('NX'); - } else if ((options).XX) { + } else if (options.XX) { args.push('XX'); } - if ((options).GET) { + if (options.GET) { args.push('GET'); } diff --git a/lib/commands/SETBIT.spec.ts b/packages/client/lib/commands/SETBIT.spec.ts similarity index 64% rename from lib/commands/SETBIT.spec.ts rename to packages/client/lib/commands/SETBIT.spec.ts index 7347913f293..43fbff7c2d9 100644 --- a/lib/commands/SETBIT.spec.ts +++ b/packages/client/lib/commands/SETBIT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SETBIT'; describe('SETBIT', () => { @@ -10,17 +10,17 @@ describe('SETBIT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.setBit', async client => { + testUtils.testWithClient('client.setBit', async client => { assert.equal( await client.setBit('key', 0, 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.setBit', async cluster => { + testUtils.testWithCluster('cluster.setBit', async cluster => { assert.equal( await cluster.setBit('key', 0, 1), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/SETBIT.ts b/packages/client/lib/commands/SETBIT.ts similarity index 100% rename from lib/commands/SETBIT.ts rename to packages/client/lib/commands/SETBIT.ts diff --git a/lib/commands/SETEX.spec.ts b/packages/client/lib/commands/SETEX.spec.ts similarity index 65% rename from lib/commands/SETEX.spec.ts rename to packages/client/lib/commands/SETEX.spec.ts index 7ea55eba83c..bca298c6c04 100644 --- a/lib/commands/SETEX.spec.ts +++ b/packages/client/lib/commands/SETEX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SETEX'; describe('SETEX', () => { @@ -10,17 +10,17 @@ describe('SETEX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.setEx', async client => { + testUtils.testWithClient('client.setEx', async client => { assert.equal( await client.setEx('key', 1, 'value'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.setEx', async cluster => { + testUtils.testWithCluster('cluster.setEx', async cluster => { assert.equal( await cluster.setEx('key', 1, 'value'), 'OK' ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/SETEX.ts b/packages/client/lib/commands/SETEX.ts similarity index 100% rename from lib/commands/SETEX.ts rename to packages/client/lib/commands/SETEX.ts diff --git a/lib/commands/SETNX .spec.ts b/packages/client/lib/commands/SETNX .spec.ts similarity index 64% rename from lib/commands/SETNX .spec.ts rename to packages/client/lib/commands/SETNX .spec.ts index daf3ca6e76a..c5bdfcffa2c 100644 --- a/lib/commands/SETNX .spec.ts +++ b/packages/client/lib/commands/SETNX .spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, TestRedisClusters, itWithCluster } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SETNX'; describe('SETNX', () => { @@ -10,17 +10,17 @@ describe('SETNX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.setNX', async client => { + testUtils.testWithClient('client.setNX', async client => { assert.equal( await client.setNX('key', 'value'), true ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.setNX', async cluster => { + testUtils.testWithCluster('cluster.setNX', async cluster => { assert.equal( await cluster.setNX('key', 'value'), true ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/SETNX.ts b/packages/client/lib/commands/SETNX.ts similarity index 56% rename from lib/commands/SETNX.ts rename to packages/client/lib/commands/SETNX.ts index f0097836581..b45e93b0f7d 100644 --- a/lib/commands/SETNX.ts +++ b/packages/client/lib/commands/SETNX.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, value: string): Array { return ['SETNX', key, value]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/SETRANGE.spec.ts b/packages/client/lib/commands/SETRANGE.spec.ts similarity index 65% rename from lib/commands/SETRANGE.spec.ts rename to packages/client/lib/commands/SETRANGE.spec.ts index 766c56c5ff1..398b7730404 100644 --- a/lib/commands/SETRANGE.spec.ts +++ b/packages/client/lib/commands/SETRANGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SETRANGE'; describe('SETRANGE', () => { @@ -10,17 +10,17 @@ describe('SETRANGE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.setRange', async client => { + testUtils.testWithClient('client.setRange', async client => { assert.equal( await client.setRange('key', 0, 'value'), 5 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.setRange', async cluster => { + testUtils.testWithCluster('cluster.setRange', async cluster => { assert.equal( await cluster.setRange('key', 0, 'value'), 5 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/SETRANGE.ts b/packages/client/lib/commands/SETRANGE.ts similarity index 100% rename from lib/commands/SETRANGE.ts rename to packages/client/lib/commands/SETRANGE.ts diff --git a/lib/commands/SHUTDOWN.spec.ts b/packages/client/lib/commands/SHUTDOWN.spec.ts similarity index 100% rename from lib/commands/SHUTDOWN.spec.ts rename to packages/client/lib/commands/SHUTDOWN.spec.ts diff --git a/lib/commands/SHUTDOWN.ts b/packages/client/lib/commands/SHUTDOWN.ts similarity index 100% rename from lib/commands/SHUTDOWN.ts rename to packages/client/lib/commands/SHUTDOWN.ts diff --git a/lib/commands/SINTER.spec.ts b/packages/client/lib/commands/SINTER.spec.ts similarity index 80% rename from lib/commands/SINTER.spec.ts rename to packages/client/lib/commands/SINTER.spec.ts index 8fee35427cf..2324eac3ee8 100644 --- a/lib/commands/SINTER.spec.ts +++ b/packages/client/lib/commands/SINTER.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SINTER'; describe('SINTER', () => { @@ -19,10 +19,10 @@ describe('SINTER', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sInter', async client => { + testUtils.testWithClient('client.sInter', async client => { assert.deepEqual( await client.sInter('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SINTER.ts b/packages/client/lib/commands/SINTER.ts similarity index 100% rename from lib/commands/SINTER.ts rename to packages/client/lib/commands/SINTER.ts diff --git a/lib/commands/SINTERSTORE.spec.ts b/packages/client/lib/commands/SINTERSTORE.spec.ts similarity index 82% rename from lib/commands/SINTERSTORE.spec.ts rename to packages/client/lib/commands/SINTERSTORE.spec.ts index 013931d2312..c4a6a095e7d 100644 --- a/lib/commands/SINTERSTORE.spec.ts +++ b/packages/client/lib/commands/SINTERSTORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SINTERSTORE'; describe('SINTERSTORE', () => { @@ -19,10 +19,10 @@ describe('SINTERSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sInterStore', async client => { + testUtils.testWithClient('client.sInterStore', async client => { assert.equal( await client.sInterStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SINTERSTORE.ts b/packages/client/lib/commands/SINTERSTORE.ts similarity index 100% rename from lib/commands/SINTERSTORE.ts rename to packages/client/lib/commands/SINTERSTORE.ts diff --git a/lib/commands/SISMEMBER.spec.ts b/packages/client/lib/commands/SISMEMBER.spec.ts similarity index 63% rename from lib/commands/SISMEMBER.spec.ts rename to packages/client/lib/commands/SISMEMBER.spec.ts index fec4ebfc57d..8d18c83697a 100644 --- a/lib/commands/SISMEMBER.spec.ts +++ b/packages/client/lib/commands/SISMEMBER.spec.ts @@ -1,10 +1,8 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SISMEMBER'; describe('SISMEMBER', () => { - describeHandleMinimumRedisVersion([6, 2]); - it('transformArguments', () => { assert.deepEqual( transformArguments('key', 'member'), @@ -12,10 +10,10 @@ describe('SISMEMBER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sIsMember', async client => { + testUtils.testWithClient('client.sIsMember', async client => { assert.equal( await client.sIsMember('key', 'member'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SISMEMBER.ts b/packages/client/lib/commands/SISMEMBER.ts similarity index 57% rename from lib/commands/SISMEMBER.ts rename to packages/client/lib/commands/SISMEMBER.ts index 661410fce0d..d8c47a76a69 100644 --- a/lib/commands/SISMEMBER.ts +++ b/packages/client/lib/commands/SISMEMBER.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, member: string): Array { return ['SISMEMBER', key, member]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/SMEMBERS.spec.ts b/packages/client/lib/commands/SMEMBERS.spec.ts similarity index 71% rename from lib/commands/SMEMBERS.spec.ts rename to packages/client/lib/commands/SMEMBERS.spec.ts index 2398dbaa8c6..b9c58c9eebb 100644 --- a/lib/commands/SMEMBERS.spec.ts +++ b/packages/client/lib/commands/SMEMBERS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SMEMBERS'; describe('SMEMBERS', () => { @@ -10,10 +10,10 @@ describe('SMEMBERS', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sMembers', async client => { + testUtils.testWithClient('client.sMembers', async client => { assert.deepEqual( await client.sMembers('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SMEMBERS.ts b/packages/client/lib/commands/SMEMBERS.ts similarity index 100% rename from lib/commands/SMEMBERS.ts rename to packages/client/lib/commands/SMEMBERS.ts diff --git a/lib/commands/SMISMEMBER.spec.ts b/packages/client/lib/commands/SMISMEMBER.spec.ts similarity index 64% rename from lib/commands/SMISMEMBER.spec.ts rename to packages/client/lib/commands/SMISMEMBER.spec.ts index 320f60d4ba2..e3728134029 100644 --- a/lib/commands/SMISMEMBER.spec.ts +++ b/packages/client/lib/commands/SMISMEMBER.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SMISMEMBER'; describe('SMISMEMBER', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('SMISMEMBER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.smIsMember', async client => { + testUtils.testWithClient('client.smIsMember', async client => { assert.deepEqual( await client.smIsMember('key', ['1', '2']), [false, false] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SMISMEMBER.ts b/packages/client/lib/commands/SMISMEMBER.ts similarity index 57% rename from lib/commands/SMISMEMBER.ts rename to packages/client/lib/commands/SMISMEMBER.ts index 07637a689b6..85b954bc3d7 100644 --- a/lib/commands/SMISMEMBER.ts +++ b/packages/client/lib/commands/SMISMEMBER.ts @@ -1,9 +1,7 @@ -import { transformReplyBooleanArray } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string, members: Array): Array { return ['SMISMEMBER', key, ...members]; } -export const transformReply = transformReplyBooleanArray; +export { transformReplyBooleanArray as transformReply } from './generic-transformers'; diff --git a/lib/commands/SMOVE.spec.ts b/packages/client/lib/commands/SMOVE.spec.ts similarity index 75% rename from lib/commands/SMOVE.spec.ts rename to packages/client/lib/commands/SMOVE.spec.ts index 97e938a46bb..e3308ee8143 100644 --- a/lib/commands/SMOVE.spec.ts +++ b/packages/client/lib/commands/SMOVE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SMOVE'; describe('SMOVE', () => { @@ -10,10 +10,10 @@ describe('SMOVE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sMove', async client => { + testUtils.testWithClient('client.sMove', async client => { assert.equal( await client.sMove('source', 'destination', 'member'), false ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SMOVE.ts b/packages/client/lib/commands/SMOVE.ts similarity index 62% rename from lib/commands/SMOVE.ts rename to packages/client/lib/commands/SMOVE.ts index f8922f6ca3f..7850b8f9ddc 100644 --- a/lib/commands/SMOVE.ts +++ b/packages/client/lib/commands/SMOVE.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export function transformArguments(source: string, destination: string, member: string): Array { return ['SMOVE', source, destination, member]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/SORT.spec.ts b/packages/client/lib/commands/SORT.spec.ts similarity index 94% rename from lib/commands/SORT.spec.ts rename to packages/client/lib/commands/SORT.spec.ts index c449e0511f0..637f48876dc 100644 --- a/lib/commands/SORT.spec.ts +++ b/packages/client/lib/commands/SORT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SORT'; describe('SORT', () => { @@ -60,7 +60,7 @@ describe('SORT', () => { ['SORT', 'key', 'ASC'] ); }); - + it('with ALPHA', () => { assert.deepEqual( transformArguments('key', { @@ -97,10 +97,10 @@ describe('SORT', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sort', async client => { + testUtils.testWithClient('client.sort', async client => { assert.deepEqual( await client.sort('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SORT.ts b/packages/client/lib/commands/SORT.ts similarity index 100% rename from lib/commands/SORT.ts rename to packages/client/lib/commands/SORT.ts diff --git a/lib/commands/SPOP.spec.ts b/packages/client/lib/commands/SPOP.spec.ts similarity index 80% rename from lib/commands/SPOP.spec.ts rename to packages/client/lib/commands/SPOP.spec.ts index 238c58f4796..6a384d181fc 100644 --- a/lib/commands/SPOP.spec.ts +++ b/packages/client/lib/commands/SPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SPOP'; describe('SPOP', () => { @@ -19,10 +19,10 @@ describe('SPOP', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sPop', async client => { + testUtils.testWithClient('client.sPop', async client => { assert.equal( await client.sPop('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SPOP.ts b/packages/client/lib/commands/SPOP.ts similarity index 100% rename from lib/commands/SPOP.ts rename to packages/client/lib/commands/SPOP.ts diff --git a/lib/commands/SRANDMEMBER.spec.ts b/packages/client/lib/commands/SRANDMEMBER.spec.ts similarity index 71% rename from lib/commands/SRANDMEMBER.spec.ts rename to packages/client/lib/commands/SRANDMEMBER.spec.ts index 5c359f73f96..291271540be 100644 --- a/lib/commands/SRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SRANDMEMBER'; describe('SRANDMEMBER', () => { @@ -10,10 +10,10 @@ describe('SRANDMEMBER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sRandMember', async client => { + testUtils.testWithClient('client.sRandMember', async client => { assert.equal( await client.sRandMember('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SRANDMEMBER.ts b/packages/client/lib/commands/SRANDMEMBER.ts similarity index 100% rename from lib/commands/SRANDMEMBER.ts rename to packages/client/lib/commands/SRANDMEMBER.ts diff --git a/lib/commands/SRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts similarity index 72% rename from lib/commands/SRANDMEMBER_COUNT.spec.ts rename to packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts index 81a4fd45f31..d3d787b3e63 100644 --- a/lib/commands/SRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SRANDMEMBER_COUNT'; describe('SRANDMEMBER COUNT', () => { @@ -10,10 +10,10 @@ describe('SRANDMEMBER COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.sRandMemberCount', async client => { + testUtils.testWithClient('client.sRandMemberCount', async client => { assert.deepEqual( await client.sRandMemberCount('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SRANDMEMBER_COUNT.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.ts similarity index 100% rename from lib/commands/SRANDMEMBER_COUNT.ts rename to packages/client/lib/commands/SRANDMEMBER_COUNT.ts diff --git a/lib/commands/SREM.spec.ts b/packages/client/lib/commands/SREM.spec.ts similarity index 81% rename from lib/commands/SREM.spec.ts rename to packages/client/lib/commands/SREM.spec.ts index c9270624ae9..d53d7b0334d 100644 --- a/lib/commands/SREM.spec.ts +++ b/packages/client/lib/commands/SREM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SREM'; describe('SREM', () => { @@ -19,10 +19,10 @@ describe('SREM', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sRem', async client => { + testUtils.testWithClient('client.sRem', async client => { assert.equal( await client.sRem('key', 'member'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SREM.ts b/packages/client/lib/commands/SREM.ts similarity index 100% rename from lib/commands/SREM.ts rename to packages/client/lib/commands/SREM.ts diff --git a/lib/commands/SSCAN.spec.ts b/packages/client/lib/commands/SSCAN.spec.ts similarity index 92% rename from lib/commands/SSCAN.spec.ts rename to packages/client/lib/commands/SSCAN.spec.ts index 9b203ffb83e..71a90bf81d8 100644 --- a/lib/commands/SSCAN.spec.ts +++ b/packages/client/lib/commands/SSCAN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './SSCAN'; describe('SSCAN', () => { @@ -62,7 +62,7 @@ describe('SSCAN', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sScan', async client => { + testUtils.testWithClient('client.sScan', async client => { assert.deepEqual( await client.sScan('key', 0), { @@ -70,5 +70,5 @@ describe('SSCAN', () => { members: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SSCAN.ts b/packages/client/lib/commands/SSCAN.ts similarity index 100% rename from lib/commands/SSCAN.ts rename to packages/client/lib/commands/SSCAN.ts diff --git a/lib/commands/STRLEN.spec.ts b/packages/client/lib/commands/STRLEN.spec.ts similarity index 62% rename from lib/commands/STRLEN.spec.ts rename to packages/client/lib/commands/STRLEN.spec.ts index 3d24e360372..519c68d3e5d 100644 --- a/lib/commands/STRLEN.spec.ts +++ b/packages/client/lib/commands/STRLEN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './STRLEN'; describe('STRLEN', () => { @@ -10,17 +10,17 @@ describe('STRLEN', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.strLen', async client => { + testUtils.testWithClient('client.strLen', async client => { assert.equal( await client.strLen('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.strLen', async cluster => { + testUtils.testWithCluster('cluster.strLen', async cluster => { assert.equal( await cluster.strLen('key'), 0 ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/STRLEN.ts b/packages/client/lib/commands/STRLEN.ts similarity index 100% rename from lib/commands/STRLEN.ts rename to packages/client/lib/commands/STRLEN.ts diff --git a/lib/commands/SUNION.spec.ts b/packages/client/lib/commands/SUNION.spec.ts similarity index 80% rename from lib/commands/SUNION.spec.ts rename to packages/client/lib/commands/SUNION.spec.ts index fdf97668971..2918607c1d6 100644 --- a/lib/commands/SUNION.spec.ts +++ b/packages/client/lib/commands/SUNION.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SUNION'; describe('SUNION', () => { @@ -19,10 +19,10 @@ describe('SUNION', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sUnion', async client => { + testUtils.testWithClient('client.sUnion', async client => { assert.deepEqual( await client.sUnion('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SUNION.ts b/packages/client/lib/commands/SUNION.ts similarity index 100% rename from lib/commands/SUNION.ts rename to packages/client/lib/commands/SUNION.ts diff --git a/lib/commands/SUNIONSTORE.spec.ts b/packages/client/lib/commands/SUNIONSTORE.spec.ts similarity index 82% rename from lib/commands/SUNIONSTORE.spec.ts rename to packages/client/lib/commands/SUNIONSTORE.spec.ts index 82c9a03a0b8..142533eea2b 100644 --- a/lib/commands/SUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/SUNIONSTORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SUNIONSTORE'; describe('SUNIONSTORE', () => { @@ -19,10 +19,10 @@ describe('SUNIONSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.sUnionStore', async client => { + testUtils.testWithClient('client.sUnionStore', async client => { assert.equal( await client.sUnionStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SUNIONSTORE.ts b/packages/client/lib/commands/SUNIONSTORE.ts similarity index 100% rename from lib/commands/SUNIONSTORE.ts rename to packages/client/lib/commands/SUNIONSTORE.ts diff --git a/lib/commands/SWAPDB.spec.ts b/packages/client/lib/commands/SWAPDB.spec.ts similarity index 71% rename from lib/commands/SWAPDB.spec.ts rename to packages/client/lib/commands/SWAPDB.spec.ts index 1a5637ae43d..add87512a64 100644 --- a/lib/commands/SWAPDB.spec.ts +++ b/packages/client/lib/commands/SWAPDB.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { itWithClient, TestRedisServers } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SWAPDB'; describe('SWAPDB', () => { @@ -10,10 +10,10 @@ describe('SWAPDB', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.swapDb', async client => { + testUtils.testWithClient('client.swapDb', async client => { assert.equal( await client.swapDb(0, 1), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/SWAPDB.ts b/packages/client/lib/commands/SWAPDB.ts similarity index 100% rename from lib/commands/SWAPDB.ts rename to packages/client/lib/commands/SWAPDB.ts diff --git a/lib/commands/TIME.spec.ts b/packages/client/lib/commands/TIME.spec.ts similarity index 73% rename from lib/commands/TIME.spec.ts rename to packages/client/lib/commands/TIME.spec.ts index 1a07114af4b..bbaa7942db0 100644 --- a/lib/commands/TIME.spec.ts +++ b/packages/client/lib/commands/TIME.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './TIME'; describe('TIME', () => { @@ -10,9 +10,9 @@ describe('TIME', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.time', async client => { + testUtils.testWithClient('client.time', async client => { const reply = await client.time(); assert.ok(reply instanceof Date); assert.ok(typeof reply.microseconds === 'number'); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/TIME.ts b/packages/client/lib/commands/TIME.ts similarity index 100% rename from lib/commands/TIME.ts rename to packages/client/lib/commands/TIME.ts diff --git a/lib/commands/TOUCH.spec.ts b/packages/client/lib/commands/TOUCH.spec.ts similarity index 80% rename from lib/commands/TOUCH.spec.ts rename to packages/client/lib/commands/TOUCH.spec.ts index c4cb4356291..578c49587d7 100644 --- a/lib/commands/TOUCH.spec.ts +++ b/packages/client/lib/commands/TOUCH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './TOUCH'; describe('TOUCH', () => { @@ -19,10 +19,10 @@ describe('TOUCH', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.touch', async client => { + testUtils.testWithClient('client.touch', async client => { assert.equal( await client.touch('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/TOUCH.ts b/packages/client/lib/commands/TOUCH.ts similarity index 100% rename from lib/commands/TOUCH.ts rename to packages/client/lib/commands/TOUCH.ts diff --git a/lib/commands/TTL.spec.ts b/packages/client/lib/commands/TTL.spec.ts similarity index 70% rename from lib/commands/TTL.spec.ts rename to packages/client/lib/commands/TTL.spec.ts index bcabe8d39e5..e37a6ab714b 100644 --- a/lib/commands/TTL.spec.ts +++ b/packages/client/lib/commands/TTL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './TTL'; describe('TTL', () => { @@ -10,10 +10,10 @@ describe('TTL', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.ttl', async client => { + testUtils.testWithClient('client.ttl', async client => { assert.equal( await client.ttl('key'), -2 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/TTL.ts b/packages/client/lib/commands/TTL.ts similarity index 100% rename from lib/commands/TTL.ts rename to packages/client/lib/commands/TTL.ts diff --git a/lib/commands/TYPE.spec.ts b/packages/client/lib/commands/TYPE.spec.ts similarity index 71% rename from lib/commands/TYPE.spec.ts rename to packages/client/lib/commands/TYPE.spec.ts index d40f724242d..1040bf979b3 100644 --- a/lib/commands/TYPE.spec.ts +++ b/packages/client/lib/commands/TYPE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './TYPE'; describe('TYPE', () => { @@ -10,10 +10,10 @@ describe('TYPE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.type', async client => { + testUtils.testWithClient('client.type', async client => { assert.equal( await client.type('key'), 'none' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/TYPE.ts b/packages/client/lib/commands/TYPE.ts similarity index 100% rename from lib/commands/TYPE.ts rename to packages/client/lib/commands/TYPE.ts diff --git a/lib/commands/UNLINK.spec.ts b/packages/client/lib/commands/UNLINK.spec.ts similarity index 80% rename from lib/commands/UNLINK.spec.ts rename to packages/client/lib/commands/UNLINK.spec.ts index a0dddf54f25..e8355407d8f 100644 --- a/lib/commands/UNLINK.spec.ts +++ b/packages/client/lib/commands/UNLINK.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './UNLINK'; describe('UNLINK', () => { @@ -19,10 +19,10 @@ describe('UNLINK', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.unlink', async client => { + testUtils.testWithClient('client.unlink', async client => { assert.equal( await client.unlink('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/UNLINK.ts b/packages/client/lib/commands/UNLINK.ts similarity index 100% rename from lib/commands/UNLINK.ts rename to packages/client/lib/commands/UNLINK.ts diff --git a/lib/commands/UNWATCH.spec.ts b/packages/client/lib/commands/UNWATCH.spec.ts similarity index 70% rename from lib/commands/UNWATCH.spec.ts rename to packages/client/lib/commands/UNWATCH.spec.ts index 07059310cbc..109ed0fa7c0 100644 --- a/lib/commands/UNWATCH.spec.ts +++ b/packages/client/lib/commands/UNWATCH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './UNWATCH'; describe('UNWATCH', () => { @@ -10,10 +10,10 @@ describe('UNWATCH', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.unwatch', async client => { + testUtils.testWithClient('client.unwatch', async client => { assert.equal( await client.unwatch(), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts similarity index 100% rename from lib/commands/UNWATCH.ts rename to packages/client/lib/commands/UNWATCH.ts diff --git a/lib/commands/WAIT.spec.ts b/packages/client/lib/commands/WAIT.spec.ts similarity index 70% rename from lib/commands/WAIT.spec.ts rename to packages/client/lib/commands/WAIT.spec.ts index c3f53b7db70..c85ef598612 100644 --- a/lib/commands/WAIT.spec.ts +++ b/packages/client/lib/commands/WAIT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './WAIT'; describe('WAIT', () => { @@ -10,10 +10,10 @@ describe('WAIT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.wait', async client => { + testUtils.testWithClient('client.wait', async client => { assert.equal( await client.wait(0, 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/WAIT.ts b/packages/client/lib/commands/WAIT.ts similarity index 100% rename from lib/commands/WAIT.ts rename to packages/client/lib/commands/WAIT.ts diff --git a/lib/commands/WATCH.spec.ts b/packages/client/lib/commands/WATCH.spec.ts similarity index 100% rename from lib/commands/WATCH.spec.ts rename to packages/client/lib/commands/WATCH.spec.ts diff --git a/lib/commands/WATCH.ts b/packages/client/lib/commands/WATCH.ts similarity index 100% rename from lib/commands/WATCH.ts rename to packages/client/lib/commands/WATCH.ts diff --git a/lib/commands/XACK.spec.ts b/packages/client/lib/commands/XACK.spec.ts similarity index 82% rename from lib/commands/XACK.spec.ts rename to packages/client/lib/commands/XACK.spec.ts index fb267c355eb..0586a5921fd 100644 --- a/lib/commands/XACK.spec.ts +++ b/packages/client/lib/commands/XACK.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XACK'; describe('XACK', () => { @@ -19,10 +19,10 @@ describe('XACK', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xAck', async client => { + testUtils.testWithClient('client.xAck', async client => { assert.equal( await client.xAck('key', 'group', '1-0'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XACK.ts b/packages/client/lib/commands/XACK.ts similarity index 100% rename from lib/commands/XACK.ts rename to packages/client/lib/commands/XACK.ts diff --git a/lib/commands/XADD.spec.ts b/packages/client/lib/commands/XADD.spec.ts similarity index 95% rename from lib/commands/XADD.spec.ts rename to packages/client/lib/commands/XADD.spec.ts index 02e6888051c..4b556ecc27c 100644 --- a/lib/commands/XADD.spec.ts +++ b/packages/client/lib/commands/XADD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XADD'; describe('XADD', () => { @@ -60,7 +60,7 @@ describe('XADD', () => { ['XADD', 'key', 'MAXLEN', '1000', '*','field', 'value'] ); }); - + it('with TRIM.strategyModifier', () => { assert.deepEqual( transformArguments('key', '*', { @@ -107,12 +107,12 @@ describe('XADD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xAdd', async client => { + testUtils.testWithClient('client.xAdd', async client => { assert.equal( typeof await client.xAdd('key', '*', { field: 'value' }), 'string' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XADD.ts b/packages/client/lib/commands/XADD.ts similarity index 100% rename from lib/commands/XADD.ts rename to packages/client/lib/commands/XADD.ts diff --git a/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts similarity index 82% rename from lib/commands/XAUTOCLAIM.spec.ts rename to packages/client/lib/commands/XAUTOCLAIM.spec.ts index a0818d5c2c3..4447a06d773 100644 --- a/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XAUTOCLAIM'; describe('XAUTOCLAIM', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('simple', () => { @@ -23,14 +23,14 @@ describe('XAUTOCLAIM', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xAutoClaim', async client => { + testUtils.testWithClient('client.xAutoClaim', async client => { await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), client.xGroupCreateConsumer('key', 'group', 'consumer'), ]); - + assert.deepEqual( await client.xAutoClaim('key', 'group', 'consumer', 1, '0-0'), { @@ -38,5 +38,5 @@ describe('XAUTOCLAIM', () => { messages: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts similarity index 100% rename from lib/commands/XAUTOCLAIM.ts rename to packages/client/lib/commands/XAUTOCLAIM.ts diff --git a/lib/commands/XAUTOCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts similarity index 76% rename from lib/commands/XAUTOCLAIM_JUSTID.spec.ts rename to packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts index d076f28751a..9aa24cd04a4 100644 --- a/lib/commands/XAUTOCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XAUTOCLAIM_JUSTID'; describe('XAUTOCLAIM JUSTID', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,7 +12,7 @@ describe('XAUTOCLAIM JUSTID', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xAutoClaimJustId', async client => { + testUtils.testWithClient('client.xAutoClaimJustId', async client => { await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true @@ -27,5 +27,5 @@ describe('XAUTOCLAIM JUSTID', () => { messages: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XAUTOCLAIM_JUSTID.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts similarity index 100% rename from lib/commands/XAUTOCLAIM_JUSTID.ts rename to packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts diff --git a/lib/commands/XCLAIM.spec.ts b/packages/client/lib/commands/XCLAIM.spec.ts similarity index 94% rename from lib/commands/XCLAIM.spec.ts rename to packages/client/lib/commands/XCLAIM.spec.ts index ff4b445dcf3..141a62ab77a 100644 --- a/lib/commands/XCLAIM.spec.ts +++ b/packages/client/lib/commands/XCLAIM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XCLAIM'; describe('XCLAIM', () => { @@ -77,14 +77,14 @@ describe('XCLAIM', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xClaim', async client => { + testUtils.testWithClient('client.xClaim', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.deepEqual( await client.xClaim('key', 'group', 'consumer', 1, '0-0'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts similarity index 85% rename from lib/commands/XCLAIM.ts rename to packages/client/lib/commands/XCLAIM.ts index c5890a75797..c87d1551e86 100644 --- a/lib/commands/XCLAIM.ts +++ b/packages/client/lib/commands/XCLAIM.ts @@ -1,4 +1,4 @@ -import { pushVerdictArguments, transformReplyStreamMessages } from './generic-transformers'; +import { pushVerdictArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -43,4 +43,4 @@ export function transformArguments( return args; } -export const transformReply = transformReplyStreamMessages; +export { transformReplyStreamMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts similarity index 78% rename from lib/commands/XCLAIM_JUSTID.spec.ts rename to packages/client/lib/commands/XCLAIM_JUSTID.spec.ts index bb31f2c4532..619f876d53d 100644 --- a/lib/commands/XCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XCLAIM_JUSTID'; describe('XCLAIM JUSTID', () => { @@ -10,14 +10,14 @@ describe('XCLAIM JUSTID', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xClaimJustId', async client => { + testUtils.testWithClient('client.xClaimJustId', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.deepEqual( await client.xClaimJustId('key', 'group', 'consumer', 1, '0-0'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XCLAIM_JUSTID.ts b/packages/client/lib/commands/XCLAIM_JUSTID.ts similarity index 100% rename from lib/commands/XCLAIM_JUSTID.ts rename to packages/client/lib/commands/XCLAIM_JUSTID.ts diff --git a/lib/commands/XDEL.spec.ts b/packages/client/lib/commands/XDEL.spec.ts similarity index 81% rename from lib/commands/XDEL.spec.ts rename to packages/client/lib/commands/XDEL.spec.ts index 1a3015538f4..00f9e2f9c67 100644 --- a/lib/commands/XDEL.spec.ts +++ b/packages/client/lib/commands/XDEL.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XDEL'; describe('XDEL', () => { @@ -19,10 +19,10 @@ describe('XDEL', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xDel', async client => { + testUtils.testWithClient('client.xDel', async client => { assert.equal( await client.xDel('key', '0-0'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XDEL.ts b/packages/client/lib/commands/XDEL.ts similarity index 100% rename from lib/commands/XDEL.ts rename to packages/client/lib/commands/XDEL.ts diff --git a/lib/commands/XGROUP_CREATE.spec.ts b/packages/client/lib/commands/XGROUP_CREATE.spec.ts similarity index 84% rename from lib/commands/XGROUP_CREATE.spec.ts rename to packages/client/lib/commands/XGROUP_CREATE.spec.ts index fdbb796f107..57516e44cc8 100644 --- a/lib/commands/XGROUP_CREATE.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XGROUP_CREATE'; describe('XGROUP CREATE', () => { @@ -21,12 +21,12 @@ describe('XGROUP CREATE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xGroupCreate', async client => { + testUtils.testWithClient('client.xGroupCreate', async client => { assert.equal( await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XGROUP_CREATE.ts b/packages/client/lib/commands/XGROUP_CREATE.ts similarity index 100% rename from lib/commands/XGROUP_CREATE.ts rename to packages/client/lib/commands/XGROUP_CREATE.ts diff --git a/lib/commands/XGROUP_CREATECONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts similarity index 69% rename from lib/commands/XGROUP_CREATECONSUMER.spec.ts rename to packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts index 5b06188e302..62443345188 100644 --- a/lib/commands/XGROUP_CREATECONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XGROUP_CREATECONSUMER'; describe('XGROUP CREATECONSUMER', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,14 +12,14 @@ describe('XGROUP CREATECONSUMER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xGroupCreateConsumer', async client => { + testUtils.testWithClient('client.xGroupCreateConsumer', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.equal( await client.xGroupCreateConsumer('key', 'group', 'consumer'), true ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XGROUP_CREATECONSUMER.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts similarity index 62% rename from lib/commands/XGROUP_CREATECONSUMER.ts rename to packages/client/lib/commands/XGROUP_CREATECONSUMER.ts index 395688706e2..f1a57e6fc42 100644 --- a/lib/commands/XGROUP_CREATECONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 2; export function transformArguments(key: string, group: string, consumer: string): Array { return ['XGROUP', 'CREATECONSUMER', key, group, consumer]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/XGROUP_DELCONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts similarity index 77% rename from lib/commands/XGROUP_DELCONSUMER.spec.ts rename to packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts index c3cf3c2378a..d071aedf64f 100644 --- a/lib/commands/XGROUP_DELCONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XGROUP_DELCONSUMER'; describe('XGROUP DELCONSUMER', () => { @@ -10,14 +10,14 @@ describe('XGROUP DELCONSUMER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xGroupDelConsumer', async client => { + testUtils.testWithClient('client.xGroupDelConsumer', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.equal( await client.xGroupDelConsumer('key', 'group', 'consumer'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XGROUP_DELCONSUMER.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts similarity index 100% rename from lib/commands/XGROUP_DELCONSUMER.ts rename to packages/client/lib/commands/XGROUP_DELCONSUMER.ts diff --git a/lib/commands/XGROUP_DESTROY.spec.ts b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts similarity index 76% rename from lib/commands/XGROUP_DESTROY.spec.ts rename to packages/client/lib/commands/XGROUP_DESTROY.spec.ts index e991bc0d667..ea8e7b7be98 100644 --- a/lib/commands/XGROUP_DESTROY.spec.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XGROUP_DESTROY'; describe('XGROUP DESTROY', () => { @@ -10,14 +10,14 @@ describe('XGROUP DESTROY', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xGroupDestroy', async client => { + testUtils.testWithClient('client.xGroupDestroy', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.equal( await client.xGroupDestroy('key', 'group'), true ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XGROUP_DESTROY.ts b/packages/client/lib/commands/XGROUP_DESTROY.ts similarity index 58% rename from lib/commands/XGROUP_DESTROY.ts rename to packages/client/lib/commands/XGROUP_DESTROY.ts index 1fd25550c33..a4d67e5f4e5 100644 --- a/lib/commands/XGROUP_DESTROY.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.ts @@ -1,9 +1,7 @@ -import { transformReplyBoolean } from './generic-transformers'; - export const FIRST_KEY_INDEX = 2; export function transformArguments(key: string, group: string): Array { return ['XGROUP', 'DESTROY', key, group]; } -export const transformReply = transformReplyBoolean; +export { transformReplyBoolean as transformReply } from './generic-transformers'; diff --git a/lib/commands/XGROUP_SETID.spec.ts b/packages/client/lib/commands/XGROUP_SETID.spec.ts similarity index 77% rename from lib/commands/XGROUP_SETID.spec.ts rename to packages/client/lib/commands/XGROUP_SETID.spec.ts index 0fa10cdb0b7..8df51f5401d 100644 --- a/lib/commands/XGROUP_SETID.spec.ts +++ b/packages/client/lib/commands/XGROUP_SETID.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XGROUP_SETID'; describe('XGROUP SETID', () => { @@ -10,7 +10,7 @@ describe('XGROUP SETID', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xGroupSetId', async client => { + testUtils.testWithClient('client.xGroupSetId', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); @@ -19,5 +19,5 @@ describe('XGROUP SETID', () => { await client.xGroupSetId('key', 'group', '0'), 'OK' ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XGROUP_SETID.ts b/packages/client/lib/commands/XGROUP_SETID.ts similarity index 100% rename from lib/commands/XGROUP_SETID.ts rename to packages/client/lib/commands/XGROUP_SETID.ts diff --git a/lib/commands/XINFO_CONSUMERS.spec.ts b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts similarity index 86% rename from lib/commands/XINFO_CONSUMERS.spec.ts rename to packages/client/lib/commands/XINFO_CONSUMERS.spec.ts index 08ef17e51aa..87c82b34f29 100644 --- a/lib/commands/XINFO_CONSUMERS.spec.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './XINFO_CONSUMERS'; describe('XINFO CONSUMERS', () => { @@ -26,9 +26,9 @@ describe('XINFO CONSUMERS', () => { idle: 83841983 }] ); - }) + }); - itWithClient(TestRedisServers.OPEN, 'client.xInfoConsumers', async client => { + testUtils.testWithClient('client.xInfoConsumers', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); @@ -37,5 +37,5 @@ describe('XINFO CONSUMERS', () => { await client.xInfoConsumers('key', 'group'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XINFO_CONSUMERS.ts b/packages/client/lib/commands/XINFO_CONSUMERS.ts similarity index 100% rename from lib/commands/XINFO_CONSUMERS.ts rename to packages/client/lib/commands/XINFO_CONSUMERS.ts diff --git a/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts similarity index 89% rename from lib/commands/XINFO_GROUPS.spec.ts rename to packages/client/lib/commands/XINFO_GROUPS.spec.ts index 8fbd86ee3ee..dea8ac58d9c 100644 --- a/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './XINFO_GROUPS'; describe('XINFO GROUPS', () => { @@ -28,9 +28,9 @@ describe('XINFO GROUPS', () => { lastDeliveredId: '1588152498034-0' }] ); - }) + }); - itWithClient(TestRedisServers.OPEN, 'client.xInfoGroups', async client => { + testUtils.testWithClient('client.xInfoGroups', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); @@ -44,5 +44,5 @@ describe('XINFO GROUPS', () => { lastDeliveredId: '0-0' }] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XINFO_GROUPS.ts b/packages/client/lib/commands/XINFO_GROUPS.ts similarity index 100% rename from lib/commands/XINFO_GROUPS.ts rename to packages/client/lib/commands/XINFO_GROUPS.ts diff --git a/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts similarity index 93% rename from lib/commands/XINFO_STREAM.spec.ts rename to packages/client/lib/commands/XINFO_STREAM.spec.ts index ecab605e4e3..ca8d44f2875 100644 --- a/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './XINFO_STREAM'; describe('XINFO STREAM', () => { @@ -51,7 +51,7 @@ describe('XINFO STREAM', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xInfoStream', async client => { + testUtils.testWithClient('client.xInfoStream', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); @@ -68,5 +68,5 @@ describe('XINFO STREAM', () => { lastEntry: null } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts similarity index 100% rename from lib/commands/XINFO_STREAM.ts rename to packages/client/lib/commands/XINFO_STREAM.ts diff --git a/lib/commands/XLEN.spec.ts b/packages/client/lib/commands/XLEN.spec.ts similarity index 70% rename from lib/commands/XLEN.spec.ts rename to packages/client/lib/commands/XLEN.spec.ts index c4f62dbc4f2..178024ba89e 100644 --- a/lib/commands/XLEN.spec.ts +++ b/packages/client/lib/commands/XLEN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XLEN'; describe('XLEN', () => { @@ -10,10 +10,10 @@ describe('XLEN', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.xLen', async client => { + testUtils.testWithClient('client.xLen', async client => { assert.equal( await client.xLen('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XLEN.ts b/packages/client/lib/commands/XLEN.ts similarity index 100% rename from lib/commands/XLEN.ts rename to packages/client/lib/commands/XLEN.ts diff --git a/lib/commands/XPENDING.spec.ts b/packages/client/lib/commands/XPENDING.spec.ts similarity index 82% rename from lib/commands/XPENDING.spec.ts rename to packages/client/lib/commands/XPENDING.spec.ts index 31ffeeb4230..7eb12b40efe 100644 --- a/lib/commands/XPENDING.spec.ts +++ b/packages/client/lib/commands/XPENDING.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XPENDING'; describe('XPENDING', () => { @@ -12,7 +12,7 @@ describe('XPENDING', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xPending', async client => { + testUtils.testWithClient('client.xPending', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); @@ -26,5 +26,5 @@ describe('XPENDING', () => { consumers: null } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XPENDING.ts b/packages/client/lib/commands/XPENDING.ts similarity index 100% rename from lib/commands/XPENDING.ts rename to packages/client/lib/commands/XPENDING.ts diff --git a/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts similarity index 90% rename from lib/commands/XPENDING_RANGE.spec.ts rename to packages/client/lib/commands/XPENDING_RANGE.spec.ts index 76a582d3db5..0b57c704bb0 100644 --- a/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XPENDING_RANGE'; describe('XPENDING RANGE', () => { @@ -10,7 +10,7 @@ describe('XPENDING RANGE', () => { ['XPENDING', 'key', 'group', '-', '+', '1'] ); }); - + it('with IDLE', () => { assert.deepEqual( transformArguments('key', 'group', '-', '+', 1, { @@ -40,14 +40,14 @@ describe('XPENDING RANGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xPendingRange', async client => { + testUtils.testWithClient('client.xPendingRange', async client => { await client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }); - + assert.deepEqual( await client.xPendingRange('key', 'group', '-', '+', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts similarity index 81% rename from lib/commands/XPENDING_RANGE.ts rename to packages/client/lib/commands/XPENDING_RANGE.ts index c9e8d898e86..d0b45f0fabb 100644 --- a/lib/commands/XPENDING_RANGE.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.ts @@ -1,5 +1,3 @@ -import { transformReplyStreamMessages } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export const IS_READ_ONLY = true; @@ -24,7 +22,7 @@ export function transformArguments( } args.push(start, end, count.toString()); - + if (options?.consumer) { args.push(options.consumer); } @@ -32,4 +30,4 @@ export function transformArguments( return args; } -export const transformReply = transformReplyStreamMessages; +export { transformReplyStreamMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts similarity index 82% rename from lib/commands/XRANGE.spec.ts rename to packages/client/lib/commands/XRANGE.spec.ts index 55efa9d7729..01c713e9595 100644 --- a/lib/commands/XRANGE.spec.ts +++ b/packages/client/lib/commands/XRANGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XRANGE'; describe('XRANGE', () => { @@ -10,7 +10,7 @@ describe('XRANGE', () => { ['XRANGE', 'key', '-', '+'] ); }); - + it('with COUNT', () => { assert.deepEqual( transformArguments('key', '-', '+', { @@ -21,10 +21,10 @@ describe('XRANGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xRange', async client => { + testUtils.testWithClient('client.xRange', async client => { assert.deepEqual( await client.xRange('key', '+', '-'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XRANGE.ts b/packages/client/lib/commands/XRANGE.ts similarity index 74% rename from lib/commands/XRANGE.ts rename to packages/client/lib/commands/XRANGE.ts index 2902d0743db..b357266c950 100644 --- a/lib/commands/XRANGE.ts +++ b/packages/client/lib/commands/XRANGE.ts @@ -1,5 +1,3 @@ -import { transformReplyStreamMessages } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export const IS_READ_ONLY = true; @@ -18,4 +16,4 @@ export function transformArguments(key: string, start: string, end: string, opti return args; } -export const transformReply = transformReplyStreamMessages; +export { transformReplyStreamMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XREAD.spec.ts b/packages/client/lib/commands/XREAD.spec.ts similarity index 90% rename from lib/commands/XREAD.spec.ts rename to packages/client/lib/commands/XREAD.spec.ts index 501571bfbeb..b607f53532e 100644 --- a/lib/commands/XREAD.spec.ts +++ b/packages/client/lib/commands/XREAD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { FIRST_KEY_INDEX, transformArguments } from './XREAD'; describe('XREAD', () => { @@ -81,7 +81,7 @@ describe('XREAD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xRead', async client => { + testUtils.testWithClient('client.xRead', async client => { assert.equal( await client.xRead({ key: 'key', @@ -89,9 +89,9 @@ describe('XREAD', () => { }), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'cluster.xRead', async cluster => { + testUtils.testWithCluster('cluster.xRead', async cluster => { assert.equal( await cluster.xRead({ key: 'key', @@ -99,5 +99,5 @@ describe('XREAD', () => { }), null ); - }); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/XREAD.ts b/packages/client/lib/commands/XREAD.ts similarity index 88% rename from lib/commands/XREAD.ts rename to packages/client/lib/commands/XREAD.ts index 1f4932837a2..00d8aa959ec 100644 --- a/lib/commands/XREAD.ts +++ b/packages/client/lib/commands/XREAD.ts @@ -1,5 +1,3 @@ -import { transformReplyStreamsMessages } from './generic-transformers'; - export const FIRST_KEY_INDEX = (streams: Array | XReadStream): string => { return Array.isArray(streams) ? streams[0].key : streams.key; }; @@ -40,4 +38,4 @@ export function transformArguments(streams: Array | XReadStream, op return args; } -export const transformReply = transformReplyStreamsMessages; +export { transformReplyStreamsMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XREADGROUP.spec.ts b/packages/client/lib/commands/XREADGROUP.spec.ts similarity index 87% rename from lib/commands/XREADGROUP.spec.ts rename to packages/client/lib/commands/XREADGROUP.spec.ts index 8cb3147bfe7..fa196d504ad 100644 --- a/lib/commands/XREADGROUP.spec.ts +++ b/packages/client/lib/commands/XREADGROUP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, itWithCluster, TestRedisClusters } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { FIRST_KEY_INDEX, transformArguments } from './XREADGROUP'; describe('XREADGROUP', () => { @@ -94,36 +94,22 @@ describe('XREADGROUP', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'null', async client => { - const [, readGroupReply] = await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xReadGroup('group', 'consumer', { - key: 'key', - id: '>' - }) - ]); - - assert.equal(readGroupReply, null); - }); - - describe('cluster.xReadGroup', () => { - itWithCluster(TestRedisClusters.OPEN, 'null', async cluster => { + describe('client.xReadGroup', () => { + testUtils.testWithClient('null', async client => { const [, readGroupReply] = await Promise.all([ - cluster.xGroupCreate('key', 'group', '$', { + client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), - cluster.xReadGroup('group', 'consumer', { + client.xReadGroup('group', 'consumer', { key: 'key', id: '>' }) ]); assert.equal(readGroupReply, null); - }); + }, GLOBAL.SERVERS.OPEN); - itWithCluster(TestRedisClusters.OPEN, 'with a message', async client => { + testUtils.testWithClient('with a message', async client => { const [, id, readGroupReply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true @@ -148,6 +134,20 @@ describe('XREADGROUP', () => { }) }] }]); - }); + }, GLOBAL.SERVERS.OPEN); }); + + testUtils.testWithCluster('cluster.xReadGroup', async cluster => { + const [, readGroupReply] = await Promise.all([ + cluster.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + cluster.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }) + ]); + + assert.equal(readGroupReply, null); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/lib/commands/XREADGROUP.ts b/packages/client/lib/commands/XREADGROUP.ts similarity index 90% rename from lib/commands/XREADGROUP.ts rename to packages/client/lib/commands/XREADGROUP.ts index b01385e7c2f..6d329d377ff 100644 --- a/lib/commands/XREADGROUP.ts +++ b/packages/client/lib/commands/XREADGROUP.ts @@ -1,5 +1,3 @@ -import { transformReplyStreamsMessages } from './generic-transformers'; - export interface XReadGroupStream { key: string; id: string; @@ -54,4 +52,4 @@ export function transformArguments( return args; } -export const transformReply = transformReplyStreamsMessages; +export { transformReplyStreamsMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts similarity index 82% rename from lib/commands/XREVRANGE.spec.ts rename to packages/client/lib/commands/XREVRANGE.spec.ts index ba009cc2bbe..fd6e1a3adfe 100644 --- a/lib/commands/XREVRANGE.spec.ts +++ b/packages/client/lib/commands/XREVRANGE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XREVRANGE'; describe('XREVRANGE', () => { @@ -10,7 +10,7 @@ describe('XREVRANGE', () => { ['XREVRANGE', 'key', '-', '+'] ); }); - + it('with COUNT', () => { assert.deepEqual( transformArguments('key', '-', '+', { @@ -21,10 +21,10 @@ describe('XREVRANGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xRevRange', async client => { + testUtils.testWithClient('client.xRevRange', async client => { assert.deepEqual( await client.xRevRange('key', '+', '-'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XREVRANGE.ts b/packages/client/lib/commands/XREVRANGE.ts similarity index 71% rename from lib/commands/XREVRANGE.ts rename to packages/client/lib/commands/XREVRANGE.ts index a1fbbbc128a..db48856cdcc 100644 --- a/lib/commands/XREVRANGE.ts +++ b/packages/client/lib/commands/XREVRANGE.ts @@ -1,5 +1,3 @@ -import { transformReplyStreamMessages } from './generic-transformers'; - interface XRangeRevOptions { COUNT?: number; } @@ -14,4 +12,4 @@ export function transformArguments(key: string, start: string, end: string, opti return args; } -export const transformReply = transformReplyStreamMessages; +export { transformReplyStreamMessages as transformReply } from './generic-transformers'; diff --git a/lib/commands/XTRIM.spec.ts b/packages/client/lib/commands/XTRIM.spec.ts similarity index 90% rename from lib/commands/XTRIM.spec.ts rename to packages/client/lib/commands/XTRIM.spec.ts index 0b48fd6a2d6..a8f8078eb28 100644 --- a/lib/commands/XTRIM.spec.ts +++ b/packages/client/lib/commands/XTRIM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './XTRIM'; describe('XTRIM', () => { @@ -40,10 +40,10 @@ describe('XTRIM', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.xTrim', async client => { + testUtils.testWithClient('client.xTrim', async client => { assert.equal( await client.xTrim('key', 'MAXLEN', 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/XTRIM.ts b/packages/client/lib/commands/XTRIM.ts similarity index 100% rename from lib/commands/XTRIM.ts rename to packages/client/lib/commands/XTRIM.ts diff --git a/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts similarity index 95% rename from lib/commands/ZADD.spec.ts rename to packages/client/lib/commands/ZADD.spec.ts index 7c017e45410..4f497bdca90 100644 --- a/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZADD'; describe('ZADD', () => { @@ -115,7 +115,7 @@ describe('ZADD', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zAdd', async client => { + testUtils.testWithClient('client.zAdd', async client => { assert.equal( await client.zAdd('key', { value: '1', @@ -123,5 +123,5 @@ describe('ZADD', () => { }), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts similarity index 83% rename from lib/commands/ZADD.ts rename to packages/client/lib/commands/ZADD.ts index 0e43ecaf508..69f01c8d534 100644 --- a/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,4 +1,4 @@ -import { transformArgumentNumberInfinity, transformReplyNumberInfinity, ZMember } from './generic-transformers'; +import { transformArgumentNumberInfinity, ZMember } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -56,11 +56,11 @@ export function transformArguments(key: string, members: ZMember | Array { @@ -10,10 +10,10 @@ describe('ZCARD', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zCard', async client => { + testUtils.testWithClient('client.zCard', async client => { assert.equal( await client.zCard('key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZCARD.ts b/packages/client/lib/commands/ZCARD.ts similarity index 100% rename from lib/commands/ZCARD.ts rename to packages/client/lib/commands/ZCARD.ts diff --git a/lib/commands/ZCOUNT.spec.ts b/packages/client/lib/commands/ZCOUNT.spec.ts similarity index 72% rename from lib/commands/ZCOUNT.spec.ts rename to packages/client/lib/commands/ZCOUNT.spec.ts index e461241ce1c..e185ed3cd45 100644 --- a/lib/commands/ZCOUNT.spec.ts +++ b/packages/client/lib/commands/ZCOUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZCOUNT'; describe('ZCOUNT', () => { @@ -10,10 +10,10 @@ describe('ZCOUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zCount', async client => { + testUtils.testWithClient('client.zCount', async client => { assert.equal( await client.zCount('key', 0, 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ZCOUNT.ts b/packages/client/lib/commands/ZCOUNT.ts new file mode 100644 index 00000000000..83a0710fa11 --- /dev/null +++ b/packages/client/lib/commands/ZCOUNT.ts @@ -0,0 +1,16 @@ +import { transformArgumentStringNumberInfinity } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: string, min: string | number, max: string | number): Array { + return [ + 'ZCOUNT', + key, + transformArgumentStringNumberInfinity(min), + transformArgumentStringNumberInfinity(max) + ]; +} + +export declare function transformReply(): number; diff --git a/lib/commands/ZDIFF.spec.ts b/packages/client/lib/commands/ZDIFF.spec.ts similarity index 72% rename from lib/commands/ZDIFF.spec.ts rename to packages/client/lib/commands/ZDIFF.spec.ts index f45b2af7edc..8bb1a101f53 100644 --- a/lib/commands/ZDIFF.spec.ts +++ b/packages/client/lib/commands/ZDIFF.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZDIFF'; describe('ZDIFF', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('string', () => { @@ -21,10 +21,10 @@ describe('ZDIFF', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zDiff', async client => { + testUtils.testWithClient('client.zDiff', async client => { assert.deepEqual( await client.zDiff('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZDIFF.ts b/packages/client/lib/commands/ZDIFF.ts similarity index 100% rename from lib/commands/ZDIFF.ts rename to packages/client/lib/commands/ZDIFF.ts diff --git a/lib/commands/ZDIFFSTORE.spec.ts b/packages/client/lib/commands/ZDIFFSTORE.spec.ts similarity index 75% rename from lib/commands/ZDIFFSTORE.spec.ts rename to packages/client/lib/commands/ZDIFFSTORE.spec.ts index 5fbeebaf502..c63902b2666 100644 --- a/lib/commands/ZDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/ZDIFFSTORE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZDIFFSTORE'; describe('ZDIFFSTORE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('string', () => { @@ -21,10 +21,10 @@ describe('ZDIFFSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zDiffStore', async client => { + testUtils.testWithClient('client.zDiffStore', async client => { assert.equal( await client.zDiffStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZDIFFSTORE.ts b/packages/client/lib/commands/ZDIFFSTORE.ts similarity index 100% rename from lib/commands/ZDIFFSTORE.ts rename to packages/client/lib/commands/ZDIFFSTORE.ts diff --git a/lib/commands/ZDIFF_WITHSCORES.spec.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts similarity index 73% rename from lib/commands/ZDIFF_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts index 99c23108292..3b9cb725aaa 100644 --- a/lib/commands/ZDIFF_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZDIFF_WITHSCORES'; describe('ZDIFF WITHSCORES', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('string', () => { @@ -21,10 +21,10 @@ describe('ZDIFF WITHSCORES', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zDiffWithScores', async client => { + testUtils.testWithClient('client.zDiffWithScores', async client => { assert.deepEqual( await client.zDiffWithScores('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZDIFF_WITHSCORES.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts similarity index 72% rename from lib/commands/ZDIFF_WITHSCORES.ts rename to packages/client/lib/commands/ZDIFF_WITHSCORES.ts index 49707563546..578927331be 100644 --- a/lib/commands/ZDIFF_WITHSCORES.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts @@ -1,5 +1,4 @@ import { RedisCommandArguments } from '.'; -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZDiffArguments } from './ZDIFF'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZDIFF'; @@ -11,4 +10,4 @@ export function transformArguments(...args: Parameters { @@ -10,10 +10,10 @@ describe('ZINCRBY', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zIncrBy', async client => { + testUtils.testWithClient('client.zIncrBy', async client => { assert.equal( await client.zIncrBy('destination', 1, 'member'), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts similarity index 61% rename from lib/commands/ZINCRBY.ts rename to packages/client/lib/commands/ZINCRBY.ts index 39f32c165f7..1edf4beff4b 100644 --- a/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -1,4 +1,4 @@ -import { transformArgumentNumberInfinity, transformReplyNumberInfinity } from './generic-transformers'; +import { transformArgumentNumberInfinity } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -11,4 +11,4 @@ export function transformArguments(key: string, increment: number, member: strin ]; } -export const transformReply = transformReplyNumberInfinity; +export { transformReplyNumberInfinity as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZINTER.spec.ts b/packages/client/lib/commands/ZINTER.spec.ts similarity index 85% rename from lib/commands/ZINTER.spec.ts rename to packages/client/lib/commands/ZINTER.spec.ts index 998c46fd3e0..4d2d86c8869 100644 --- a/lib/commands/ZINTER.spec.ts +++ b/packages/client/lib/commands/ZINTER.spec.ts @@ -1,10 +1,10 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZINTER'; describe('ZINTER', () => { - describeHandleMinimumRedisVersion([6, 2]); - + testUtils.isVersionGreaterThanHook([6, 2]); + describe('transformArguments', () => { it('key (string)', () => { assert.deepEqual( @@ -49,10 +49,10 @@ describe('ZINTER', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zInter', async client => { + testUtils.testWithClient('client.zInter', async client => { assert.deepEqual( await client.zInter('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZINTER.ts b/packages/client/lib/commands/ZINTER.ts similarity index 100% rename from lib/commands/ZINTER.ts rename to packages/client/lib/commands/ZINTER.ts diff --git a/lib/commands/ZINTERSTORE.spec.ts b/packages/client/lib/commands/ZINTERSTORE.spec.ts similarity index 91% rename from lib/commands/ZINTERSTORE.spec.ts rename to packages/client/lib/commands/ZINTERSTORE.spec.ts index fca03157cb2..224961f0786 100644 --- a/lib/commands/ZINTERSTORE.spec.ts +++ b/packages/client/lib/commands/ZINTERSTORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZINTERSTORE'; describe('ZINTERSTORE', () => { @@ -47,10 +47,10 @@ describe('ZINTERSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zInterStore', async client => { + testUtils.testWithClient('client.zInterStore', async client => { assert.equal( await client.zInterStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZINTERSTORE.ts b/packages/client/lib/commands/ZINTERSTORE.ts similarity index 100% rename from lib/commands/ZINTERSTORE.ts rename to packages/client/lib/commands/ZINTERSTORE.ts diff --git a/lib/commands/ZINTER_WITHSCORES.spec.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts similarity index 86% rename from lib/commands/ZINTER_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts index f66787e3def..0eaeb26a244 100644 --- a/lib/commands/ZINTER_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZINTER_WITHSCORES'; describe('ZINTER WITHSCORES', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('key (string)', () => { @@ -49,10 +49,10 @@ describe('ZINTER WITHSCORES', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zInterWithScores', async client => { + testUtils.testWithClient('client.zInterWithScores', async client => { assert.deepEqual( await client.zInterWithScores('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZINTER_WITHSCORES.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.ts similarity index 73% rename from lib/commands/ZINTER_WITHSCORES.ts rename to packages/client/lib/commands/ZINTER_WITHSCORES.ts index f75a506de73..cfe022f9e94 100644 --- a/lib/commands/ZINTER_WITHSCORES.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.ts @@ -1,5 +1,4 @@ import { RedisCommandArguments } from '.'; -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZInterArguments } from './ZINTER'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZINTER'; @@ -11,4 +10,4 @@ export function transformArguments(...args: Parameters { @@ -10,10 +10,10 @@ describe('ZLEXCOUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zLexCount', async client => { + testUtils.testWithClient('client.zLexCount', async client => { assert.equal( await client.zLexCount('key', '[a', '[b'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZLEXCOUNT.ts b/packages/client/lib/commands/ZLEXCOUNT.ts similarity index 100% rename from lib/commands/ZLEXCOUNT.ts rename to packages/client/lib/commands/ZLEXCOUNT.ts diff --git a/lib/commands/ZMSCORE.spec.ts b/packages/client/lib/commands/ZMSCORE.spec.ts similarity index 73% rename from lib/commands/ZMSCORE.spec.ts rename to packages/client/lib/commands/ZMSCORE.spec.ts index 3cf3845392d..228c8e9d6f6 100644 --- a/lib/commands/ZMSCORE.spec.ts +++ b/packages/client/lib/commands/ZMSCORE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZMSCORE'; describe('ZMSCORE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('string', () => { @@ -21,10 +21,10 @@ describe('ZMSCORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zmScore', async client => { + testUtils.testWithClient('client.zmScore', async client => { assert.deepEqual( await client.zmScore('key', 'member'), [null] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts similarity index 62% rename from lib/commands/ZMSCORE.ts rename to packages/client/lib/commands/ZMSCORE.ts index 2790f712316..a6dd8e45e4a 100644 --- a/lib/commands/ZMSCORE.ts +++ b/packages/client/lib/commands/ZMSCORE.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments, transformReplyNumberInfinityNullArray } from './generic-transformers'; +import { pushVerdictArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,4 +9,4 @@ export function transformArguments(key: string, member: string | Array): return pushVerdictArguments(['ZMSCORE', key], member); } -export const transformReply = transformReplyNumberInfinityNullArray; +export { transformReplyNumberInfinityNullArray as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZPOPMAX.spec.ts b/packages/client/lib/commands/ZPOPMAX.spec.ts similarity index 79% rename from lib/commands/ZPOPMAX.spec.ts rename to packages/client/lib/commands/ZPOPMAX.spec.ts index ceab3cad1d0..18fba23a3e9 100644 --- a/lib/commands/ZPOPMAX.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './ZPOPMAX'; describe('ZPOPMAX', () => { @@ -21,14 +21,14 @@ describe('ZPOPMAX', () => { }); describe('client.zPopMax', () => { - itWithClient(TestRedisServers.OPEN, 'null', async client => { + testUtils.testWithClient('null', async client => { assert.equal( await client.zPopMax('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'member', async client => { + testUtils.testWithClient('member', async client => { const member = { score: 1, value: 'value' }, [, zPopMaxReply] = await Promise.all([ client.zAdd('key', member), @@ -36,6 +36,6 @@ describe('ZPOPMAX', () => { ]); assert.deepEqual(zPopMaxReply, member); - }); + }, GLOBAL.SERVERS.OPEN); }); }); diff --git a/lib/commands/ZPOPMAX.ts b/packages/client/lib/commands/ZPOPMAX.ts similarity index 100% rename from lib/commands/ZPOPMAX.ts rename to packages/client/lib/commands/ZPOPMAX.ts diff --git a/lib/commands/ZPOPMAX_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts similarity index 72% rename from lib/commands/ZPOPMAX_COUNT.spec.ts rename to packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts index c0e71977ee8..b282d0d3199 100644 --- a/lib/commands/ZPOPMAX_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZPOPMAX_COUNT'; describe('ZPOPMAX COUNT', () => { @@ -10,10 +10,10 @@ describe('ZPOPMAX COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zPopMaxCount', async client => { + testUtils.testWithClient('client.zPopMaxCount', async client => { assert.deepEqual( await client.zPopMaxCount('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZPOPMAX_COUNT.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.ts similarity index 67% rename from lib/commands/ZPOPMAX_COUNT.ts rename to packages/client/lib/commands/ZPOPMAX_COUNT.ts index abfa8494ec4..abef32cca56 100644 --- a/lib/commands/ZPOPMAX_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.ts @@ -1,4 +1,3 @@ -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZPopMaxArguments } from './ZPOPMAX'; export { FIRST_KEY_INDEX } from './ZPOPMAX'; @@ -10,4 +9,4 @@ export function transformArguments(key: string, count: number): Array { ]; } -export const transformReply = transformReplySortedSetWithScores; +export { transformReplySortedSetWithScores as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZPOPMIN.spec.ts b/packages/client/lib/commands/ZPOPMIN.spec.ts similarity index 79% rename from lib/commands/ZPOPMIN.spec.ts rename to packages/client/lib/commands/ZPOPMIN.spec.ts index c69ca7c27f7..624b7054404 100644 --- a/lib/commands/ZPOPMIN.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './ZPOPMIN'; describe('ZPOPMIN', () => { @@ -21,14 +21,14 @@ describe('ZPOPMIN', () => { }); describe('client.zPopMin', () => { - itWithClient(TestRedisServers.OPEN, 'null', async client => { + testUtils.testWithClient('null', async client => { assert.equal( await client.zPopMin('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); - itWithClient(TestRedisServers.OPEN, 'member', async client => { + testUtils.testWithClient('member', async client => { const member = { score: 1, value: 'value' }, [, zPopMinReply] = await Promise.all([ client.zAdd('key', member), @@ -36,6 +36,6 @@ describe('ZPOPMIN', () => { ]); assert.deepEqual(zPopMinReply, member); - }); + }, GLOBAL.SERVERS.OPEN); }); }); diff --git a/lib/commands/ZPOPMIN.ts b/packages/client/lib/commands/ZPOPMIN.ts similarity index 100% rename from lib/commands/ZPOPMIN.ts rename to packages/client/lib/commands/ZPOPMIN.ts diff --git a/lib/commands/ZPOPMIN_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts similarity index 72% rename from lib/commands/ZPOPMIN_COUNT.spec.ts rename to packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts index 1c2745a0fdf..6d40002ab72 100644 --- a/lib/commands/ZPOPMIN_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZPOPMIN_COUNT'; describe('ZPOPMIN COUNT', () => { @@ -10,10 +10,10 @@ describe('ZPOPMIN COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zPopMinCount', async client => { + testUtils.testWithClient('client.zPopMinCount', async client => { assert.deepEqual( await client.zPopMinCount('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZPOPMIN_COUNT.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.ts similarity index 67% rename from lib/commands/ZPOPMIN_COUNT.ts rename to packages/client/lib/commands/ZPOPMIN_COUNT.ts index e313b32dc8a..7d290ebfe37 100644 --- a/lib/commands/ZPOPMIN_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.ts @@ -1,4 +1,3 @@ -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZPopMinArguments } from './ZPOPMIN'; export { FIRST_KEY_INDEX } from './ZPOPMIN'; @@ -10,4 +9,4 @@ export function transformArguments(key: string, count: number): Array { ]; } -export const transformReply = transformReplySortedSetWithScores; +export { transformReplySortedSetWithScores as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZRANDMEMBER.spec.ts b/packages/client/lib/commands/ZRANDMEMBER.spec.ts similarity index 62% rename from lib/commands/ZRANDMEMBER.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER.spec.ts index da31641a18c..c57d26f830e 100644 --- a/lib/commands/ZRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANDMEMBER'; describe('ZRANDMEMBER', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('ZRANDMEMBER', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRandMember', async client => { + testUtils.testWithClient('client.zRandMember', async client => { assert.equal( await client.zRandMember('key'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANDMEMBER.ts b/packages/client/lib/commands/ZRANDMEMBER.ts similarity index 100% rename from lib/commands/ZRANDMEMBER.ts rename to packages/client/lib/commands/ZRANDMEMBER.ts diff --git a/lib/commands/ZRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts similarity index 63% rename from lib/commands/ZRANDMEMBER_COUNT.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts index 4c873c82d90..10db0727b23 100644 --- a/lib/commands/ZRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANDMEMBER_COUNT'; describe('ZRANDMEMBER COUNT', () => { - describeHandleMinimumRedisVersion([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('ZRANDMEMBER COUNT', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRandMemberCount', async client => { + testUtils.testWithClient('client.zRandMemberCount', async client => { assert.deepEqual( await client.zRandMemberCount('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANDMEMBER_COUNT.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT.ts similarity index 100% rename from lib/commands/ZRANDMEMBER_COUNT.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT.ts diff --git a/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts similarity index 64% rename from lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts index 55624361fb6..5b5ec1f500f 100644 --- a/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANDMEMBER_COUNT_WITHSCORES'; describe('ZRANDMEMBER COUNT WITHSCORES', () => { - describeHandleMinimumRedisVersion([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); it('transformArguments', () => { assert.deepEqual( @@ -12,10 +12,10 @@ describe('ZRANDMEMBER COUNT WITHSCORES', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRandMemberCountWithScores', async client => { + testUtils.testWithClient('client.zRandMemberCountWithScores', async client => { assert.deepEqual( await client.zRandMemberCountWithScores('key', 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts similarity index 73% rename from lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts index 6d79f41c955..8f49b326ad1 100644 --- a/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts @@ -1,4 +1,3 @@ -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZRandMemberCountArguments } from './ZRANDMEMBER_COUNT'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANDMEMBER_COUNT'; @@ -10,4 +9,4 @@ export function transformArguments(...args: Parameters { @@ -11,13 +11,6 @@ describe('ZRANGE', () => { ); }); - it('using strings', () => { - assert.deepEqual( - transformArguments('src', '0', '1'), - ['ZRANGE', 'src', '0', '1'] - ); - }); - it('with BYSCORE', () => { assert.deepEqual( transformArguments('src', 0, 1, { @@ -72,10 +65,10 @@ describe('ZRANGE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRange', async client => { + testUtils.testWithClient('client.zRange', async client => { assert.deepEqual( await client.zRange('src', 0, 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGE.ts b/packages/client/lib/commands/ZRANGE.ts similarity index 78% rename from lib/commands/ZRANGE.ts rename to packages/client/lib/commands/ZRANGE.ts index 391c5ca893e..3d30e0f8dd2 100644 --- a/lib/commands/ZRANGE.ts +++ b/packages/client/lib/commands/ZRANGE.ts @@ -1,4 +1,4 @@ -import { transformArgumentNumberInfinity } from './generic-transformers'; +import { transformArgumentStringNumberInfinity } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -17,8 +17,8 @@ export function transformArguments(key: string, min: string | number, max: strin const args = [ 'ZRANGE', key, - typeof min === 'string' ? min : transformArgumentNumberInfinity(min), - typeof max === 'string' ? max : transformArgumentNumberInfinity(max) + transformArgumentStringNumberInfinity(min), + transformArgumentStringNumberInfinity(max) ]; switch (options?.BY) { diff --git a/lib/commands/ZRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts similarity index 84% rename from lib/commands/ZRANGEBYLEX.spec.ts rename to packages/client/lib/commands/ZRANGEBYLEX.spec.ts index 7f687509548..fe7b7d5a16e 100644 --- a/lib/commands/ZRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANGEBYLEX'; describe('ZRANGEBYLEX', () => { @@ -24,10 +24,10 @@ describe('ZRANGEBYLEX', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRangeByLex', async client => { + testUtils.testWithClient('client.zRangeByLex', async client => { assert.deepEqual( await client.zRangeByLex('src', '-', '+'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGEBYLEX.ts b/packages/client/lib/commands/ZRANGEBYLEX.ts similarity index 74% rename from lib/commands/ZRANGEBYLEX.ts rename to packages/client/lib/commands/ZRANGEBYLEX.ts index 7e2e7613b00..214d796da0a 100644 --- a/lib/commands/ZRANGEBYLEX.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { transformArgumentNumberInfinity } from './generic-transformers'; +import { transformArgumentStringNumberInfinity } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -21,8 +21,8 @@ export function transformArguments( const args = [ 'ZRANGEBYLEX', key, - typeof min === 'string' ? min : transformArgumentNumberInfinity(min), - typeof max === 'string' ? max : transformArgumentNumberInfinity(max) + transformArgumentStringNumberInfinity(min), + transformArgumentStringNumberInfinity(max) ]; if (options?.LIMIT) { diff --git a/lib/commands/ZRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts similarity index 84% rename from lib/commands/ZRANGEBYSCORE.spec.ts rename to packages/client/lib/commands/ZRANGEBYSCORE.spec.ts index 0419b232563..a3484326306 100644 --- a/lib/commands/ZRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANGEBYSCORE'; describe('ZRANGEBYSCORE', () => { @@ -24,10 +24,10 @@ describe('ZRANGEBYSCORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRangeByScore', async client => { + testUtils.testWithClient('client.zRangeByScore', async client => { assert.deepEqual( await client.zRangeByScore('src', 0, 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGEBYSCORE.ts b/packages/client/lib/commands/ZRANGEBYSCORE.ts similarity index 74% rename from lib/commands/ZRANGEBYSCORE.ts rename to packages/client/lib/commands/ZRANGEBYSCORE.ts index 48dd8a415c6..f6097fad581 100644 --- a/lib/commands/ZRANGEBYSCORE.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '.'; -import { transformArgumentNumberInfinity } from './generic-transformers'; +import { transformArgumentStringNumberInfinity } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -21,8 +21,8 @@ export function transformArguments( const args = [ 'ZRANGEBYSCORE', key, - typeof min === 'string' ? min : transformArgumentNumberInfinity(min), - typeof max === 'string' ? max : transformArgumentNumberInfinity(max) + transformArgumentStringNumberInfinity(min), + transformArgumentStringNumberInfinity(max) ]; if (options?.LIMIT) { diff --git a/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts similarity index 84% rename from lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts index 84d1aeb0aad..3552d3e2535 100644 --- a/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANGEBYSCORE_WITHSCORES'; describe('ZRANGEBYSCORE WITHSCORES', () => { @@ -24,10 +24,10 @@ describe('ZRANGEBYSCORE WITHSCORES', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRangeByScoreWithScores', async client => { + testUtils.testWithClient('client.zRangeByScoreWithScores', async client => { assert.deepEqual( await client.zRangeByScoreWithScores('src', 0, 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts similarity index 78% rename from lib/commands/ZRANGEBYSCORE_WITHSCORES.ts rename to packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts index f6f7f993cbc..6541662c855 100644 --- a/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts @@ -1,5 +1,4 @@ import { RedisCommandArguments } from '.'; -import { transformReplySortedSetWithScores } from './generic-transformers'; import { ZRangeByScoreOptions, transformArguments as transformZRangeByScoreArguments } from './ZRANGEBYSCORE'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGEBYSCORE'; @@ -16,4 +15,4 @@ export function transformArguments( ]; } -export const transformReply = transformReplySortedSetWithScores; +export { transformReplySortedSetWithScores as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZRANGESTORE.spec.ts b/packages/client/lib/commands/ZRANGESTORE.spec.ts similarity index 90% rename from lib/commands/ZRANGESTORE.spec.ts rename to packages/client/lib/commands/ZRANGESTORE.spec.ts index 54055656409..7af253e539f 100644 --- a/lib/commands/ZRANGESTORE.spec.ts +++ b/packages/client/lib/commands/ZRANGESTORE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './ZRANGESTORE'; describe('ZRANGESTORE', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('simple', () => { @@ -71,13 +71,14 @@ describe('ZRANGESTORE', () => { describe('transformReply', () => { it('should throw TypeError when reply is not a number', () => { assert.throws( + // eslint-disable-next-line @typescript-eslint/no-explicit-any () => (transformReply as any)([]), TypeError ); }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRangeStore', async client => { + testUtils.testWithClient('client.zRangeStore', async client => { await client.zAdd('src', { score: 0.5, value: 'value' @@ -87,5 +88,5 @@ describe('ZRANGESTORE', () => { await client.zRangeStore('dst', 'src', 0, 1), 1 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGESTORE.ts b/packages/client/lib/commands/ZRANGESTORE.ts similarity index 72% rename from lib/commands/ZRANGESTORE.ts rename to packages/client/lib/commands/ZRANGESTORE.ts index 6ad75661668..c76afe61029 100644 --- a/lib/commands/ZRANGESTORE.ts +++ b/packages/client/lib/commands/ZRANGESTORE.ts @@ -1,4 +1,4 @@ -import { transformArgumentNumberInfinity } from './generic-transformers'; +import { transformArgumentStringNumberInfinity } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -12,13 +12,19 @@ interface ZRangeStoreOptions { WITHSCORES?: true; } -export function transformArguments(dst: string, src: string, min: number, max: number, options?: ZRangeStoreOptions): Array { +export function transformArguments( + dst: string, + src: string, + min: string | number, + max: string | number, + options?: ZRangeStoreOptions +): Array { const args = [ 'ZRANGESTORE', dst, src, - transformArgumentNumberInfinity(min), - transformArgumentNumberInfinity(max) + transformArgumentStringNumberInfinity(min), + transformArgumentStringNumberInfinity(max) ]; switch (options?.BY) { diff --git a/lib/commands/ZRANGE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts similarity index 92% rename from lib/commands/ZRANGE_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts index 4c739b3d3b3..d9b07e19dda 100644 --- a/lib/commands/ZRANGE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZRANGE_WITHSCORES'; describe('ZRANGE WITHSCORES', () => { @@ -56,10 +56,10 @@ describe('ZRANGE WITHSCORES', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRangeWithScores', async client => { + testUtils.testWithClient('client.zRangeWithScores', async client => { assert.deepEqual( await client.zRangeWithScores('src', 0, 1), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANGE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts similarity index 70% rename from lib/commands/ZRANGE_WITHSCORES.ts rename to packages/client/lib/commands/ZRANGE_WITHSCORES.ts index 0f777132f27..63d71dfb681 100644 --- a/lib/commands/ZRANGE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts @@ -1,4 +1,3 @@ -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZRangeArguments } from './ZRANGE'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGE'; @@ -10,4 +9,4 @@ export function transformArguments(...args: Parameters { @@ -10,10 +10,10 @@ describe('ZRANK', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRank', async client => { + testUtils.testWithClient('client.zRank', async client => { assert.equal( await client.zRank('key', 'member'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZRANK.ts b/packages/client/lib/commands/ZRANK.ts similarity index 100% rename from lib/commands/ZRANK.ts rename to packages/client/lib/commands/ZRANK.ts diff --git a/lib/commands/ZREM.spec.ts b/packages/client/lib/commands/ZREM.spec.ts similarity index 81% rename from lib/commands/ZREM.spec.ts rename to packages/client/lib/commands/ZREM.spec.ts index d613832035d..3ac001708a0 100644 --- a/lib/commands/ZREM.spec.ts +++ b/packages/client/lib/commands/ZREM.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZREM'; describe('ZREM', () => { @@ -19,10 +19,10 @@ describe('ZREM', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zRem', async client => { + testUtils.testWithClient('client.zRem', async client => { assert.equal( await client.zRem('key', 'member'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZREM.ts b/packages/client/lib/commands/ZREM.ts similarity index 100% rename from lib/commands/ZREM.ts rename to packages/client/lib/commands/ZREM.ts diff --git a/lib/commands/ZREMRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts similarity index 73% rename from lib/commands/ZREMRANGEBYLEX.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts index 7aae059480c..b59c9e9f3b0 100644 --- a/lib/commands/ZREMRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZREMRANGEBYLEX'; describe('ZREMRANGEBYLEX', () => { @@ -10,10 +10,10 @@ describe('ZREMRANGEBYLEX', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRemRangeByLex', async client => { + testUtils.testWithClient('client.zRemRangeByLex', async client => { assert.equal( await client.zRemRangeByLex('key', '[a', '[b'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZREMRANGEBYLEX.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.ts similarity index 100% rename from lib/commands/ZREMRANGEBYLEX.ts rename to packages/client/lib/commands/ZREMRANGEBYLEX.ts diff --git a/lib/commands/ZREMRANGEBYRANK.spec.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts similarity index 72% rename from lib/commands/ZREMRANGEBYRANK.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts index 401b57c8e2a..c659dadb790 100644 --- a/lib/commands/ZREMRANGEBYRANK.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZREMRANGEBYRANK'; describe('ZREMRANGEBYRANK', () => { @@ -10,10 +10,10 @@ describe('ZREMRANGEBYRANK', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRemRangeByRank', async client => { + testUtils.testWithClient('client.zRemRangeByRank', async client => { assert.equal( await client.zRemRangeByRank('key', 0, 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZREMRANGEBYRANK.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.ts similarity index 100% rename from lib/commands/ZREMRANGEBYRANK.ts rename to packages/client/lib/commands/ZREMRANGEBYRANK.ts diff --git a/lib/commands/ZREMRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts similarity index 72% rename from lib/commands/ZREMRANGEBYSCORE.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts index 141392e772b..988fd7690c9 100644 --- a/lib/commands/ZREMRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZREMRANGEBYSCORE'; describe('ZREMRANGEBYSCORE', () => { @@ -10,10 +10,10 @@ describe('ZREMRANGEBYSCORE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRemRangeByScore', async client => { + testUtils.testWithClient('client.zRemRangeByScore', async client => { assert.equal( await client.zRemRangeByScore('key', 0, 1), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZREMRANGEBYSCORE.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.ts similarity index 100% rename from lib/commands/ZREMRANGEBYSCORE.ts rename to packages/client/lib/commands/ZREMRANGEBYSCORE.ts diff --git a/lib/commands/ZREVRANK.spec.ts b/packages/client/lib/commands/ZREVRANK.spec.ts similarity index 72% rename from lib/commands/ZREVRANK.spec.ts rename to packages/client/lib/commands/ZREVRANK.spec.ts index 727a61a35a6..d9fef0d70a4 100644 --- a/lib/commands/ZREVRANK.spec.ts +++ b/packages/client/lib/commands/ZREVRANK.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZREVRANK'; describe('ZREVRANK', () => { @@ -10,10 +10,10 @@ describe('ZREVRANK', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zRevRank', async client => { + testUtils.testWithClient('client.zRevRank', async client => { assert.equal( await client.zRevRank('key', 'member'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZREVRANK.ts b/packages/client/lib/commands/ZREVRANK.ts similarity index 100% rename from lib/commands/ZREVRANK.ts rename to packages/client/lib/commands/ZREVRANK.ts diff --git a/lib/commands/ZSCAN.spec.ts b/packages/client/lib/commands/ZSCAN.spec.ts similarity index 93% rename from lib/commands/ZSCAN.spec.ts rename to packages/client/lib/commands/ZSCAN.spec.ts index 3ff0c0a52b2..afa221a1ef3 100644 --- a/lib/commands/ZSCAN.spec.ts +++ b/packages/client/lib/commands/ZSCAN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './ZSCAN'; describe('ZSCAN', () => { @@ -65,7 +65,7 @@ describe('ZSCAN', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zScan', async client => { + testUtils.testWithClient('client.zScan', async client => { assert.deepEqual( await client.zScan('key', 0), { @@ -73,5 +73,5 @@ describe('ZSCAN', () => { members: [] } ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts similarity index 100% rename from lib/commands/ZSCAN.ts rename to packages/client/lib/commands/ZSCAN.ts diff --git a/lib/commands/ZSCORE.spec.ts b/packages/client/lib/commands/ZSCORE.spec.ts similarity index 72% rename from lib/commands/ZSCORE.spec.ts rename to packages/client/lib/commands/ZSCORE.spec.ts index d346a2e2c81..fe2a1c6a7c5 100644 --- a/lib/commands/ZSCORE.spec.ts +++ b/packages/client/lib/commands/ZSCORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZSCORE'; describe('ZSCORE', () => { @@ -10,10 +10,10 @@ describe('ZSCORE', () => { ); }); - itWithClient(TestRedisServers.OPEN, 'client.zScore', async client => { + testUtils.testWithClient('client.zScore', async client => { assert.equal( await client.zScore('key', 'member'), null ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZSCORE.ts b/packages/client/lib/commands/ZSCORE.ts similarity index 57% rename from lib/commands/ZSCORE.ts rename to packages/client/lib/commands/ZSCORE.ts index 18b664a3217..2bdecaf432a 100644 --- a/lib/commands/ZSCORE.ts +++ b/packages/client/lib/commands/ZSCORE.ts @@ -1,5 +1,3 @@ -import { transformReplyNumberInfinityNull } from './generic-transformers'; - export const FIRST_KEY_INDEX = 1; export const IS_READ_ONLY = true; @@ -8,4 +6,4 @@ export function transformArguments(key: string, member: string): Array { return ['ZSCORE', key, member]; } -export const transformReply = transformReplyNumberInfinityNull; +export { transformReplyNumberInfinityNull as transformReply } from './generic-transformers'; diff --git a/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts similarity index 83% rename from lib/commands/ZUNION.spec.ts rename to packages/client/lib/commands/ZUNION.spec.ts index 12e92833931..c53498cbf65 100644 --- a/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZUNION'; describe('ZUNION', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('key (string)', () => { @@ -39,10 +39,10 @@ describe('ZUNION', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zUnion', async client => { + testUtils.testWithClient('client.zUnion', async client => { assert.deepEqual( await client.zUnion('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZUNION.ts b/packages/client/lib/commands/ZUNION.ts similarity index 100% rename from lib/commands/ZUNION.ts rename to packages/client/lib/commands/ZUNION.ts diff --git a/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts similarity index 91% rename from lib/commands/ZUNIONSTORE.spec.ts rename to packages/client/lib/commands/ZUNIONSTORE.spec.ts index 0c4d7a3006b..8f11828b221 100644 --- a/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZUNIONSTORE'; describe('ZUNIONSTORE', () => { @@ -47,10 +47,10 @@ describe('ZUNIONSTORE', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zUnionStore', async client => { + testUtils.testWithClient('client.zUnionStore', async client => { assert.equal( await client.zUnionStore('destination', 'key'), 0 ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZUNIONSTORE.ts b/packages/client/lib/commands/ZUNIONSTORE.ts similarity index 100% rename from lib/commands/ZUNIONSTORE.ts rename to packages/client/lib/commands/ZUNIONSTORE.ts diff --git a/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts similarity index 83% rename from lib/commands/ZUNION_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index d9c65ba5e4b..3786a97963d 100644 --- a/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TestRedisServers, itWithClient, describeHandleMinimumRedisVersion } from '../test-utils'; +import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './ZUNION_WITHSCORES'; describe('ZUNION WITHSCORES', () => { - describeHandleMinimumRedisVersion([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { it('key (string)', () => { @@ -39,10 +39,10 @@ describe('ZUNION WITHSCORES', () => { }); }); - itWithClient(TestRedisServers.OPEN, 'client.zUnionWithScores', async client => { + testUtils.testWithClient('client.zUnionWithScores', async client => { assert.deepEqual( await client.zUnionWithScores('key'), [] ); - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/lib/commands/ZUNION_WITHSCORES.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.ts similarity index 73% rename from lib/commands/ZUNION_WITHSCORES.ts rename to packages/client/lib/commands/ZUNION_WITHSCORES.ts index d361fd432b0..3b937341921 100644 --- a/lib/commands/ZUNION_WITHSCORES.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.ts @@ -1,5 +1,4 @@ import { RedisCommandArguments } from '.'; -import { transformReplySortedSetWithScores } from './generic-transformers'; import { transformArguments as transformZUnionArguments } from './ZUNION'; export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZUNION'; @@ -11,4 +10,4 @@ export function transformArguments(...args: Parameters { }); }); + describe('transformArgumentStringNumberInfinity', () => { + it("'0.5'", () => { + assert.equal( + transformArgumentStringNumberInfinity('0.5'), + '0.5' + ); + }); + + it('0.5', () => { + assert.equal( + transformArgumentStringNumberInfinity(0.5), + '0.5' + ); + }); + }); + it('transformReplyTuples', () => { assert.deepEqual( transformReplyTuples(['key1', 'value1', 'key2', 'value2']), @@ -268,7 +285,7 @@ describe('Generic Transformers', () => { }) }] }] - ) + ); }); }); diff --git a/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts similarity index 98% rename from lib/commands/generic-transformers.ts rename to packages/client/lib/commands/generic-transformers.ts index a531e86b432..3075636e756 100644 --- a/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -69,6 +69,12 @@ export function transformArgumentNumberInfinity(num: number): string { } } +export function transformArgumentStringNumberInfinity(num: string | number): string { + if (typeof num === 'string') return num; + + return transformArgumentNumberInfinity(num); +} + export interface TuplesObject { [field: string]: string; } diff --git a/lib/commands/index.ts b/packages/client/lib/commands/index.ts similarity index 100% rename from lib/commands/index.ts rename to packages/client/lib/commands/index.ts diff --git a/lib/errors.ts b/packages/client/lib/errors.ts similarity index 65% rename from lib/errors.ts rename to packages/client/lib/errors.ts index 86a65587cf5..79a438aa1d8 100644 --- a/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -21,3 +21,15 @@ export class ClientClosedError extends Error { super('The client is closed'); } } + +export class DisconnectsClientError extends Error { + constructor() { + super('Disconnects client'); + } +} + +export class SocketClosedUnexpectedlyError extends Error { + constructor() { + super('Socket closed unexpectedly'); + } +} diff --git a/lib/lua-script.ts b/packages/client/lib/lua-script.ts similarity index 100% rename from lib/lua-script.ts rename to packages/client/lib/lua-script.ts diff --git a/lib/multi-command.spec.ts b/packages/client/lib/multi-command.spec.ts similarity index 100% rename from lib/multi-command.spec.ts rename to packages/client/lib/multi-command.spec.ts diff --git a/lib/multi-command.ts b/packages/client/lib/multi-command.ts similarity index 100% rename from lib/multi-command.ts rename to packages/client/lib/multi-command.ts diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts new file mode 100644 index 00000000000..321a9da63d5 --- /dev/null +++ b/packages/client/lib/test-utils.ts @@ -0,0 +1,49 @@ +import TestUtils from '@node-redis/test-utils'; +import { SinonSpy } from 'sinon'; +import { promiseTimeout } from './utils'; + +export default new TestUtils({ + defaultDockerVersion: '6.2', + dockerImageName: 'redis', + dockerImageVersionArgument: 'redis-version' +}); + +export const GLOBAL = { + SERVERS: { + OPEN: { + serverArguments: [] + }, + PASSWORD: { + serverArguments: ['--requirepass', 'password'], + clientOptions: { + password: 'password' + } + } + }, + CLUSTERS: { + OPEN: { + serverArguments: [] + }, + PASSWORD: { + serverArguments: ['--requirepass', 'password'], + clusterConfiguration: { + defaults: { + password: 'password' + } + } + } + } +}; + +export async function waitTillBeenCalled(spy: SinonSpy): Promise { + const start = process.hrtime.bigint(), + calls = spy.callCount; + + do { + if (process.hrtime.bigint() - start > 1_000_000_000) { + throw new Error('Waiting for more than 1 second'); + } + + await promiseTimeout(1); + } while (spy.callCount === calls); +} diff --git a/lib/ts-declarations/cluster-key-slot.d.ts b/packages/client/lib/ts-declarations/cluster-key-slot.d.ts similarity index 100% rename from lib/ts-declarations/cluster-key-slot.d.ts rename to packages/client/lib/ts-declarations/cluster-key-slot.d.ts diff --git a/lib/utils.ts b/packages/client/lib/utils.ts similarity index 100% rename from lib/utils.ts rename to packages/client/lib/utils.ts diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 00000000000..7a6d23f5ff9 --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,50 @@ +{ + "name": "@node-redis/client", + "version": "1.0.0-rc.0", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "build": "tsc", + "lint": "eslint ./*.ts ./lib/**/*.ts", + "documentation": "typedoc" + }, + "dependencies": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "redis-parser": "3.0.0", + "yallist": "4.0.0" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-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.4.0", + "@typescript-eslint/parser": "^5.4.0", + "eslint": "^8.2.0", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "sinon": "^12.0.1", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typedoc": "^0.22.9", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.6", + "typescript": "^4.4.4" + }, + "engines": { + "node": ">=12" + }, + "repository": { + "type": "git", + "url": "git://github.com/redis/node-redis.git" + }, + "bugs": { + "url": "https://github.com/redis/node-redis/issues" + }, + "homepage": "https://github.com/redis/node-redis/tree/master/packages/client" +} diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 00000000000..3280af594ef --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./index.ts", + "./lib/**/*.ts" + ], + "exclude": [ + "./lib/test-utils.ts", + "./lib/**/*.spec.ts" + ], + "typedocOptions": { + "entryPoints": [ + "./index.ts", + "./lib" + ], + "entryPointStrategy": "expand", + "exclude": [ + "./lib/ts-declarations", + "./lib/test-utils.ts" + ], + "theme": "./node_modules/typedoc-github-wiki-theme/dist", + "out": "documentation" + } +} diff --git a/packages/json/.npmignore b/packages/json/.npmignore new file mode 100644 index 00000000000..bbef2b404fb --- /dev/null +++ b/packages/json/.npmignore @@ -0,0 +1,6 @@ +.nyc_output/ +coverage/ +lib/ +.nycrc.json +.release-it.json +tsconfig.json diff --git a/.nycrc.json b/packages/json/.nycrc.json similarity index 98% rename from .nycrc.json rename to packages/json/.nycrc.json index 925d954248c..b4e671e178f 100644 --- a/.nycrc.json +++ b/packages/json/.nycrc.json @@ -1,4 +1,4 @@ { "extends": "@istanbuljs/nyc-config-typescript", "exclude": ["**/*.spec.ts", "lib/test-utils.ts"] -} \ No newline at end of file +} diff --git a/packages/json/.release-it.json b/packages/json/.release-it.json new file mode 100644 index 00000000000..ab495a49b13 --- /dev/null +++ b/packages/json/.release-it.json @@ -0,0 +1,10 @@ +{ + "git": { + "tagName": "json@${version}", + "commitMessage": "Release ${tagName}", + "tagAnnotation": "Release ${tagName}" + }, + "npm": { + "publishArgs": ["--access", "public"] + } +} diff --git a/packages/json/README.md b/packages/json/README.md new file mode 100644 index 00000000000..1cd599d5ea8 --- /dev/null +++ b/packages/json/README.md @@ -0,0 +1,2 @@ +# @node-redis/json +The sources and docs for this package are in the main [node-redis](https://github.com/redis/node-redis) repo. diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts new file mode 100644 index 00000000000..ab53837a000 --- /dev/null +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRAPPEND'; + +describe('ARRAPPEND', () => { + describe('transformArguments', () => { + it('single JSON', () => { + assert.deepEqual( + transformArguments('key', '$', 1), + ['JSON.ARRAPPEND', 'key', '$', '1'] + ); + }); + + it('multiple JSONs', () => { + assert.deepEqual( + transformArguments('key', '$', 1, 2), + ['JSON.ARRAPPEND', 'key', '$', '1', '2'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrAppend', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrAppend('key', '$', 1), + [1] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRAPPEND.ts b/packages/json/lib/commands/ARRAPPEND.ts new file mode 100644 index 00000000000..2935d192996 --- /dev/null +++ b/packages/json/lib/commands/ARRAPPEND.ts @@ -0,0 +1,15 @@ +import { RedisJSON, transformRedisJsonArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path: string, ...jsons: Array): Array { + const args = ['JSON.ARRAPPEND', key, path]; + + for (const json of jsons) { + args.push(transformRedisJsonArgument(json)); + } + + return args; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/ARRINDEX.spec.ts b/packages/json/lib/commands/ARRINDEX.spec.ts new file mode 100644 index 00000000000..7a47d67126a --- /dev/null +++ b/packages/json/lib/commands/ARRINDEX.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRINDEX'; + +describe('ARRINDEX', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', '$', 'json'), + ['JSON.ARRINDEX', 'key', '$', '"json"'] + ); + }); + + it('with start', () => { + assert.deepEqual( + transformArguments('key', '$', 'json', 1), + ['JSON.ARRINDEX', 'key', '$', '"json"', '1'] + ); + }); + + it('with start, end', () => { + assert.deepEqual( + transformArguments('key', '$', 'json', 1, 2), + ['JSON.ARRINDEX', 'key', '$', '"json"', '1', '2'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrIndex', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrIndex('key', '$', 'json'), + [-1] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRINDEX.ts b/packages/json/lib/commands/ARRINDEX.ts new file mode 100644 index 00000000000..5860b59cb3c --- /dev/null +++ b/packages/json/lib/commands/ARRINDEX.ts @@ -0,0 +1,21 @@ +import { RedisJSON, transformRedisJsonArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: string, path: string, json: RedisJSON, start?: number, stop?: number): Array { + const args = ['JSON.ARRINDEX', key, path, transformRedisJsonArgument(json)]; + + if (start !== undefined && start !== null) { + args.push(start.toString()); + + if (stop !== undefined && stop !== null) { + args.push(stop.toString()); + } + } + + return args; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts new file mode 100644 index 00000000000..4b9d58b2cac --- /dev/null +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRINSERT'; + +describe('ARRINSERT', () => { + describe('transformArguments', () => { + it('single JSON', () => { + assert.deepEqual( + transformArguments('key', '$', 0, 'json'), + ['JSON.ARRINSERT', 'key', '$', '0', '"json"'] + ); + }); + + it('multiple JSONs', () => { + assert.deepEqual( + transformArguments('key', '$', 0, '1', '2'), + ['JSON.ARRINSERT', 'key', '$', '0', '"1"', '"2"'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrInsert', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrInsert('key', '$', 0, 'json'), + [1] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRINSERT.ts b/packages/json/lib/commands/ARRINSERT.ts new file mode 100644 index 00000000000..85857657019 --- /dev/null +++ b/packages/json/lib/commands/ARRINSERT.ts @@ -0,0 +1,15 @@ +import { RedisJSON, transformRedisJsonArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path: string, index: number, ...jsons: Array): Array { + const args = ['JSON.ARRINSERT', key, path, index.toString()]; + + for (const json of jsons) { + args.push(transformRedisJsonArgument(json)); + } + + return args; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts new file mode 100644 index 00000000000..f0a3ec40a4c --- /dev/null +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRLEN'; + +describe('ARRLEN', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.ARRLEN', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.ARRLEN', 'key', '$'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrLen', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrLen('key', '$'), + [0] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRLEN.ts b/packages/json/lib/commands/ARRLEN.ts new file mode 100644 index 00000000000..818397b7f8d --- /dev/null +++ b/packages/json/lib/commands/ARRLEN.ts @@ -0,0 +1,15 @@ +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.ARRLEN', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/ARRPOP.spec.ts b/packages/json/lib/commands/ARRPOP.spec.ts new file mode 100644 index 00000000000..a80b8c3cbc5 --- /dev/null +++ b/packages/json/lib/commands/ARRPOP.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRPOP'; + +describe('ARRPOP', () => { + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.ARRPOP', 'key'] + ); + }); + + it('key, path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.ARRPOP', 'key', '$'] + ); + }); + + it('key, path, index', () => { + assert.deepEqual( + transformArguments('key', '$', 0), + ['JSON.ARRPOP', 'key', '$', '0'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrPop', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrPop('key', '$'), + [null] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRPOP.ts b/packages/json/lib/commands/ARRPOP.ts new file mode 100644 index 00000000000..5d8785a8d94 --- /dev/null +++ b/packages/json/lib/commands/ARRPOP.ts @@ -0,0 +1,17 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string, index?: number): Array { + const args = ['JSON.ARRPOP', key]; + + if (path) { + args.push(path); + + if (index !== undefined && index !== null) { + args.push(index.toString()); + } + } + + return args; +} + +export { transformRedisJsonNullArrayReply as transformReply } from '.'; diff --git a/packages/json/lib/commands/ARRTRIM.spec.ts b/packages/json/lib/commands/ARRTRIM.spec.ts new file mode 100644 index 00000000000..c254e1b6a03 --- /dev/null +++ b/packages/json/lib/commands/ARRTRIM.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ARRTRIM'; + +describe('ARRTRIM', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', '$', 0, 1), + ['JSON.ARRTRIM', 'key', '$', '0', '1'] + ); + }); + + testUtils.testWithClient('client.json.arrTrim', async client => { + await client.json.set('key', '$', []); + + assert.deepEqual( + await client.json.arrTrim('key', '$', 0, 1), + [0] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/ARRTRIM.ts b/packages/json/lib/commands/ARRTRIM.ts new file mode 100644 index 00000000000..2de444eeebd --- /dev/null +++ b/packages/json/lib/commands/ARRTRIM.ts @@ -0,0 +1,7 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path: string, start: number, stop: number): Array { + return ['JSON.ARRTRIM', key, path, start.toString(), stop.toString()]; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts new file mode 100644 index 00000000000..468c994f2f5 --- /dev/null +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './DEBUG_MEMORY'; + +describe('DEBUG MEMORY', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.DEBUG', 'MEMORY', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.DEBUG', 'MEMORY', 'key', '$'] + ); + }); + }); + + testUtils.testWithClient('client.json.arrTrim', async client => { + assert.deepEqual( + await client.json.debugMemory('key', '$'), + [] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts new file mode 100644 index 00000000000..da60b1d9529 --- /dev/null +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 2; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.DEBUG', 'MEMORY', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number; diff --git a/packages/json/lib/commands/DEL.spec.ts b/packages/json/lib/commands/DEL.spec.ts new file mode 100644 index 00000000000..a957b9584ac --- /dev/null +++ b/packages/json/lib/commands/DEL.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './DEL'; + +describe('DEL', () => { + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.DEL', 'key'] + ); + }); + + it('key, path', () => { + assert.deepEqual( + transformArguments('key', '$.path'), + ['JSON.DEL', 'key', '$.path'] + ); + }); + }); + + testUtils.testWithClient('client.json.del', async client => { + assert.deepEqual( + await client.json.del('key'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/DEL.ts b/packages/json/lib/commands/DEL.ts new file mode 100644 index 00000000000..090d4dbe853 --- /dev/null +++ b/packages/json/lib/commands/DEL.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.DEL', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number; diff --git a/packages/json/lib/commands/FORGET.spec.ts b/packages/json/lib/commands/FORGET.spec.ts new file mode 100644 index 00000000000..923bb997fc8 --- /dev/null +++ b/packages/json/lib/commands/FORGET.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './FORGET'; + +describe('FORGET', () => { + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.FORGET', 'key'] + ); + }); + + it('key, path', () => { + assert.deepEqual( + transformArguments('key', '$.path'), + ['JSON.FORGET', 'key', '$.path'] + ); + }); + }); + + testUtils.testWithClient('client.json.forget', async client => { + assert.deepEqual( + await client.json.forget('key'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/FORGET.ts b/packages/json/lib/commands/FORGET.ts new file mode 100644 index 00000000000..cb2df3d605d --- /dev/null +++ b/packages/json/lib/commands/FORGET.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.FORGET', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number; diff --git a/packages/json/lib/commands/GET.spec.ts b/packages/json/lib/commands/GET.spec.ts new file mode 100644 index 00000000000..ed831689a93 --- /dev/null +++ b/packages/json/lib/commands/GET.spec.ts @@ -0,0 +1,78 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './GET'; + +describe('GET', () => { + describe('transformArguments', () => { + describe('path', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', { path: '$' }), + ['JSON.GET', 'key', '$'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', { path: ['$.1', '$.2'] }), + ['JSON.GET', 'key', '$.1', '$.2'] + ); + }); + }); + + it('key', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.GET', 'key'] + ); + }); + + it('INDENT', () => { + assert.deepEqual( + transformArguments('key', { INDENT: 'indent' }), + ['JSON.GET', 'key', 'INDENT', 'indent'] + ); + }); + + it('NEWLINE', () => { + assert.deepEqual( + transformArguments('key', { NEWLINE: 'newline' }), + ['JSON.GET', 'key', 'NEWLINE', 'newline'] + ); + }); + + it('SPACE', () => { + assert.deepEqual( + transformArguments('key', { SPACE: 'space' }), + ['JSON.GET', 'key', 'SPACE', 'space'] + ); + }); + + it('NOESCAPE', () => { + assert.deepEqual( + transformArguments('key', { NOESCAPE: true }), + ['JSON.GET', 'key', 'NOESCAPE'] + ); + }); + + it('INDENT, NEWLINE, SPACE, NOESCAPE, path', () => { + assert.deepEqual( + transformArguments('key', { + path: '$.path', + INDENT: 'indent', + NEWLINE: 'newline', + SPACE: 'space', + NOESCAPE: true + }), + ['JSON.GET', 'key', '$.path', 'INDENT', 'indent', 'NEWLINE', 'newline', 'SPACE', 'space', 'NOESCAPE'] + ); + }); + }); + + testUtils.testWithClient('client.json.get', async client => { + assert.equal( + await client.json.get('key'), + null + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/GET.ts b/packages/json/lib/commands/GET.ts new file mode 100644 index 00000000000..8e897bb67d2 --- /dev/null +++ b/packages/json/lib/commands/GET.ts @@ -0,0 +1,41 @@ +import { pushVerdictArguments } from '@node-redis/client/dist/lib/commands/generic-transformers'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +interface GetOptions { + path?: string | Array; + INDENT?: string; + NEWLINE?: string; + SPACE?: string; + NOESCAPE?: true; +} + +export function transformArguments(key: string, options?: GetOptions): Array { + const args = ['JSON.GET', key]; + + if (options?.path) { + pushVerdictArguments(args, options.path); + } + + if (options?.INDENT) { + args.push('INDENT', options.INDENT); + } + + if (options?.NEWLINE) { + args.push('NEWLINE', options.NEWLINE); + } + + if (options?.SPACE) { + args.push('SPACE', options.SPACE); + } + + if (options?.NOESCAPE) { + args.push('NOESCAPE'); + } + + return args; +} + +export { transformRedisJsonNullReply as transformReply } from '.'; diff --git a/packages/json/lib/commands/MGET.spec.ts b/packages/json/lib/commands/MGET.spec.ts new file mode 100644 index 00000000000..456e160dd50 --- /dev/null +++ b/packages/json/lib/commands/MGET.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './MGET'; + +describe('MGET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(['1', '2'], '$'), + ['JSON.MGET', '1', '2', '$'] + ); + }); + + testUtils.testWithClient('client.json.mGet', async client => { + assert.deepEqual( + await client.json.mGet(['1', '2'], '$'), + [null, null] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/MGET.ts b/packages/json/lib/commands/MGET.ts new file mode 100644 index 00000000000..582b73bf85a --- /dev/null +++ b/packages/json/lib/commands/MGET.ts @@ -0,0 +1,15 @@ +import { RedisJSON, transformRedisJsonNullReply } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(keys: Array, path: string): Array { + return [ + 'JSON.MGET', + ...keys, + path + ]; +} + +export function transformReply(reply: Array): Array { + return reply.map(transformRedisJsonNullReply); +} diff --git a/packages/json/lib/commands/NUMINCRBY.spec.ts b/packages/json/lib/commands/NUMINCRBY.spec.ts new file mode 100644 index 00000000000..56dede68bde --- /dev/null +++ b/packages/json/lib/commands/NUMINCRBY.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './NUMINCRBY'; + +describe('NUMINCRBY', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', '$', 1), + ['JSON.NUMINCRBY', 'key', '$', '1'] + ); + }); + + testUtils.testWithClient('client.json.numIncrBy', async client => { + await client.json.set('key', '$', 0); + + assert.deepEqual( + await client.json.numIncrBy('key', '$', 1), + [1] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/NUMINCRBY.ts b/packages/json/lib/commands/NUMINCRBY.ts new file mode 100644 index 00000000000..e3d8887ea3d --- /dev/null +++ b/packages/json/lib/commands/NUMINCRBY.ts @@ -0,0 +1,7 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path: string, by: number): Array { + return ['JSON.NUMINCRBY', key, path, by.toString()]; +} + +export { transformNumbersReply as transformReply } from '.'; diff --git a/packages/json/lib/commands/NUMMULTBY.spec.ts b/packages/json/lib/commands/NUMMULTBY.spec.ts new file mode 100644 index 00000000000..3e2581a3cd8 --- /dev/null +++ b/packages/json/lib/commands/NUMMULTBY.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './NUMMULTBY'; + +describe('NUMMULTBY', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', '$', 2), + ['JSON.NUMMULTBY', 'key', '$', '2'] + ); + }); + + testUtils.testWithClient('client.json.numMultBy', async client => { + await client.json.set('key', '$', 1); + + assert.deepEqual( + await client.json.numMultBy('key', '$', 2), + [2] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/NUMMULTBY.ts b/packages/json/lib/commands/NUMMULTBY.ts new file mode 100644 index 00000000000..2082916619a --- /dev/null +++ b/packages/json/lib/commands/NUMMULTBY.ts @@ -0,0 +1,7 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path: string, by: number): Array { + return ['JSON.NUMMULTBY', key, path, by.toString()]; +} + +export { transformNumbersReply as transformReply } from '.'; diff --git a/packages/json/lib/commands/OBJKEYS.spec.ts b/packages/json/lib/commands/OBJKEYS.spec.ts new file mode 100644 index 00000000000..6288c112392 --- /dev/null +++ b/packages/json/lib/commands/OBJKEYS.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './OBJKEYS'; + +describe('OBJKEYS', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.OBJKEYS', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.OBJKEYS', 'key', '$'] + ); + }); + }); + + // testUtils.testWithClient('client.json.objKeys', async client => { + // assert.deepEqual( + // await client.json.objKeys('key', '$'), + // [null] + // ); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/OBJKEYS.ts b/packages/json/lib/commands/OBJKEYS.ts new file mode 100644 index 00000000000..a9465c9160c --- /dev/null +++ b/packages/json/lib/commands/OBJKEYS.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.OBJKEYS', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): Array | null | Array | null>; diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts new file mode 100644 index 00000000000..35b6589c875 --- /dev/null +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './OBJLEN'; + +describe('OBJLEN', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.OBJLEN', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.OBJLEN', 'key', '$'] + ); + }); + }); + + // testUtils.testWithClient('client.json.objLen', async client => { + // assert.equal( + // await client.json.objLen('key', '$'), + // [null] + // ); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/OBJLEN.ts b/packages/json/lib/commands/OBJLEN.ts new file mode 100644 index 00000000000..aa800e97f71 --- /dev/null +++ b/packages/json/lib/commands/OBJLEN.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.OBJLEN', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number | null | Array; diff --git a/packages/json/lib/commands/RESP.spec.ts b/packages/json/lib/commands/RESP.spec.ts new file mode 100644 index 00000000000..8b70962d1c5 --- /dev/null +++ b/packages/json/lib/commands/RESP.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './RESP'; + +describe('RESP', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.RESP', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.RESP', 'key', '$'] + ); + }); + }); + + // testUtils.testWithClient('client.json.resp', async client => { + // assert.deepEqual( + // await client.json.resp('key', '$'), + // [null] + // ); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/RESP.ts b/packages/json/lib/commands/RESP.ts new file mode 100644 index 00000000000..2b56bf1f059 --- /dev/null +++ b/packages/json/lib/commands/RESP.ts @@ -0,0 +1,15 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.RESP', key]; + + if (path) { + args.push(path); + } + + return args; +} + +type RESPReply = Array; + +export declare function transfromReply(): RESPReply; diff --git a/packages/json/lib/commands/SET.spec.ts b/packages/json/lib/commands/SET.spec.ts new file mode 100644 index 00000000000..8f8586a2047 --- /dev/null +++ b/packages/json/lib/commands/SET.spec.ts @@ -0,0 +1,35 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SET'; + +describe('SET', () => { + describe('transformArguments', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', '$', 'json'), + ['JSON.SET', 'key', '$', '"json"'] + ); + }); + + it('NX', () => { + assert.deepEqual( + transformArguments('key', '$', 'json', { NX: true }), + ['JSON.SET', 'key', '$', '"json"', 'NX'] + ); + }); + + it('XX', () => { + assert.deepEqual( + transformArguments('key', '$', 'json', { XX: true }), + ['JSON.SET', 'key', '$', '"json"', 'XX'] + ); + }); + }); + + testUtils.testWithClient('client.json.mGet', async client => { + assert.equal( + await client.json.set('key', '$', 'json'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/SET.ts b/packages/json/lib/commands/SET.ts new file mode 100644 index 00000000000..f50a42bf5db --- /dev/null +++ b/packages/json/lib/commands/SET.ts @@ -0,0 +1,25 @@ +import { RedisJSON, transformRedisJsonArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +interface NX { + NX: true; +} + +interface XX { + XX: true; +} + +export function transformArguments(key: string, path: string, json: RedisJSON, options?: NX | XX): Array { + const args = ['JSON.SET', key, path, transformRedisJsonArgument(json)]; + + if ((options)?.NX) { + args.push('NX'); + } else if ((options)?.XX) { + args.push('XX'); + } + + return args; +} + +export declare function transformReply(): 'OK' | null; diff --git a/packages/json/lib/commands/STRAPPEND.spec.ts b/packages/json/lib/commands/STRAPPEND.spec.ts new file mode 100644 index 00000000000..a37eaa1d91c --- /dev/null +++ b/packages/json/lib/commands/STRAPPEND.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './STRAPPEND'; + +describe('STRAPPEND', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key', 'append'), + ['JSON.STRAPPEND', 'key', '"append"'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$', 'append'), + ['JSON.STRAPPEND', 'key', '$', '"append"'] + ); + }); + }); + + testUtils.testWithClient('client.json.strAppend', async client => { + await client.json.set('key', '$', ''); + + assert.deepEqual( + await client.json.strAppend('key', '$', 'append'), + [6] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/STRAPPEND.ts b/packages/json/lib/commands/STRAPPEND.ts new file mode 100644 index 00000000000..eea384c93fd --- /dev/null +++ b/packages/json/lib/commands/STRAPPEND.ts @@ -0,0 +1,21 @@ +import { transformRedisJsonArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +type AppendArguments = [key: string, append: string]; + +type AppendWithPathArguments = [key: string, path: string, append: string]; + +export function transformArguments(...[key, pathOrAppend, append]: AppendArguments | AppendWithPathArguments): Array { + const args = ['JSON.STRAPPEND', key]; + + if (append !== undefined && append !== null) { + args.push(pathOrAppend, transformRedisJsonArgument(append)); + } else { + args.push(transformRedisJsonArgument(pathOrAppend)); + } + + return args; +} + +export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts new file mode 100644 index 00000000000..cf163d3c19e --- /dev/null +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './STRLEN'; + +describe('STRLEN', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.STRLEN', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.STRLEN', 'key', '$'] + ); + }); + }); + + testUtils.testWithClient('client.json.strLen', async client => { + await client.json.set('key', '$', ''); + + assert.deepEqual( + await client.json.strLen('key', '$'), + [0] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/STRLEN.ts b/packages/json/lib/commands/STRLEN.ts new file mode 100644 index 00000000000..93f5d563baf --- /dev/null +++ b/packages/json/lib/commands/STRLEN.ts @@ -0,0 +1,15 @@ +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.STRLEN', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): number; diff --git a/packages/json/lib/commands/TYPE.spec.ts b/packages/json/lib/commands/TYPE.spec.ts new file mode 100644 index 00000000000..5cecfb827a7 --- /dev/null +++ b/packages/json/lib/commands/TYPE.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './TYPE'; + +describe('TYPE', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.TYPE', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + transformArguments('key', '$'), + ['JSON.TYPE', 'key', '$'] + ); + }); + }); + + // testUtils.testWithClient('client.json.type', async client => { + // assert.deepEqual( + // await client.json.type('key', '$'), + // [null] + // ); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/TYPE.ts b/packages/json/lib/commands/TYPE.ts new file mode 100644 index 00000000000..7fd55f625dc --- /dev/null +++ b/packages/json/lib/commands/TYPE.ts @@ -0,0 +1,13 @@ +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: string, path?: string): Array { + const args = ['JSON.TYPE', key]; + + if (path) { + args.push(path); + } + + return args; +} + +export declare function transformReply(): string | null | Array; diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts new file mode 100644 index 00000000000..91b4f7dc4b5 --- /dev/null +++ b/packages/json/lib/commands/index.ts @@ -0,0 +1,94 @@ +import * as ARRAPPEND from './ARRAPPEND'; +import * as ARRINDEX from './ARRINDEX'; +import * as ARRINSERT from './ARRINSERT'; +import * as ARRLEN from './ARRLEN'; +import * as ARRPOP from './ARRPOP'; +import * as ARRTRIM from './ARRTRIM'; +import * as DEBUG_MEMORY from './DEBUG_MEMORY'; +import * as DEL from './DEL'; +import * as FORGET from './FORGET'; +import * as GET from './GET'; +import * as MGET from './MGET'; +import * as NUMINCRBY from './NUMINCRBY'; +import * as NUMMULTBY from './NUMMULTBY'; +import * as OBJKEYS from './OBJKEYS'; +import * as OBJLEN from './OBJLEN'; +import * as RESP from './RESP'; +import * as SET from './SET'; +import * as STRAPPEND from './STRAPPEND'; +import * as STRLEN from './STRLEN'; +import * as TYPE from './TYPE'; + +export default { + ARRAPPEND, + arrAppend: ARRAPPEND, + ARRINDEX, + arrIndex: ARRINDEX, + ARRINSERT, + arrInsert: ARRINSERT, + ARRLEN, + arrLen: ARRLEN, + ARRPOP, + arrPop: ARRPOP, + ARRTRIM, + arrTrim: ARRTRIM, + DEBUG_MEMORY, + debugMemory: DEBUG_MEMORY, + DEL, + del: DEL, + FORGET, + forget: FORGET, + GET, + get: GET, + MGET, + mGet: MGET, + NUMINCRBY, + numIncrBy: NUMINCRBY, + NUMMULTBY, + numMultBy: NUMMULTBY, + OBJKEYS, + objKeys: OBJKEYS, + OBJLEN, + objLen: OBJLEN, + RESP, + resp: RESP, + SET, + set: SET, + STRAPPEND, + strAppend: STRAPPEND, + STRLEN, + strLen: STRLEN, + TYPE, + type: TYPE +}; + +// using two "objects" and not `Record` cause of: +// https://github.com/microsoft/TypeScript/issues/14174 +export type RedisJSON = null | boolean | number | string | Date | Array | { [key: string]: RedisJSON } | { [key: number]: RedisJSON }; + +export function transformRedisJsonArgument(json: RedisJSON): string { + return JSON.stringify(json); +} + +export function transformRedisJsonReply(json: string): RedisJSON { + return JSON.parse(json); +} + +export function transformRedisJsonArrayReply(jsons: Array): Array { + return jsons.map(transformRedisJsonReply) +} + +export function transformRedisJsonNullReply(json: string | null): RedisJSON | null { + if (json === null) return null; + + return transformRedisJsonReply(json); +} + + +export function transformRedisJsonNullArrayReply(jsons: Array): Array { + return jsons.map(transformRedisJsonNullReply); +} + +export function transformNumbersReply(reply: string): number | Array { + return JSON.parse(reply); +} diff --git a/packages/json/lib/index.ts b/packages/json/lib/index.ts new file mode 100644 index 00000000000..bc0e103e8c8 --- /dev/null +++ b/packages/json/lib/index.ts @@ -0,0 +1 @@ +export { default } from './commands'; diff --git a/packages/json/lib/test-utils.ts b/packages/json/lib/test-utils.ts new file mode 100644 index 00000000000..eeee3c77c9d --- /dev/null +++ b/packages/json/lib/test-utils.ts @@ -0,0 +1,21 @@ +import TestUtils from '@node-redis/test-utils'; +import RedisJSON from '.'; + +export default new TestUtils({ + dockerImageName: 'redislabs/rejson', + dockerImageVersionArgument: 'rejson-version', + defaultDockerVersion: '2.0.2' +}); + +export const GLOBAL = { + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/rejson.so'], + clientOptions: { + modules: { + json: RedisJSON + } + } + } + } +}; diff --git a/packages/json/package.json b/packages/json/package.json new file mode 100644 index 00000000000..7e5f6e10c1f --- /dev/null +++ b/packages/json/package.json @@ -0,0 +1,24 @@ +{ + "name": "@node-redis/json", + "version": "1.0.0-rc.0", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "build": "tsc" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } +} diff --git a/packages/json/tsconfig.json b/packages/json/tsconfig.json new file mode 100644 index 00000000000..14fda1d8711 --- /dev/null +++ b/packages/json/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./lib/**/*.ts" + ] +} diff --git a/packages/search/.npmignore b/packages/search/.npmignore new file mode 100644 index 00000000000..bbef2b404fb --- /dev/null +++ b/packages/search/.npmignore @@ -0,0 +1,6 @@ +.nyc_output/ +coverage/ +lib/ +.nycrc.json +.release-it.json +tsconfig.json diff --git a/packages/search/.nycrc.json b/packages/search/.nycrc.json new file mode 100644 index 00000000000..b4e671e178f --- /dev/null +++ b/packages/search/.nycrc.json @@ -0,0 +1,4 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "exclude": ["**/*.spec.ts", "lib/test-utils.ts"] +} diff --git a/packages/search/.release-it.json b/packages/search/.release-it.json new file mode 100644 index 00000000000..72cb1016ef4 --- /dev/null +++ b/packages/search/.release-it.json @@ -0,0 +1,10 @@ +{ + "git": { + "tagName": "search@${version}", + "commitMessage": "Release ${tagName}", + "tagAnnotation": "Release ${tagName}" + }, + "npm": { + "publishArgs": ["--access", "public"] + } +} diff --git a/packages/search/README.md b/packages/search/README.md new file mode 100644 index 00000000000..856a75fbb5a --- /dev/null +++ b/packages/search/README.md @@ -0,0 +1,2 @@ +# @node-redis/search +The sources and docs for this package are in the main [node-redis](https://github.com/redis/node-redis) repo. diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts new file mode 100644 index 00000000000..2a6647c97a4 --- /dev/null +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -0,0 +1,482 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { AggregateGroupByReducers, AggregateSteps, transformArguments } from './AGGREGATE'; +import { SchemaFieldTypes } from './CREATE'; + +describe('AGGREGATE', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('index', '*'), + ['FT.AGGREGATE', 'index', '*'] + ); + }); + + it('with VERBATIM', () => { + assert.deepEqual( + transformArguments('index', '*', { VERBATIM: true }), + ['FT.AGGREGATE', 'index', '*', 'VERBATIM'] + ); + }); + + describe('with LOAD', () => { + describe('single', () => { + describe('without alias', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', '*', { LOAD: '@property' }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] + ); + }); + + it('{ identifier: string }', () => { + assert.deepEqual( + transformArguments('index', '*', { + LOAD: { + identifier: '@property' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] + ); + }); + }); + + it('with alias', () => { + assert.deepEqual( + transformArguments('index', '*', { + LOAD: { + identifier: '@property', + AS: 'alias' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '3', '@property', 'AS', 'alias'] + ); + }); + }); + + it('multiple', () => { + assert.deepEqual( + transformArguments('index', '*', { LOAD: ['@1', '@2'] }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '2', '@1', '@2'] + ); + }); + }); + + describe('with STEPS', () => { + describe('GROUPBY', () => { + describe('COUNT', () => { + describe('without properties', () => { + it('without alias', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.COUNT + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0'] + ); + }); + + it('with alias', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.COUNT, + AS: 'count' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0', 'AS', 'count'] + ); + }); + }); + + describe('with properties', () => { + it('single', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + properties: '@property', + REDUCE: { + type: AggregateGroupByReducers.COUNT + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '1', '@property', 'REDUCE', 'COUNT', '0'] + ); + }); + + it('multiple', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + properties: ['@1', '@2'], + REDUCE: { + type: AggregateGroupByReducers.COUNT + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '2', '@1', '@2', 'REDUCE', 'COUNT', '0'] + ); + }); + }); + }); + + it('COUNT_DISTINCT', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.COUNT_DISTINCT, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCT', '1', '@property'] + ); + }); + + it('COUNT_DISTINCTISH', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.COUNT_DISTINCTISH, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCTISH', '1', '@property'] + ); + }); + + it('SUM', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.SUM, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'SUM', '1', '@property'] + ); + }); + + it('MIN', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.MIN, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MIN', '1', '@property'] + ); + }); + + it('MAX', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.MAX, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MAX', '1', '@property'] + ); + }); + + it('AVG', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.AVG, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'AVG', '1', '@property'] + ); + }); + + it('STDDEV', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.STDDEV, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'STDDEV', '1', '@property'] + ); + }); + + it('QUANTILE', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.QUANTILE, + property: '@property', + quantile: 0.5 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'QUANTILE', '2', '@property', '0.5'] + ); + }); + + it('TO_LIST', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.TO_LIST, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'TOLIST', '1', '@property'] + ); + }); + + describe('FIRST_VALUE', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.FIRST_VALUE, + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '1', '@property'] + ); + }); + + describe('with BY', () => { + describe('without direction', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.FIRST_VALUE, + property: '@property', + BY: '@by' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] + ); + }); + + + it('{ property: string }', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.FIRST_VALUE, + property: '@property', + BY: { + property: '@by' + } + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] + ); + }); + }); + + it('with direction', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.FIRST_VALUE, + property: '@property', + BY: { + property: '@by', + direction: 'ASC' + } + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '4', '@property', 'BY', '@by', 'ASC'] + ); + }); + }); + }); + + it('RANDOM_SAMPLE', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: { + type: AggregateGroupByReducers.RANDOM_SAMPLE, + property: '@property', + sampleSize: 1 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'RANDOM_SAMPLE', '2', '@property', '1'] + ); + }); + }); + + describe('SORTBY', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.SORTBY, + BY: '@by' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.SORTBY, + BY: ['@1', '@2'] + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '2', '@1', '@2'] + ); + }); + + it('with MAX', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.SORTBY, + BY: '@by', + MAX: 1 + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by', 'MAX', '1'] + ); + }); + }); + + describe('APPLY', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.APPLY, + expression: '@field + 1', + AS: 'as' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'APPLY', '@field + 1', 'AS', 'as'] + ); + }); + + describe('LIMIT', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.LIMIT, + from: 0, + size: 1 + }] + }), + ['FT.AGGREGATE', 'index', '*', 'LIMIT', '0', '1'] + ); + }); + + describe('FILTER', () => { + assert.deepEqual( + transformArguments('index', '*', { + STEPS: [{ + type: AggregateSteps.FILTER, + expression: '@field != ""' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'FILTER', '@field != ""'] + ); + }); + }); + }); + + testUtils.testWithClient('client.ft.aggregate', async client => { + await Promise.all([ + client.ft.create('index', { + field: SchemaFieldTypes.NUMERIC + }), + client.hSet('1', 'field', '1'), + client.hSet('2', 'field', '2') + ]); + + assert.deepEqual( + await client.ft.aggregate('index', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: [{ + type: AggregateGroupByReducers.SUM, + property: '@field', + AS: 'sum' + }, { + type: AggregateGroupByReducers.AVG, + property: '@field', + AS: 'avg' + }] + }] + }), + { + total: 1, + results: [ + Object.create(null, { + sum: { + value: '3', + configurable: true, + enumerable: true + }, + avg: { + value: '1.5', + configurable: true, + enumerable: true + } + }) + ] + } + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts new file mode 100644 index 00000000000..c81dcfef4dd --- /dev/null +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -0,0 +1,283 @@ +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; +import { pushVerdictArgument, transformReplyTuples, TuplesObject } from '@node-redis/client/dist/lib/commands/generic-transformers'; +import { PropertyName, pushArgumentsWithLength, pushSortByArguments, SortByOptions } from '.'; + +export enum AggregateSteps { + GROUPBY = 'GROUPBY', + SORTBY = 'SORTBY', + APPLY = 'APPLY', + LIMIT = 'LIMIT', + FILTER = 'FILTER' +} + +interface AggregateStep { + type: T; +} + +export enum AggregateGroupByReducers { + COUNT = 'COUNT', + COUNT_DISTINCT = 'COUNT_DISTINCT', + COUNT_DISTINCTISH = 'COUNT_DISTINCTISH', + SUM = 'SUM', + MIN = 'MIN', + MAX = 'MAX', + AVG = 'AVG', + STDDEV = 'STDDEV', + QUANTILE = 'QUANTILE', + TOLIST = 'TOLIST', + TO_LIST = 'TOLIST', + FIRST_VALUE = 'FIRST_VALUE', + RANDOM_SAMPLE = 'RANDOM_SAMPLE' +} + +interface GroupByReducer { + type: T; + AS?: string; +} + +type CountReducer = GroupByReducer; + +interface CountDistinctReducer extends GroupByReducer { + property: PropertyName; +} + +interface CountDistinctishReducer extends GroupByReducer { + property: PropertyName; +} + +interface SumReducer extends GroupByReducer { + property: PropertyName; +} + +interface MinReducer extends GroupByReducer { + property: PropertyName; +} + +interface MaxReducer extends GroupByReducer { + property: PropertyName; +} + +interface AvgReducer extends GroupByReducer { + property: PropertyName; +} + +interface StdDevReducer extends GroupByReducer { + property: PropertyName; +} + +interface QuantileReducer extends GroupByReducer { + property: PropertyName; + quantile: number; +} + +interface ToListReducer extends GroupByReducer { + property: PropertyName; +} + +interface FirstValueReducer extends GroupByReducer { + property: PropertyName; + BY?: PropertyName | { + property: PropertyName; + direction?: 'ASC' | 'DESC'; + }; +} + +interface RandomSampleReducer extends GroupByReducer { + property: PropertyName; + sampleSize: number; +} + +type GroupByReducers = CountReducer | CountDistinctReducer | CountDistinctishReducer | SumReducer | MinReducer | MaxReducer | AvgReducer | StdDevReducer | QuantileReducer | ToListReducer | FirstValueReducer | RandomSampleReducer; + +interface GroupByStep extends AggregateStep { + properties?: PropertyName | Array; + REDUCE: GroupByReducers | Array; +} + +interface SortStep extends AggregateStep { + BY: SortByOptions | Array; + MAX?: number; +} + +interface ApplyStep extends AggregateStep { + expression: string; + AS: string; +} + +interface LimitStep extends AggregateStep { + from: number; + size: number; +} + +interface FilterStep extends AggregateStep { + expression: string; +} + +type LoadField = PropertyName | { + identifier: PropertyName; + AS?: string; +} + +interface AggregateOptions { + VERBATIM?: true; + LOAD?: LoadField | Array; + STEPS?: Array; +} + +export function transformArguments(index: string, query: string, options?: AggregateOptions): RedisCommandArguments { + const args = ['FT.AGGREGATE', index, query]; + + if (options?.VERBATIM) { + args.push('VERBATIM'); + } + + if (options?.LOAD) { + args.push('LOAD'); + pushArgumentsWithLength(args, () => { + if (Array.isArray(options.LOAD)) { + for (const load of options.LOAD) { + pushLoadField(args, load); + } + } else { + pushLoadField(args, options.LOAD!); + } + }); + } + + if (options?.STEPS) { + for (const step of options.STEPS) { + switch (step.type) { + case AggregateSteps.GROUPBY: + args.push('GROUPBY'); + if (!step.properties) { + args.push('0'); + } else { + pushVerdictArgument(args, step.properties); + } + + if (Array.isArray(step.REDUCE)) { + for (const reducer of step.REDUCE) { + pushGroupByReducer(args, reducer); + } + } else { + pushGroupByReducer(args, step.REDUCE); + } + + break; + + case AggregateSteps.SORTBY: + pushSortByArguments(args, 'SORTBY', step.BY); + + if (step.MAX) { + args.push('MAX', step.MAX.toString()); + } + + break; + + case AggregateSteps.APPLY: + args.push('APPLY', step.expression, 'AS', step.AS); + break; + + case AggregateSteps.LIMIT: + args.push('LIMIT', step.from.toString(), step.size.toString()); + break; + + case AggregateSteps.FILTER: + args.push('FILTER', step.expression); + break; + } + } + } + + return args; +} + +function pushLoadField(args: RedisCommandArguments, toLoad: LoadField): void { + if (typeof toLoad === 'string') { + args.push(toLoad); + } else { + args.push(toLoad.identifier); + + if (toLoad.AS) { + args.push('AS', toLoad.AS); + } + } +} + +function pushGroupByReducer(args: RedisCommandArguments, reducer: GroupByReducers): void { + args.push('REDUCE', reducer.type); + + switch (reducer.type) { + case AggregateGroupByReducers.COUNT: + args.push('0'); + break; + + case AggregateGroupByReducers.COUNT_DISTINCT: + case AggregateGroupByReducers.COUNT_DISTINCTISH: + case AggregateGroupByReducers.SUM: + case AggregateGroupByReducers.MIN: + case AggregateGroupByReducers.MAX: + case AggregateGroupByReducers.AVG: + case AggregateGroupByReducers.STDDEV: + case AggregateGroupByReducers.TOLIST: + args.push('1', reducer.property); + break; + + case AggregateGroupByReducers.QUANTILE: + args.push('2', reducer.property, reducer.quantile.toString()); + break; + + case AggregateGroupByReducers.FIRST_VALUE: { + pushArgumentsWithLength(args, () => { + args.push(reducer.property); + + if (reducer.BY) { + args.push('BY'); + if (typeof reducer.BY === 'string') { + args.push(reducer.BY); + } else { + args.push(reducer.BY.property); + + if (reducer.BY.direction) { + args.push(reducer.BY.direction); + } + } + } + }); + + break; + } + + case AggregateGroupByReducers.RANDOM_SAMPLE: + args.push('2', reducer.property, reducer.sampleSize.toString()); + break; + } + + if (reducer.AS) { + args.push('AS', reducer.AS); + } +} + +type AggregateRawReply = [ + total: number, + ...results: Array> +]; + +interface AggregateReply { + total: number; + results: Array; +} + +export function transformReply(rawReply: AggregateRawReply): AggregateReply { + const results: Array = []; + for (let i = 1; i < rawReply.length; i++) { + results.push( + transformReplyTuples(rawReply[i] as Array) + ); + } + + return { + total: rawReply[0], + results + }; +} \ No newline at end of file diff --git a/packages/search/lib/commands/ALIASADD.spec.ts b/packages/search/lib/commands/ALIASADD.spec.ts new file mode 100644 index 00000000000..7bb2452838b --- /dev/null +++ b/packages/search/lib/commands/ALIASADD.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './ALIASADD'; + +describe('ALIASADD', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('alias', 'index'), + ['FT.ALIASADD', 'alias', 'index'] + ); + }); +}); diff --git a/packages/search/lib/commands/ALIASADD.ts b/packages/search/lib/commands/ALIASADD.ts new file mode 100644 index 00000000000..552c1add695 --- /dev/null +++ b/packages/search/lib/commands/ALIASADD.ts @@ -0,0 +1,5 @@ +export function transformArguments(name: string, index: string): Array { + return ['FT.ALIASADD', name, index]; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/ALIASDEL.spec.ts b/packages/search/lib/commands/ALIASDEL.spec.ts new file mode 100644 index 00000000000..5255ba835db --- /dev/null +++ b/packages/search/lib/commands/ALIASDEL.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './ALIASDEL'; + +describe('ALIASDEL', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('alias', 'index'), + ['FT.ALIASDEL', 'alias', 'index'] + ); + }); +}); diff --git a/packages/search/lib/commands/ALIASDEL.ts b/packages/search/lib/commands/ALIASDEL.ts new file mode 100644 index 00000000000..434b4df3dea --- /dev/null +++ b/packages/search/lib/commands/ALIASDEL.ts @@ -0,0 +1,5 @@ +export function transformArguments(name: string, index: string): Array { + return ['FT.ALIASDEL', name, index]; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/ALIASUPDATE.spec.ts b/packages/search/lib/commands/ALIASUPDATE.spec.ts new file mode 100644 index 00000000000..79421b1a20d --- /dev/null +++ b/packages/search/lib/commands/ALIASUPDATE.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './ALIASUPDATE'; + +describe('ALIASUPDATE', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('alias', 'index'), + ['FT.ALIASUPDATE', 'alias', 'index'] + ); + }); +}); diff --git a/packages/search/lib/commands/ALIASUPDATE.ts b/packages/search/lib/commands/ALIASUPDATE.ts new file mode 100644 index 00000000000..ac64ef57c3f --- /dev/null +++ b/packages/search/lib/commands/ALIASUPDATE.ts @@ -0,0 +1,5 @@ +export function transformArguments(name: string, index: string): Array { + return ['FT.ALIASUPDATE', name, index]; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/CONFIG_GET.spec.ts b/packages/search/lib/commands/CONFIG_GET.spec.ts new file mode 100644 index 00000000000..8614f443426 --- /dev/null +++ b/packages/search/lib/commands/CONFIG_GET.spec.ts @@ -0,0 +1,25 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './CONFIG_GET'; + +describe('CONFIG GET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('TIMEOUT'), + ['FT.CONFIG', 'GET', 'TIMEOUT'] + ); + }); + + testUtils.testWithClient('client.ft.configGet', async client => { + assert.deepEqual( + await client.ft.configGet('TIMEOUT'), + Object.create(null, { + TIMEOUT: { + value: '500', + configurable: true, + enumerable: true + } + }) + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/CONFIG_GET.ts b/packages/search/lib/commands/CONFIG_GET.ts new file mode 100644 index 00000000000..fbf1f1164b9 --- /dev/null +++ b/packages/search/lib/commands/CONFIG_GET.ts @@ -0,0 +1,16 @@ +export function transformArguments(option: string) { + return ['FT.CONFIG', 'GET', option]; +} + +interface ConfigGetReply { + [option: string]: string | null; +} + +export function transformReply(rawReply: Array<[string, string | null]>): ConfigGetReply { + const transformedReply: ConfigGetReply = Object.create(null); + for (const [key, value] of rawReply) { + transformedReply[key] = value; + } + + return transformedReply; +} diff --git a/packages/search/lib/commands/CONFIG_SET.spec.ts b/packages/search/lib/commands/CONFIG_SET.spec.ts new file mode 100644 index 00000000000..59cb63a3d8e --- /dev/null +++ b/packages/search/lib/commands/CONFIG_SET.spec.ts @@ -0,0 +1,12 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './CONFIG_SET'; + +describe('CONFIG SET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('TIMEOUT', '500'), + ['FT.CONFIG', 'SET', 'TIMEOUT', '500'] + ); + }); +}); diff --git a/packages/search/lib/commands/CONFIG_SET.ts b/packages/search/lib/commands/CONFIG_SET.ts new file mode 100644 index 00000000000..93b76d79edf --- /dev/null +++ b/packages/search/lib/commands/CONFIG_SET.ts @@ -0,0 +1,5 @@ +export function transformArguments(option: string, value: string): Array { + return ['FT.CONFIG', 'SET', option, value]; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts new file mode 100644 index 00000000000..5bdf4c93a43 --- /dev/null +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -0,0 +1,350 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes, SchemaTextFieldPhonetics, transformArguments } from './CREATE'; +import { RedisSearchLanguages } from '.'; + +describe('CREATE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('index', {}), + ['FT.CREATE', 'index', 'SCHEMA'] + ); + }); + + describe('with fields', () => { + describe('TEXT', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('index', { + field: SchemaFieldTypes.TEXT + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT'] + ); + }); + + it('with NOSTEM', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + NOSTEM: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOSTEM'] + ); + }); + + it('with WEIGHT', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + WEIGHT: 1 + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'WEIGHT', '1'] + ); + }); + + it('with PHONETIC', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + PHONETIC: SchemaTextFieldPhonetics.DM_EN + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'PHONETIC', SchemaTextFieldPhonetics.DM_EN] + ); + }); + }); + + it('NUMERIC', () => { + assert.deepEqual( + transformArguments('index', { + field: SchemaFieldTypes.NUMERIC + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'NUMERIC'] + ); + }); + + it('GEO', () => { + assert.deepEqual( + transformArguments('index', { + field: SchemaFieldTypes.GEO + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEO'] + ); + }); + + describe('TAG', () => { + describe('without options', () => { + it('SchemaFieldTypes.TAG', () => { + assert.deepEqual( + transformArguments('index', { + field: SchemaFieldTypes.TAG + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG'] + ); + }); + + it('{ type: SchemaFieldTypes.TAG }', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TAG + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG'] + ); + }); + }); + + it('with SEPERATOR', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TAG, + SEPERATOR: 'seperator' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'SEPERATOR', 'seperator'] + ); + }); + + + + it('with CASESENSITIVE', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TAG, + CASESENSITIVE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'CASESENSITIVE'] + ); + }); + }); + + describe('with generic options', () => { + it('with AS', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + AS: 'as' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'AS', 'as', 'TEXT'] + ); + }); + + describe('with SORTABLE', () => { + it('true', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + SORTABLE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE'] + ); + }); + + it('UNF', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + SORTABLE: 'UNF' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE', 'UNF'] + ); + }); + }); + + it('with NOINDEX', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + NOINDEX: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOINDEX'] + ); + }); + }); + }); + + it('with ON', () => { + assert.deepEqual( + transformArguments('index', {}, { + ON: 'HASH' + }), + ['FT.CREATE', 'index', 'ON', 'HASH', 'SCHEMA'] + ); + }); + + describe('with PREFIX', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', {}, { + PREFIX: 'prefix' + }), + ['FT.CREATE', 'index', 'PREFIX', '1', 'prefix', 'SCHEMA'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('index', {}, { + PREFIX: ['1', '2'] + }), + ['FT.CREATE', 'index', 'PREFIX', '2', '1', '2', 'SCHEMA'] + ); + }); + }); + + it('with FILTER', () => { + assert.deepEqual( + transformArguments('index', {}, { + FILTER: '@field != ""' + }), + ['FT.CREATE', 'index', 'FILTER', '@field != ""', 'SCHEMA'] + ); + }); + + it('with LANGUAGE', () => { + assert.deepEqual( + transformArguments('index', {}, { + LANGUAGE: RedisSearchLanguages.ARABIC + }), + ['FT.CREATE', 'index', 'LANGUAGE', RedisSearchLanguages.ARABIC, 'SCHEMA'] + ); + }); + + it('with LANGUAGE_FIELD', () => { + assert.deepEqual( + transformArguments('index', {}, { + LANGUAGE_FIELD: '@field' + }), + ['FT.CREATE', 'index', 'LANGUAGE_FIELD', '@field', 'SCHEMA'] + ); + }); + + it('with SCORE', () => { + assert.deepEqual( + transformArguments('index', {}, { + SCORE: 1 + }), + ['FT.CREATE', 'index', 'SCORE', '1', 'SCHEMA'] + ); + }); + + it('with SCORE_FIELD', () => { + assert.deepEqual( + transformArguments('index', {}, { + SCORE_FIELD: '@field' + }), + ['FT.CREATE', 'index', 'SCORE_FIELD', '@field', 'SCHEMA'] + ); + }); + + it('with MAXTEXTFIELDS', () => { + assert.deepEqual( + transformArguments('index', {}, { + MAXTEXTFIELDS: true + }), + ['FT.CREATE', 'index', 'MAXTEXTFIELDS', 'SCHEMA'] + ); + }); + + it('with TEMPORARY', () => { + assert.deepEqual( + transformArguments('index', {}, { + TEMPORARY: 1 + }), + ['FT.CREATE', 'index', 'TEMPORARY', '1', 'SCHEMA'] + ); + }); + + it('with NOOFFSETS', () => { + assert.deepEqual( + transformArguments('index', {}, { + NOOFFSETS: true + }), + ['FT.CREATE', 'index', 'NOOFFSETS', 'SCHEMA'] + ); + }); + + it('with NOHL', () => { + assert.deepEqual( + transformArguments('index', {}, { + NOHL: true + }), + ['FT.CREATE', 'index', 'NOHL', 'SCHEMA'] + ); + }); + + it('with NOFIELDS', () => { + assert.deepEqual( + transformArguments('index', {}, { + NOFIELDS: true + }), + ['FT.CREATE', 'index', 'NOFIELDS', 'SCHEMA'] + ); + }); + + it('with NOFREQS', () => { + assert.deepEqual( + transformArguments('index', {}, { + NOFREQS: true + }), + ['FT.CREATE', 'index', 'NOFREQS', 'SCHEMA'] + ); + }); + + it('with SKIPINITIALSCAN', () => { + assert.deepEqual( + transformArguments('index', {}, { + SKIPINITIALSCAN: true + }), + ['FT.CREATE', 'index', 'SKIPINITIALSCAN', 'SCHEMA'] + ); + }); + + describe('with STOPWORDS', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', {}, { + STOPWORDS: 'stopword' + }), + ['FT.CREATE', 'index', 'STOPWORDS', '1', 'stopword', 'SCHEMA'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('index', {}, { + STOPWORDS: ['1', '2'] + }), + ['FT.CREATE', 'index', 'STOPWORDS', '2', '1', '2', 'SCHEMA'] + ); + }); + }); + }); + + testUtils.testWithClient('client.ft.create', async client => { + assert.equal( + await client.ft.create('index', { + field: SchemaFieldTypes.TEXT // TODO: shouldn't be mandatory + }), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts new file mode 100644 index 00000000000..1a5e45a4a88 --- /dev/null +++ b/packages/search/lib/commands/CREATE.ts @@ -0,0 +1,194 @@ +import { pushOptionalVerdictArgument } from '@node-redis/client/dist/lib/commands/generic-transformers'; +import { RedisSearchLanguages, PropertyName } from '.'; + +export enum SchemaFieldTypes { + TEXT = 'TEXT', + NUMERIC = 'NUMERIC', + GEO = 'GEO', + TAG = 'TAG' +} + +type CreateSchemaField> = T | ({ + type: T; + AS?: string; + SORTABLE?: true | 'UNF'; + NOINDEX?: true; +} & E); + +export enum SchemaTextFieldPhonetics { + DM_EN = 'dm:en', + DM_FR = 'dm:fr', + FM_PT = 'dm:pt', + DM_ES = 'dm:es' +} + +type CreateSchemaTextField = CreateSchemaField; + +type CreateSchemaNumericField = CreateSchemaField; + +type CreateSchemaGeoField = CreateSchemaField; + +type CreateSchemaTagField = CreateSchemaField; + +interface CreateSchema { + [field: string]: + CreateSchemaTextField | + CreateSchemaNumericField | + CreateSchemaGeoField | + CreateSchemaTagField +} + +interface CreateOptions { + ON?: 'HASH' | 'JSON'; + PREFIX?: string | Array; + FILTER?: string; + LANGUAGE?: RedisSearchLanguages; + LANGUAGE_FIELD?: PropertyName; + SCORE?: number; + SCORE_FIELD?: PropertyName; + // PAYLOAD_FIELD?: string; + MAXTEXTFIELDS?: true; + TEMPORARY?: number; + NOOFFSETS?: true; + NOHL?: true; + NOFIELDS?: true; + NOFREQS?: true; + SKIPINITIALSCAN?: true; + STOPWORDS?: string | Array; +} + +export function transformArguments(index: string, schema: CreateSchema, options?: CreateOptions): Array { + const args = ['FT.CREATE', index]; + + if (options?.ON) { + args.push('ON', options.ON); + } + + pushOptionalVerdictArgument(args, 'PREFIX', options?.PREFIX); + + if (options?.FILTER) { + args.push('FILTER', options.FILTER); + } + + if (options?.LANGUAGE) { + args.push('LANGUAGE', options.LANGUAGE); + } + + if (options?.LANGUAGE_FIELD) { + args.push('LANGUAGE_FIELD', options.LANGUAGE_FIELD); + } + + if (options?.SCORE) { + args.push('SCORE', options.SCORE.toString()); + } + + if (options?.SCORE_FIELD) { + args.push('SCORE_FIELD', options.SCORE_FIELD); + } + + // if (options?.PAYLOAD_FIELD) { + // args.push('PAYLOAD_FIELD', options.PAYLOAD_FIELD); + // } + + if (options?.MAXTEXTFIELDS) { + args.push('MAXTEXTFIELDS'); + } + + if (options?.TEMPORARY) { + args.push('TEMPORARY', options.TEMPORARY.toString()); + } + + if (options?.NOOFFSETS) { + args.push('NOOFFSETS'); + } + + if (options?.NOHL) { + args.push('NOHL'); + } + + if (options?.NOFIELDS) { + args.push('NOFIELDS'); + } + + if (options?.NOFREQS) { + args.push('NOFREQS'); + } + + if (options?.SKIPINITIALSCAN) { + args.push('SKIPINITIALSCAN'); + } + + pushOptionalVerdictArgument(args, 'STOPWORDS', options?.STOPWORDS); + + args.push('SCHEMA'); + + for (const [field, fieldOptions] of Object.entries(schema)) { + args.push(field); + + if (typeof fieldOptions === 'string') { + args.push(fieldOptions); + continue; + } + + if (fieldOptions.AS) { + args.push('AS', fieldOptions.AS); + } + + args.push(fieldOptions.type); + + switch (fieldOptions.type) { + case 'TEXT': + if (fieldOptions.NOSTEM) { + args.push('NOSTEM'); + } + + if (fieldOptions.WEIGHT) { + args.push('WEIGHT', fieldOptions.WEIGHT.toString()); + } + + if (fieldOptions.PHONETIC) { + args.push('PHONETIC', fieldOptions.PHONETIC); + } + + break; + + // case 'NUMERIC': + // case 'GEO': + // break; + + case 'TAG': + if (fieldOptions.SEPERATOR) { + args.push('SEPERATOR', fieldOptions.SEPERATOR); + } + + if (fieldOptions.CASESENSITIVE) { + args.push('CASESENSITIVE'); + } + + break; + } + + if (fieldOptions.SORTABLE) { + args.push('SORTABLE'); + + if (fieldOptions.SORTABLE === 'UNF') { + args.push('UNF'); + } + } + + if (fieldOptions.NOINDEX) { + args.push('NOINDEX'); + } + } + + return args; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/DICTADD.spec.ts b/packages/search/lib/commands/DICTADD.spec.ts new file mode 100644 index 00000000000..b5f29dd4083 --- /dev/null +++ b/packages/search/lib/commands/DICTADD.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './DICTADD'; + +describe('DICTADD', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('dictionary', 'term'), + ['FT.DICTADD', 'dictionary', 'term'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('dictionary', ['1', '2']), + ['FT.DICTADD', 'dictionary', '1', '2'] + ); + }); + }); + + testUtils.testWithClient('client.ft.dictAdd', async client => { + assert.equal( + await client.ft.dictAdd('dictionary', 'term'), + 1 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/DICTADD.ts b/packages/search/lib/commands/DICTADD.ts new file mode 100644 index 00000000000..b3f993395fa --- /dev/null +++ b/packages/search/lib/commands/DICTADD.ts @@ -0,0 +1,8 @@ +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; +import { pushVerdictArguments } from '@node-redis/client/dist/lib/commands/generic-transformers'; + +export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { + return pushVerdictArguments(['FT.DICTADD', dictionary], term); +} + +export declare function transformReply(): number; diff --git a/packages/search/lib/commands/DICTDEL.spec.ts b/packages/search/lib/commands/DICTDEL.spec.ts new file mode 100644 index 00000000000..5ffa6b6b84f --- /dev/null +++ b/packages/search/lib/commands/DICTDEL.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './DICTDEL'; + +describe('DICTDEL', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('dictionary', 'term'), + ['FT.DICTDEL', 'dictionary', 'term'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('dictionary', ['1', '2']), + ['FT.DICTDEL', 'dictionary', '1', '2'] + ); + }); + }); + + testUtils.testWithClient('client.ft.dictDel', async client => { + assert.equal( + await client.ft.dictDel('dictionary', 'term'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/DICTDEL.ts b/packages/search/lib/commands/DICTDEL.ts new file mode 100644 index 00000000000..bd047a5031d --- /dev/null +++ b/packages/search/lib/commands/DICTDEL.ts @@ -0,0 +1,8 @@ +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; +import { pushVerdictArguments } from '@node-redis/client/dist/lib/commands/generic-transformers'; + +export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { + return pushVerdictArguments(['FT.DICTDEL', dictionary], term); +} + +export declare function transformReply(): number; diff --git a/packages/search/lib/commands/DICTDUMP.spec.ts b/packages/search/lib/commands/DICTDUMP.spec.ts new file mode 100644 index 00000000000..9896fb9440d --- /dev/null +++ b/packages/search/lib/commands/DICTDUMP.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './DICTDUMP'; + +describe('DICTDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('dictionary'), + ['FT.DICTDUMP', 'dictionary'] + ); + }); + + testUtils.testWithClient('client.ft.dictDump', async client => { + await client.ft.dictAdd('dictionary', 'string') + + assert.deepEqual( + await client.ft.dictDump('dictionary'), + ['string'] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/DICTDUMP.ts b/packages/search/lib/commands/DICTDUMP.ts new file mode 100644 index 00000000000..1427bb42cb7 --- /dev/null +++ b/packages/search/lib/commands/DICTDUMP.ts @@ -0,0 +1,5 @@ +export function transformArguments(dictionary: string): Array { + return ['FT.DICTDUMP', dictionary]; +} + +export declare function transformReply(): Array; diff --git a/packages/search/lib/commands/DROPINDEX.spec.ts b/packages/search/lib/commands/DROPINDEX.spec.ts new file mode 100644 index 00000000000..751e274ba60 --- /dev/null +++ b/packages/search/lib/commands/DROPINDEX.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes } from './CREATE'; +import { transformArguments } from './DROPINDEX'; + +describe('DROPINDEX', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('index'), + ['FT.DROPINDEX', 'index'] + ); + }); + + it('with DD', () => { + assert.deepEqual( + transformArguments('index', { DD: true }), + ['FT.DROPINDEX', 'index', 'DD'] + ); + }); + }); + + testUtils.testWithClient('client.ft.dropIndex', async client => { + await client.ft.create('index', { + field: SchemaFieldTypes.TEXT // TODO: shouldn't be mandatory + }); + + assert.equal( + await client.ft.dropIndex('index'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/DROPINDEX.ts b/packages/search/lib/commands/DROPINDEX.ts new file mode 100644 index 00000000000..7897a9dd82e --- /dev/null +++ b/packages/search/lib/commands/DROPINDEX.ts @@ -0,0 +1,15 @@ +interface DropIndexOptions { + DD?: true; +} + +export function transformArguments(index: string, options?: DropIndexOptions): Array { + const args = ['FT.DROPINDEX', index]; + + if (options?.DD) { + args.push('DD'); + } + + return args; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/EXPLAIN.spec.ts b/packages/search/lib/commands/EXPLAIN.spec.ts new file mode 100644 index 00000000000..dd55e038710 --- /dev/null +++ b/packages/search/lib/commands/EXPLAIN.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './EXPLAIN'; + +describe('EXPLAIN', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('index', '*'), + ['FT.EXPLAIN', 'index', '*'] + ); + }); +}); diff --git a/packages/search/lib/commands/EXPLAIN.ts b/packages/search/lib/commands/EXPLAIN.ts new file mode 100644 index 00000000000..c41cd9a4aac --- /dev/null +++ b/packages/search/lib/commands/EXPLAIN.ts @@ -0,0 +1,7 @@ +export const IS_READ_ONLY = true; + +export function transformArguments(index: string, query: string): Array { + return ['FT.EXPLAIN', index, query]; +} + +export declare function transformReply(): string; diff --git a/packages/search/lib/commands/EXPLAINCLI.spec.ts b/packages/search/lib/commands/EXPLAINCLI.spec.ts new file mode 100644 index 00000000000..238ef44eaaa --- /dev/null +++ b/packages/search/lib/commands/EXPLAINCLI.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'assert'; +import { transformArguments } from './EXPLAINCLI'; + +describe('EXPLAINCLI', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('index', '*'), + ['FT.EXPLAINCLI', 'index', '*'] + ); + }); +}); diff --git a/packages/search/lib/commands/EXPLAINCLI.ts b/packages/search/lib/commands/EXPLAINCLI.ts new file mode 100644 index 00000000000..db97fb9c8da --- /dev/null +++ b/packages/search/lib/commands/EXPLAINCLI.ts @@ -0,0 +1,7 @@ +export const IS_READ_ONLY = true; + +export function transformArguments(index: string, query: string): Array { + return ['FT.EXPLAINCLI', index, query]; +} + +export declare function transformReply(): Array; diff --git a/packages/search/lib/commands/INFO.spec.ts b/packages/search/lib/commands/INFO.spec.ts new file mode 100644 index 00000000000..fa50a4b0cd8 --- /dev/null +++ b/packages/search/lib/commands/INFO.spec.ts @@ -0,0 +1,65 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes } from './CREATE'; +import { transformArguments } from './INFO'; + +describe('INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('index'), + ['FT.INFO', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.info', async client => { + await client.ft.create('index', {}, { + ON: 'HASH' // TODO: shouldn't be mandatory + }); + + assert.deepEqual( + await client.ft.info('index'), + { + indexName: 'index', + indexOptions: [], + indexDefinition: { + defaultScore: '1', + keyType: 'HASH', + prefixes: [''] + }, + attributes: [], + numDocs: '0', + maxDocId: '0', + numTerms: '0', + numRecords: '0', + invertedSzMb: '0', + totalInvertedIndexBlocks: '0', + offsetVectorsSzMb: '0', + docTableSizeMb: '0', + sortableValuesSizeMb: '0', + keyTableSizeMb: '0', + recordsPerDocAvg: '-nan', + bytesPerRecordAvg: '-nan', + offsetsPerTermAvg: '-nan', + offsetBitsPerRecordAvg: '-nan', + hashIndexingFailures: '0', + indexing: '0', + percentIndexed: '1', + gcStats: { + bytesCollected: '0', + totalMsRun: '0', + totalCycles: '0', + averageCycleTimeMs: '-nan', + lastRunTimeMs: '0', + gcNumericTreesMissed: '0', + gcBlocksDenied: '0' + }, + cursorStats: { + globalIdle: 0, + globalTotal: 0, + indexCapacity: 128, + idnexTotal: 0 + } + } + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/INFO.ts b/packages/search/lib/commands/INFO.ts new file mode 100644 index 00000000000..42451114c89 --- /dev/null +++ b/packages/search/lib/commands/INFO.ts @@ -0,0 +1,171 @@ +export function transformArguments(index: string): Array { + return ['FT.INFO', index]; +} + +type InfoRawReply = [ + _: string, + indexName: string, + _: string, + indexOptions: Array, + _: string, + indexDefinition: [ + _: string, + keyType: string, + _: string, + prefixes: Array, + _: string, + defaultScore: string + ], + _: string, + attributes: Array>, + _: string, + numDocs: string, + _: string, + maxDocId: string, + _: string, + numTerms: string, + _: string, + numRecords: string, + _: string, + invertedSzMb: string, + _: string, + totalInvertedIndexBlocks: string, + _: string, + offsetVectorsSzMb: string, + _: string, + docTableSizeMb: string, + _: string, + sortableValuesSizeMb: string, + _: string, + keyTableSizeMb: string, + _: string, + recordsPerDocAvg: string, + _: string, + bytesPerRecordAvg: string, + _: string, + offsetsPerTermAvg: string, + _: string, + offsetBitsPerRecordAvg: string, + _: string, + hashIndexingFailures: string, + _: string, + indexing: string, + _: string, + percentIndexed: string, + _: string, + gcStats: [ + _: string, + bytesCollected: string, + _: string, + totalMsRun: string, + _: string, + totalCycles: string, + _: string, + averageCycleTimeMs: string, + _: string, + lastRunTimeMs: string, + _: string, + gcNumericTreesMissed: string, + _: string, + gcBlocksDenied: string + ], + _: string, + cursorStats: [ + _: string, + globalIdle: number, + _: string, + globalTotal: number, + _: string, + indexCapacity: number, + _: string, + idnexTotal: number + ] +]; + +interface InfoReply { + indexName: string; + indexOptions: Array; + indexDefinition: { + keyType: string; + prefixes: Array; + defaultScore: string; + }; + attributes: Array>; + numDocs: string; + maxDocId: string; + numTerms: string; + numRecords: string; + invertedSzMb: string; + totalInvertedIndexBlocks: string; + offsetVectorsSzMb: string; + docTableSizeMb: string; + sortableValuesSizeMb: string; + keyTableSizeMb: string; + recordsPerDocAvg: string; + bytesPerRecordAvg: string; + offsetsPerTermAvg: string; + offsetBitsPerRecordAvg: string; + hashIndexingFailures: string; + indexing: string; + percentIndexed: string; + gcStats: { + bytesCollected: string; + totalMsRun: string; + totalCycles: string; + averageCycleTimeMs: string; + lastRunTimeMs: string; + gcNumericTreesMissed: string; + gcBlocksDenied: string; + }; + cursorStats: { + globalIdle: number; + globalTotal: number; + indexCapacity: number; + idnexTotal: number; + }; +} + +export function transformReply(rawReply: InfoRawReply): InfoReply { + return { + indexName: rawReply[1], + indexOptions: rawReply[3], + indexDefinition: { + keyType: rawReply[5][1], + prefixes: rawReply[5][3], + defaultScore: rawReply[5][5] + }, + attributes: rawReply[7], + numDocs: rawReply[9], + maxDocId: rawReply[11], + numTerms: rawReply[13], + numRecords: rawReply[15], + invertedSzMb: rawReply[17], + totalInvertedIndexBlocks: rawReply[19], + offsetVectorsSzMb: rawReply[21], + docTableSizeMb: rawReply[23], + sortableValuesSizeMb: rawReply[25], + keyTableSizeMb: rawReply[27], + recordsPerDocAvg: rawReply[29], + bytesPerRecordAvg: rawReply[31], + offsetsPerTermAvg: rawReply[33], + offsetBitsPerRecordAvg: rawReply[35], + hashIndexingFailures: rawReply[37], + indexing: rawReply[39], + percentIndexed: rawReply[41], + gcStats: { + bytesCollected: rawReply[43][1], + totalMsRun: rawReply[43][3], + totalCycles: rawReply[43][5], + averageCycleTimeMs: rawReply[43][7], + lastRunTimeMs: rawReply[43][9], + gcNumericTreesMissed: rawReply[43][11], + gcBlocksDenied: rawReply[43][13] + }, + cursorStats: { + globalIdle: rawReply[45][1], + globalTotal: rawReply[45][3], + indexCapacity: rawReply[45][5], + idnexTotal: rawReply[45][7] + } + }; +} diff --git a/packages/search/lib/commands/PROFILE.ts b/packages/search/lib/commands/PROFILE.ts new file mode 100644 index 00000000000..e315ea52304 --- /dev/null +++ b/packages/search/lib/commands/PROFILE.ts @@ -0,0 +1,26 @@ +export const IS_READ_ONLY = true; + +interface ProfileOptions { + LIMITED?: true; +} + +export function transformArguments( + index: string, + type: 'SEARCH' | 'AGGREGATE', + query: string, + options?: ProfileOptions +): Array { + const args = ['FT.PROFILE', index, type]; + + if (options?.LIMITED) { + args.push('LIMITED'); + } + + args.push('QUERY', query); + + return args; +} + +export function transformReply() { + +} diff --git a/packages/search/lib/commands/SEARCH.spec.ts b/packages/search/lib/commands/SEARCH.spec.ts new file mode 100644 index 00000000000..15dc4740948 --- /dev/null +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -0,0 +1,244 @@ +import { strict as assert } from 'assert'; +import { RedisSearchLanguages } from '.'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes } from './CREATE'; +import { transformArguments } from './SEARCH'; + +describe('SEARCH', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('index', 'query'), + ['FT.SEARCH', 'index', 'query'] + ); + }); + + it('with VERBATIM', () => { + assert.deepEqual( + transformArguments('index', 'query', { VERBATIM: true }), + ['FT.SEARCH', 'index', 'query', 'VERBATIM'] + ); + }); + + it('with NOSTOPWORDS', () => { + assert.deepEqual( + transformArguments('index', 'query', { NOSTOPWORDS: true }), + ['FT.SEARCH', 'index', 'query', 'NOSTOPWORDS'] + ); + }); + + it('with INKEYS', () => { + assert.deepEqual( + transformArguments('index', 'query', { INKEYS: 'key' }), + ['FT.SEARCH', 'index', 'query', 'INKEYS', '1', 'key'] + ); + }); + + it('with INFIELDS', () => { + assert.deepEqual( + transformArguments('index', 'query', { INFIELDS: 'field' }), + ['FT.SEARCH', 'index', 'query', 'INFIELDS', '1', 'field'] + ); + }); + + it('with RETURN', () => { + assert.deepEqual( + transformArguments('index', 'query', { RETURN: 'return' }), + ['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return'] + ); + }); + + describe('with SUMMARIZE', () => { + it('true', () => { + assert.deepEqual( + transformArguments('index', 'query', { SUMMARIZE: true }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE'] + ); + }); + + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: ['@field'] + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '1', '@field'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '2', '@1', '@2'] + ); + }); + }); + + it('with FRAGS', () => { + assert.deepEqual( + transformArguments('index', 'query', { + SUMMARIZE: { + FRAGS: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FRAGS', '1'] + ); + }); + + it('with LEN', () => { + assert.deepEqual( + transformArguments('index', 'query', { + SUMMARIZE: { + LEN: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'LEN', '1'] + ); + }); + + it('with SEPARATOR', () => { + assert.deepEqual( + transformArguments('index', 'query', { + SUMMARIZE: { + SEPARATOR: 'separator' + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'SEPARATOR', 'separator'] + ); + }); + }); + + describe('with HIGHLIGHT', () => { + it('true', () => { + assert.deepEqual( + transformArguments('index', 'query', { HIGHLIGHT: true }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT'] + ); + }); + + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@field'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '1', '@field'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '2', '@1', '@2'] + ); + }); + }); + + it('with TAGS', () => { + assert.deepEqual( + transformArguments('index', 'query', { + HIGHLIGHT: { + TAGS: { + open: 'open', + close: 'close' + } + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'TAGS', 'open', 'close'] + ); + }); + }); + + it('with SLOP', () => { + assert.deepEqual( + transformArguments('index', 'query', { SLOP: 1 }), + ['FT.SEARCH', 'index', 'query', 'SLOP', '1'] + ); + }); + + it('with INORDER', () => { + assert.deepEqual( + transformArguments('index', 'query', { INORDER: true }), + ['FT.SEARCH', 'index', 'query', 'INORDER'] + ); + }); + + it('with LANGUAGE', () => { + assert.deepEqual( + transformArguments('index', 'query', { LANGUAGE: RedisSearchLanguages.ARABIC }), + ['FT.SEARCH', 'index', 'query', 'LANGUAGE', RedisSearchLanguages.ARABIC] + ); + }); + + it('with EXPANDER', () => { + assert.deepEqual( + transformArguments('index', 'query', { EXPANDER: 'expender' }), + ['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender'] + ); + }); + + it('with SCORER', () => { + assert.deepEqual( + transformArguments('index', 'query', { SCORER: 'scorer' }), + ['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer'] + ); + }); + + it('with MSORTBY', () => { + assert.deepEqual( + transformArguments('index', 'query', { MSORTBY: '@by' }), + ['FT.SEARCH', 'index', 'query', 'MSORTBY', '1', '@by'] + ); + }); + + it('with LIMIT', () => { + assert.deepEqual( + transformArguments('index', 'query', { + LIMIT: { + from: 0, + size: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'LIMIT', '0', '1'] + ); + }); + }); + + testUtils.testWithClient('client.ft.search', async client => { + await Promise.all([ + client.ft.create('index', { + field: SchemaFieldTypes.NUMERIC + }), + client.hSet('1', 'field', '1') + ]); + + assert.deepEqual( + await client.ft.search('index', '*'), + { + total: 1, + documents: [{ + id: '1', + value: Object.create(null, { + field: { + value: '1', + configurable: true, + enumerable: true + } + }) + }] + } + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SEARCH.ts b/packages/search/lib/commands/SEARCH.ts new file mode 100644 index 00000000000..9616bfa0bee --- /dev/null +++ b/packages/search/lib/commands/SEARCH.ts @@ -0,0 +1,200 @@ +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; +import { pushOptionalVerdictArgument, pushVerdictArgument, transformReplyTuples } from '@node-redis/client/dist/lib/commands/generic-transformers'; +import { RedisSearchLanguages, PropertyName, pushSortByArguments, SortByOptions } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +interface SearchOptions { + // NOCONTENT?: true; TODO + VERBATIM?: true; + NOSTOPWORDS?: true; + // WITHSCORES?: true; + // WITHPAYLOADS?: true; + WITHSORTKEYS?: true; + // FILTER?: { + // field: string; + // min: number | string; + // max: number | string; + // }; + // GEOFILTER?: { + // field: string; + // lon: number; + // lat: number; + // radius: number; + // unit: 'm' | 'km' | 'mi' | 'ft'; + // }; + INKEYS?: string | Array; + INFIELDS?: string | Array; + RETURN?: string | Array; + SUMMARIZE?: true | { + FIELDS?: PropertyName | Array; + FRAGS?: number; + LEN?: number; + SEPARATOR?: string; + }; + HIGHLIGHT?: true | { + FIELDS?: PropertyName | Array; + TAGS?: { + open: string; + close: string; + }; + }; + SLOP?: number; + INORDER?: true; + LANGUAGE?: RedisSearchLanguages; + EXPANDER?: string; + SCORER?: string; + // EXPLAINSCORE?: true; // TODO: WITHSCORES + // PAYLOAD?: ; + // SORTBY?: SortByOptions; + MSORTBY?: SortByOptions | Array; + LIMIT?: { + from: number | string; + size: number | string; + }; +} + +export function transformArguments( + index: string, + query: string, + options?: SearchOptions +): RedisCommandArguments { + const args: RedisCommandArguments = ['FT.SEARCH', index, query]; + + if (options?.VERBATIM) { + args.push('VERBATIM'); + } + + if (options?.NOSTOPWORDS) { + args.push('NOSTOPWORDS'); + } + + // if (options?.WITHSCORES) { + // args.push('WITHSCORES'); + // } + + // if (options?.WITHPAYLOADS) { + // args.push('WITHPAYLOADS'); + // } + + pushOptionalVerdictArgument(args, 'INKEYS', options?.INKEYS); + pushOptionalVerdictArgument(args, 'INFIELDS', options?.INFIELDS); + pushOptionalVerdictArgument(args, 'RETURN', options?.RETURN); + + if (options?.SUMMARIZE) { + args.push('SUMMARIZE'); + + if (typeof options.SUMMARIZE === 'object') { + if (options.SUMMARIZE.FIELDS) { + args.push('FIELDS'); + pushVerdictArgument(args, options.SUMMARIZE.FIELDS); + } + + if (options.SUMMARIZE.FRAGS) { + args.push('FRAGS', options.SUMMARIZE.FRAGS.toString()); + } + + if (options.SUMMARIZE.LEN) { + args.push('LEN', options.SUMMARIZE.LEN.toString()); + } + + if (options.SUMMARIZE.SEPARATOR) { + args.push('SEPARATOR', options.SUMMARIZE.SEPARATOR); + } + } + } + + if (options?.HIGHLIGHT) { + args.push('HIGHLIGHT'); + + if (typeof options.HIGHLIGHT === 'object') { + if (options.HIGHLIGHT.FIELDS) { + args.push('FIELDS'); + pushVerdictArgument(args, options.HIGHLIGHT.FIELDS); + } + + if (options.HIGHLIGHT.TAGS) { + args.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close); + } + } + } + + if (options?.SLOP) { + args.push('SLOP', options.SLOP.toString()); + } + + if (options?.INORDER) { + args.push('INORDER'); + } + + if (options?.LANGUAGE) { + args.push('LANGUAGE', options.LANGUAGE); + } + + if (options?.EXPANDER) { + args.push('EXPANDER', options.EXPANDER); + } + + if (options?.SCORER) { + args.push('SCORER', options.SCORER); + } + + // if (options?.EXPLAINSCORE) { + // args.push('EXPLAINSCORE'); + // } + + // if (options?.PAYLOAD) { + // args.push('PAYLOAD', options.PAYLOAD); + // } + + // if (options?.SORTBY) { + // args.push('SORTBY'); + // pushSortByArguments(args, options.SORTBY); + // } + + if (options?.MSORTBY) { + pushSortByArguments(args, 'MSORTBY', options.MSORTBY); + } + + if (options?.LIMIT) { + args.push( + 'LIMIT', + options.LIMIT.from.toString(), + options.LIMIT.size.toString() + ); + } + + return args; +} + +interface SearchDocumentValue { + [key: string]: string | number | null | Array | SearchDocumentValue; +} + +interface SearchReply { + total: number; + documents: Array<{ + id: string; + value: SearchDocumentValue; + }>; +} + +export function transformReply(reply: Array): SearchReply { + const documents = []; + for (let i = 1; i < reply.length; i += 2) { + const tuples = reply[i + 1]; + documents.push({ + id: reply[i], + value: tuples.length === 2 && tuples[0] === '$' ? + JSON.parse(tuples[1]) : + transformReplyTuples(tuples) + }); + } + + return { + total: reply[0], + documents + }; +} diff --git a/packages/search/lib/commands/SPELLCHECK.spec.ts b/packages/search/lib/commands/SPELLCHECK.spec.ts new file mode 100644 index 00000000000..bacbe118b38 --- /dev/null +++ b/packages/search/lib/commands/SPELLCHECK.spec.ts @@ -0,0 +1,71 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes } from './CREATE'; +import { transformArguments } from './SPELLCHECK'; + +describe('SPELLCHECK', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('index', 'query'), + ['FT.SPELLCHECK', 'index', 'query'] + ); + }); + + it('with DISTANCE', () => { + assert.deepEqual( + transformArguments('index', 'query', { DISTANCE: 2 }), + ['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2'] + ); + }); + + describe('with TERMS', () => { + it('single', () => { + assert.deepEqual( + transformArguments('index', 'query', { + TERMS: { + mode: 'INCLUDE', + dictionary: 'dictionary' + } + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary'] + ); + }); + + it('multiple', () => { + assert.deepEqual( + transformArguments('index', 'query', { + TERMS: [{ + mode: 'INCLUDE', + dictionary: 'include' + }, { + mode: 'EXCLUDE', + dictionary: 'exclude' + }] + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude'] + ); + }); + }); + }); + + testUtils.testWithClient('client.ft.spellCheck', async client => { + await Promise.all([ + client.ft.create('index', { + field: SchemaFieldTypes.TEXT + }), + client.hSet('key', 'field', 'query') + ]); + + assert.deepEqual( + await client.ft.spellCheck('index', 'quer'), + [{ + term: 'quer', + suggestions: [{ + score: 1, + suggestion: 'query' + }] + }] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SPELLCHECK.ts b/packages/search/lib/commands/SPELLCHECK.ts new file mode 100644 index 00000000000..ae4cb3cdce1 --- /dev/null +++ b/packages/search/lib/commands/SPELLCHECK.ts @@ -0,0 +1,57 @@ +interface SpellCheckTerms { + mode: 'INCLUDE' | 'EXCLUDE'; + dictionary: string; +} + +interface SpellCheckOptions { + DISTANCE?: number; + TERMS?: SpellCheckTerms | Array; +} + +export function transformArguments(index: string, query: string, options?: SpellCheckOptions): Array { + const args = ['FT.SPELLCHECK', index, query]; + + if (options?.DISTANCE) { + args.push('DISTANCE', options.DISTANCE.toString()); + } + + if (options?.TERMS) { + if (Array.isArray(options.TERMS)) { + for (const term of options.TERMS) { + pushTerms(args, term); + } + } else { + pushTerms(args, options.TERMS); + } + } + + return args; +} + +function pushTerms(args: Array, { mode, dictionary }: SpellCheckTerms): void { + args.push('TERMS', mode, dictionary); +} + +type SpellCheckRawReply = Array<[ + _: string, + term: string, + suggestions: Array<[score: string, suggestion: string]> +]>; + +type SpellCheckReply = Array<{ + term: string, + suggestions: Array<{ + score: number, + suggestion: string + }> +}>; + +export function transformReply(rawReply: SpellCheckRawReply): SpellCheckReply { + return rawReply.map(([, term, suggestions]) => ({ + term, + suggestions: suggestions.map(([score, suggestion]) => ({ + score: Number(score), + suggestion + })) + })); +} diff --git a/packages/search/lib/commands/SUGADD.spec.ts b/packages/search/lib/commands/SUGADD.spec.ts new file mode 100644 index 00000000000..23294eb4abd --- /dev/null +++ b/packages/search/lib/commands/SUGADD.spec.ts @@ -0,0 +1,35 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGADD'; + +describe('SUGADD', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('key', 'string', 1), + ['FT.SUGADD', 'key', 'string', '1'] + ); + }); + + it('with INCR', () => { + assert.deepEqual( + transformArguments('key', 'string', 1, { INCR: true }), + ['FT.SUGADD', 'key', 'string', '1', 'INCR'] + ); + }); + + it('with PAYLOAD', () => { + assert.deepEqual( + transformArguments('key', 'string', 1, { PAYLOAD: 'payload' }), + ['FT.SUGADD', 'key', 'string', '1', 'PAYLOAD', 'payload'] + ); + }); + }); + + testUtils.testWithClient('client.ft.sugAdd', async client => { + assert.equal( + await client.ft.sugAdd('key', 'string', 1), + 1 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SUGADD.ts b/packages/search/lib/commands/SUGADD.ts new file mode 100644 index 00000000000..d68f0d98841 --- /dev/null +++ b/packages/search/lib/commands/SUGADD.ts @@ -0,0 +1,20 @@ +interface SugAddOptions { + INCR?: true; + PAYLOAD?: string; +} + +export function transformArguments(key: string, string: string, score: number, options?: SugAddOptions): Array { + const args = ['FT.SUGADD', key, string, score.toString()]; + + if (options?.INCR) { + args.push('INCR'); + } + + if (options?.PAYLOAD) { + args.push('PAYLOAD', options.PAYLOAD); + } + + return args; +} + +export declare function transformReply(): number; diff --git a/packages/search/lib/commands/SUGDEL.spec.ts b/packages/search/lib/commands/SUGDEL.spec.ts new file mode 100644 index 00000000000..3d89e3b9a72 --- /dev/null +++ b/packages/search/lib/commands/SUGDEL.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGDEL'; + +describe('SUGDEL', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', 'string'), + ['FT.SUGDEL', 'key', 'string'] + ); + }); + + testUtils.testWithClient('client.ft.sugDel', async client => { + assert.equal( + await client.ft.sugDel('key', 'string'), + false + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SUGDEL.ts b/packages/search/lib/commands/SUGDEL.ts new file mode 100644 index 00000000000..43f4744c00d --- /dev/null +++ b/packages/search/lib/commands/SUGDEL.ts @@ -0,0 +1,5 @@ +export function transformArguments(key: string, string: string): Array { + return ['FT.SUGDEL', key, string]; +} + +export { transformReplyBoolean as transformReply } from '@node-redis/client/dist/lib/commands/generic-transformers'; diff --git a/packages/search/lib/commands/SUGGET.spec.ts b/packages/search/lib/commands/SUGGET.spec.ts new file mode 100644 index 00000000000..c24c2ff0863 --- /dev/null +++ b/packages/search/lib/commands/SUGGET.spec.ts @@ -0,0 +1,46 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGGET'; + +describe('SUGGET', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix'] + ); + }); + + it('with FUZZY', () => { + assert.deepEqual( + transformArguments('key', 'prefix', { FUZZY: true }), + ['FT.SUGGET', 'key', 'prefix', 'FUZZY'] + ); + }); + + it('with MAX', () => { + assert.deepEqual( + transformArguments('key', 'prefix', { MAX: 10 }), + ['FT.SUGGET', 'key', 'prefix', 'MAX', '10'] + ); + }); + }); + + describe('client.ft.sugGet', () => { + testUtils.testWithClient('null', async client => { + assert.equal( + await client.ft.sugGet('key', 'prefix'), + null + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with suggestions', async client => { + await client.ft.sugAdd('key', 'string', 1); + + assert.deepEqual( + await client.ft.sugGet('key', 'string'), + ['string'] + ); + }, GLOBAL.SERVERS.OPEN); + }); +}); diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts new file mode 100644 index 00000000000..558cedeaa08 --- /dev/null +++ b/packages/search/lib/commands/SUGGET.ts @@ -0,0 +1,22 @@ +export const IS_READ_ONLY = true; + +export interface SugGetOptions { + FUZZY?: true; + MAX?: number; +} + +export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { + const args = ['FT.SUGGET', key, prefix]; + + if (options?.FUZZY) { + args.push('FUZZY'); + } + + if (options?.MAX) { + args.push('MAX', options.MAX.toString()); + } + + return args; +} + +export declare function transformReply(): null | Array; diff --git a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts new file mode 100644 index 00000000000..a4a87ebe895 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGGET_WITHPAYLOADS'; + +describe('SUGGET WITHPAYLOADS', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix', 'WITHPAYLOADS'] + ); + }); + + describe('client.ft.sugGetWithPayloads', () => { + testUtils.testWithClient('null', async client => { + assert.equal( + await client.ft.sugGetWithPayloads('key', 'prefix'), + null + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with suggestions', async client => { + await client.ft.sugAdd('key', 'string', 1, { PAYLOAD: 'payload' }); + + assert.deepEqual( + await client.ft.sugGetWithPayloads('key', 'string'), + [{ + suggestion: 'string', + payload: 'payload' + }] + ); + }, GLOBAL.SERVERS.OPEN); + }); +}); diff --git a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts new file mode 100644 index 00000000000..7eaff4697e1 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts @@ -0,0 +1,29 @@ +import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; + +export { IS_READ_ONLY } from './SUGGET'; + +export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { + return [ + ...transformSugGetArguments(key, prefix, options), + 'WITHPAYLOADS' + ]; +} + +export interface SuggestionWithPayload { + suggestion: string; + payload: string | null; +} + +export function transformReply(rawReply: Array | null): Array | null { + if (rawReply === null) return null; + + const transformedReply = []; + for (let i = 0; i < rawReply.length; i += 2) { + transformedReply.push({ + suggestion: rawReply[i]!, + payload: rawReply[i + 1] + }); + } + + return transformedReply; +} diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts new file mode 100644 index 00000000000..e60daa917a9 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGGET_WITHSCORES'; + +describe('SUGGET WITHSCORES', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix', 'WITHSCORES'] + ); + }); + + describe('client.ft.sugGetWithScores', () => { + testUtils.testWithClient('null', async client => { + assert.equal( + await client.ft.sugGetWithScores('key', 'prefix'), + null + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with suggestions', async client => { + await client.ft.sugAdd('key', 'string', 1); + + assert.deepEqual( + await client.ft.sugGetWithScores('key', 'string'), + [{ + suggestion: 'string', + score: 2147483648 + }] + ); + }, GLOBAL.SERVERS.OPEN); + }); +}); diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES.ts b/packages/search/lib/commands/SUGGET_WITHSCORES.ts new file mode 100644 index 00000000000..bad5bff2999 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHSCORES.ts @@ -0,0 +1,29 @@ +import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; + +export { IS_READ_ONLY } from './SUGGET'; + +export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { + return [ + ...transformSugGetArguments(key, prefix, options), + 'WITHSCORES' + ]; +} + +export interface SuggestionWithScores { + suggestion: string; + score: number; +} + +export function transformReply(rawReply: Array | null): Array | null { + if (rawReply === null) return null; + + const transformedReply = []; + for (let i = 0; i < rawReply.length; i += 2) { + transformedReply.push({ + suggestion: rawReply[i], + score: Number(rawReply[i + 1]) + }); + } + + return transformedReply; +} diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts new file mode 100644 index 00000000000..0900d91b8d9 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts @@ -0,0 +1,34 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGGET_WITHSCORES_WITHPAYLOADS'; + +describe('SUGGET WITHSCORES WITHPAYLOADS', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix', 'WITHSCORES', 'WITHPAYLOADS'] + ); + }); + + describe('client.ft.sugGetWithScoresWithPayloads', () => { + testUtils.testWithClient('null', async client => { + assert.equal( + await client.ft.sugGetWithScoresWithPayloads('key', 'prefix'), + null + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with suggestions', async client => { + await client.ft.sugAdd('key', 'string', 1, { PAYLOAD: 'payload' }); + + assert.deepEqual( + await client.ft.sugGetWithScoresWithPayloads('key', 'string'), + [{ + suggestion: 'string', + score: 2147483648, + payload: 'payload' + }] + ); + }, GLOBAL.SERVERS.OPEN); + }); +}); diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts new file mode 100644 index 00000000000..3b2fe7667b7 --- /dev/null +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts @@ -0,0 +1,30 @@ +import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; +import { SuggestionWithPayload } from './SUGGET_WITHPAYLOADS'; +import { SuggestionWithScores } from './SUGGET_WITHSCORES'; + +export { IS_READ_ONLY } from './SUGGET'; + +export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { + return [ + ...transformSugGetArguments(key, prefix, options), + 'WITHSCORES', + 'WITHPAYLOADS' + ]; +} + +type SuggestionWithScoresAndPayloads = SuggestionWithScores & SuggestionWithPayload; + +export function transformReply(rawReply: Array | null): Array | null { + if (rawReply === null) return null; + + const transformedReply = []; + for (let i = 0; i < rawReply.length; i += 3) { + transformedReply.push({ + suggestion: rawReply[i]!, + score: Number(rawReply[i + 1]!), + payload: rawReply[i + 2] + }); + } + + return transformedReply; +} diff --git a/packages/search/lib/commands/SUGLEN.spec.ts b/packages/search/lib/commands/SUGLEN.spec.ts new file mode 100644 index 00000000000..2ea680df953 --- /dev/null +++ b/packages/search/lib/commands/SUGLEN.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SUGLEN'; + +describe('SUGLEN', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['FT.SUGLEN', 'key'] + ); + }); + + testUtils.testWithClient('client.ft.sugLen', async client => { + assert.equal( + await client.ft.sugLen('key'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SUGLEN.ts b/packages/search/lib/commands/SUGLEN.ts new file mode 100644 index 00000000000..15b3da61261 --- /dev/null +++ b/packages/search/lib/commands/SUGLEN.ts @@ -0,0 +1,7 @@ +export const IS_READ_ONLY = true; + +export function transformArguments(key: string): Array { + return ['FT.SUGLEN', key]; +} + +export declare function transformReply(): number; diff --git a/packages/search/lib/commands/SYNDUMP.spec.ts b/packages/search/lib/commands/SYNDUMP.spec.ts new file mode 100644 index 00000000000..4b0cb0c8b3a --- /dev/null +++ b/packages/search/lib/commands/SYNDUMP.spec.ts @@ -0,0 +1,23 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SYNDUMP'; + +describe('SYNDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('index'), + ['FT.SYNDUMP', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.synDump', async client => { + await client.ft.create('index', {}, { + ON: 'HASH' // TODO: shouldn't be mandatory + }); + + assert.deepEqual( + await client.ft.synDump('index'), + [] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SYNDUMP.ts b/packages/search/lib/commands/SYNDUMP.ts new file mode 100644 index 00000000000..5f1e71aaf78 --- /dev/null +++ b/packages/search/lib/commands/SYNDUMP.ts @@ -0,0 +1,5 @@ +export function transformArguments(index: string): Array { + return ['FT.SYNDUMP', index]; +} + +export declare function transformReply(): Array; diff --git a/packages/search/lib/commands/SYNUPDATE.spec.ts b/packages/search/lib/commands/SYNUPDATE.spec.ts new file mode 100644 index 00000000000..bf7fed84934 --- /dev/null +++ b/packages/search/lib/commands/SYNUPDATE.spec.ts @@ -0,0 +1,39 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SYNUPDATE'; + +describe('SYNUPDATE', () => { + describe('transformArguments', () => { + it('single term', () => { + assert.deepEqual( + transformArguments('index', 'groupId', 'term'), + ['FT.SYNUPDATE', 'index', 'groupId', 'term'] + ); + }); + + it('multiple terms', () => { + assert.deepEqual( + transformArguments('index', 'groupId', ['1', '2']), + ['FT.SYNUPDATE', 'index', 'groupId', '1', '2'] + ); + }); + + it('with SKIPINITIALSCAN', () => { + assert.deepEqual( + transformArguments('index', 'groupId', 'term', { SKIPINITIALSCAN: true }), + ['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term'] + ); + }); + }); + + testUtils.testWithClient('client.ft.synUpdate', async client => { + await client.ft.create('index', {}, { + ON: 'HASH' // TODO: shouldn't be mandatory + }); + + assert.equal( + await client.ft.synUpdate('index', 'groupId', 'term'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/SYNUPDATE.ts b/packages/search/lib/commands/SYNUPDATE.ts new file mode 100644 index 00000000000..b59d35617fa --- /dev/null +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -0,0 +1,23 @@ +import { pushVerdictArguments } from '@node-redis/client/dist/lib/commands/generic-transformers'; +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; + +interface SynUpdateOptions { + SKIPINITIALSCAN?: true; +} + +export function transformArguments( + index: string, + groupId: string, + terms: string | Array, + options?: SynUpdateOptions +): RedisCommandArguments { + const args = ['FT.SYNUPDATE', index, groupId]; + + if (options?.SKIPINITIALSCAN) { + args.push('SKIPINITIALSCAN'); + } + + return pushVerdictArguments(args, terms); +} + +export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/TAGVALS.spec.ts b/packages/search/lib/commands/TAGVALS.spec.ts new file mode 100644 index 00000000000..1f90939bb0d --- /dev/null +++ b/packages/search/lib/commands/TAGVALS.spec.ts @@ -0,0 +1,24 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { SchemaFieldTypes } from './CREATE'; +import { transformArguments } from './TAGVALS'; + +describe('TAGVALS', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('index', '@field'), + ['FT.TAGVALS', 'index', '@field'] + ); + }); + + testUtils.testWithClient('client.ft.tagVals', async client => { + await client.ft.create('index', { + field: SchemaFieldTypes.TAG + }); + + assert.deepEqual( + await client.ft.tagVals('index', 'field'), + [] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/TAGVALS.ts b/packages/search/lib/commands/TAGVALS.ts new file mode 100644 index 00000000000..54342f0c9e5 --- /dev/null +++ b/packages/search/lib/commands/TAGVALS.ts @@ -0,0 +1,5 @@ +export function transformArguments(index: string, fieldName: string): Array { + return ['FT.TAGVALS', index, fieldName]; +} + +export declare function transformReply(): Array; diff --git a/packages/search/lib/commands/_LIST.spec.ts b/packages/search/lib/commands/_LIST.spec.ts new file mode 100644 index 00000000000..602c29975f2 --- /dev/null +++ b/packages/search/lib/commands/_LIST.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './_LIST'; + +describe('_LIST', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['FT._LIST'] + ); + }); + + testUtils.testWithClient('client.ft._list', async client => { + assert.deepEqual( + await client.ft._list(), + [] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/search/lib/commands/_LIST.ts b/packages/search/lib/commands/_LIST.ts new file mode 100644 index 00000000000..588ec837c3b --- /dev/null +++ b/packages/search/lib/commands/_LIST.ts @@ -0,0 +1,5 @@ +export function transformArguments(): Array { + return ['FT._LIST']; +} + +export declare function transformReply(): Array; diff --git a/packages/search/lib/commands/index.spec.ts b/packages/search/lib/commands/index.spec.ts new file mode 100644 index 00000000000..f0afa304a92 --- /dev/null +++ b/packages/search/lib/commands/index.spec.ts @@ -0,0 +1,46 @@ +import { strict as assert } from 'assert'; +import { pushArgumentsWithLength, pushSortByArguments } from '.'; + +describe('pushSortByArguments', () => { + describe('single', () => { + it('string', () => { + assert.deepEqual( + pushSortByArguments([], 'SORTBT', '@property'), + ['SORTBT', '1', '@property'] + ); + }); + + it('.BY', () => { + assert.deepEqual( + pushSortByArguments([], 'SORTBT', { BY: '@property' }), + ['SORTBT', '1', '@property'] + ); + }); + + it('with DIRECTION', () => { + assert.deepEqual( + pushSortByArguments([], 'SORTBY', { + BY: '@property', + DIRECTION: 'ASC' + }), + ['SORTBY', '2', '@property', 'ASC'] + ); + }); + }); + + it('multiple', () => { + assert.deepEqual( + pushSortByArguments([], 'SORTBY', ['@1', '@2']), + ['SORTBY', '2', '@1', '@2'] + ); + }); +}); + +it('pushArgumentsWithLength', () => { + assert.deepEqual( + pushArgumentsWithLength(['a'], args => { + args.push('b', 'c'); + }), + ['a', '2', 'b', 'c'] + ); +}); diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts new file mode 100644 index 00000000000..70626c00df0 --- /dev/null +++ b/packages/search/lib/commands/index.ts @@ -0,0 +1,161 @@ +import * as _LIST from './_LIST'; +import * as AGGREGATE from './AGGREGATE'; +import * as ALIASADD from './ALIASADD'; +import * as ALIASDEL from './ALIASDEL'; +import * as ALIASUPDATE from './ALIASUPDATE'; +import * as CONFIG_GET from './CONFIG_GET'; +import * as CONFIG_SET from './CONFIG_SET'; +import * as CREATE from './CREATE'; +import * as DICTADD from './DICTADD'; +import * as DICTDEL from './DICTDEL'; +import * as DICTDUMP from './DICTDUMP'; +import * as DROPINDEX from './DROPINDEX'; +import * as EXPLAIN from './EXPLAIN'; +import * as EXPLAINCLI from './EXPLAINCLI'; +import * as INFO from './INFO'; +// import * as PROFILE from './PROFILE'; +import * as SEARCH from './SEARCH'; +import * as SPELLCHECK from './SPELLCHECK'; +import * as SUGADD from './SUGADD'; +import * as SUGDEL from './SUGDEL'; +import * as SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; +import * as SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; +import * as SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; +import * as SUGGET from './SUGGET'; +import * as SUGLEN from './SUGLEN'; +import * as SYNDUMP from './SYNDUMP'; +import * as SYNUPDATE from './SYNUPDATE'; +import * as TAGVALS from './TAGVALS'; +import { RedisCommandArguments } from '@node-redis/client/dist/lib/commands'; + +export default { + _LIST, + _list: _LIST, + AGGREGATE, + aggregate: AGGREGATE, + ALIASADD, + aliasAdd: ALIASADD, + ALIASDEL, + aliasDel: ALIASDEL, + ALIASUPDATE, + aliasUpdate: ALIASUPDATE, + CONFIG_GET, + configGet: CONFIG_GET, + CONFIG_SET, + configSet: CONFIG_SET, + CREATE, + create: CREATE, + DICTADD, + dictAdd: DICTADD, + DICTDEL, + dictDel: DICTDEL, + DICTDUMP, + dictDump: DICTDUMP, + DROPINDEX, + dropIndex: DROPINDEX, + EXPLAIN, + explain: EXPLAIN, + EXPLAINCLI, + explainCli: EXPLAINCLI, + INFO, + info: INFO, + // PROFILE, + // profile: PROFILE, + SEARCH, + search: SEARCH, + SPELLCHECK, + spellCheck: SPELLCHECK, + SUGADD, + sugAdd: SUGADD, + SUGDEL, + sugDel: SUGDEL, + SUGGET_WITHPAYLOADS, + sugGetWithPayloads: SUGGET_WITHPAYLOADS, + SUGGET_WITHSCORES_WITHPAYLOADS, + sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, + SUGGET_WITHSCORES, + sugGetWithScores: SUGGET_WITHSCORES, + SUGGET, + sugGet: SUGGET, + SUGLEN, + sugLen: SUGLEN, + SYNDUMP, + synDump: SYNDUMP, + SYNUPDATE, + synUpdate: SYNUPDATE, + TAGVALS, + tagVals: TAGVALS +}; + +export enum RedisSearchLanguages { + ARABIC = 'Arabic', + BASQUE = 'Basque', + CATALANA = 'Catalan', + DANISH = 'Danish', + DUTCH = 'Dutch', + ENGLISH = 'English', + FINNISH = 'Finnish', + FRENCH = 'French', + GERMAN = 'German', + GREEK = 'Greek', + HUNGARIAN = 'Hungarian', + INDONESAIN = 'Indonesian', + IRISH = 'Irish', + ITALIAN = 'Italian', + LITHUANIAN = 'Lithuanian', + NEPALI = 'Nepali', + NORWEIGAN = 'Norwegian', + PORTUGUESE = 'Portuguese', + ROMANIAN = 'Romanian', + RUSSIAN = 'Russian', + SPANISH = 'Spanish', + SWEDISH = 'Swedish', + TAMIL = 'Tamil', + TURKISH = 'Turkish', + CHINESE = 'Chinese' +} + +export type PropertyName = `${'@' | '$.'}${string}`; + +export type SortByOptions = PropertyName | { + BY: PropertyName; + DIRECTION?: 'ASC' | 'DESC'; +}; + +function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByOptions): void { + if (typeof sortBy === 'string') { + args.push(sortBy); + } else { + args.push(sortBy.BY); + + if (sortBy.DIRECTION) { + args.push(sortBy.DIRECTION); + } + } +} + +export function pushSortByArguments(args: RedisCommandArguments, name: string, sortBy: SortByOptions | Array): RedisCommandArguments { + const lengthBefore = args.push( + name, + '' // will be overwritten + ); + + if (Array.isArray(sortBy)) { + for (const field of sortBy) { + pushSortByProperty(args, field); + } + } else { + pushSortByProperty(args, sortBy); + } + + args[lengthBefore - 1] = (args.length - lengthBefore).toString(); + + return args; +} + +export function pushArgumentsWithLength(args: RedisCommandArguments, fn: (args: RedisCommandArguments) => void): RedisCommandArguments { + const lengthIndex = args.push('') - 1; + fn(args); + args[lengthIndex] = (args.length - lengthIndex - 1).toString(); + return args; +} diff --git a/packages/search/lib/index.ts b/packages/search/lib/index.ts new file mode 100644 index 00000000000..9e0be7b169c --- /dev/null +++ b/packages/search/lib/index.ts @@ -0,0 +1,4 @@ +export { default } from './commands'; + +export { SchemaFieldTypes, SchemaTextFieldPhonetics } from './commands/CREATE'; +export { AggregateSteps, AggregateGroupByReducers } from './commands/AGGREGATE'; diff --git a/packages/search/lib/test-utils.ts b/packages/search/lib/test-utils.ts new file mode 100644 index 00000000000..4af05e10623 --- /dev/null +++ b/packages/search/lib/test-utils.ts @@ -0,0 +1,21 @@ +import TestUtils from '@node-redis/test-utils'; +import RediSearch from '.'; + +export default new TestUtils({ + dockerImageName: 'redislabs/redisearch', + dockerImageVersionArgument: 'redisearch-version', + defaultDockerVersion: '2.2.1' +}); + +export const GLOBAL = { + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/redisearch.so'], + clientOptions: { + modules: { + ft: RediSearch + } + } + } + } +}; diff --git a/packages/search/package.json b/packages/search/package.json new file mode 100644 index 00000000000..a72678c2add --- /dev/null +++ b/packages/search/package.json @@ -0,0 +1,24 @@ +{ + "name": "@node-redis/search", + "version": "1.0.0-rc.0", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "build": "tsc" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@node-redis/test-utils": "*", + "@types/node": "^16.11.7", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } +} diff --git a/packages/search/tsconfig.json b/packages/search/tsconfig.json new file mode 100644 index 00000000000..14fda1d8711 --- /dev/null +++ b/packages/search/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./lib/**/*.ts" + ] +} diff --git a/packages/test-utils/docker/Dockerfile b/packages/test-utils/docker/Dockerfile new file mode 100644 index 00000000000..23fc0b3a517 --- /dev/null +++ b/packages/test-utils/docker/Dockerfile @@ -0,0 +1,9 @@ +ARG IMAGE +FROM ${IMAGE} + +ARG REDIS_ARGUMENTS +ENV REDIS_ARGUMENTS=${REDIS_ARGUMENTS} + +COPY ./entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/packages/test-utils/docker/entrypoint.sh b/packages/test-utils/docker/entrypoint.sh new file mode 100755 index 00000000000..244977e83c4 --- /dev/null +++ b/packages/test-utils/docker/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo testststealkshdfklhasdf + +echo $REDIS_ARGUMENTS + +redis-server $REDIS_ARGUMENTS diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts new file mode 100644 index 00000000000..3dd6dcf3ebf --- /dev/null +++ b/packages/test-utils/lib/dockers.ts @@ -0,0 +1,222 @@ +import { createConnection } from 'net'; +import { once } from 'events'; +import { RedisModules, RedisScripts } from '@node-redis/client/lib/commands'; +import RedisClient, { RedisClientType } from '@node-redis/client/lib/client'; +import { promiseTimeout } from '@node-redis/client/lib/utils'; +import * as path from 'path'; +import { promisify } from 'util'; +import { exec } from 'child_process'; +const execAsync = promisify(exec); + +interface ErrorWithCode extends Error { + code: string; +} + +async function isPortAvailable(port: number): Promise { + try { + const socket = createConnection({ port }); + await once(socket, 'connect'); + socket.end(); + } catch (err) { + if (err instanceof Error && (err as ErrorWithCode).code === 'ECONNREFUSED') { + return true; + } + } + + return false; +} + +const portIterator = (async function*(): AsyncIterableIterator { + for (let i = 6379; i < 65535; i++) { + if (await isPortAvailable(i)) { + yield i; + } + } + + throw new Error('All ports are in use'); +})(); + +export interface RedisServerDockerConfig { + image: string; + version: Array; +} + +export interface RedisServerDocker { + port: number; + dockerId: string; +} + +// ".." cause it'll be in `./dist` +const DOCKER_FODLER_PATH = path.join(__dirname, '../docker'); + +async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array): Promise { + const port = (await portIterator.next()).value, + { stdout, stderr } = await execAsync( + 'docker run -d --network host $(' + + `docker build ${DOCKER_FODLER_PATH} -q ` + + `--build-arg IMAGE=${image}:${version.join('.')} ` + + `--build-arg REDIS_ARGUMENTS="--save --port ${port.toString()} ${serverArguments.join(' ')}"` + + ')' + ); + + if (!stdout) { + throw new Error(`docker run error - ${stderr}`); + } + + while (await isPortAvailable(port)) { + await promiseTimeout(500); + } + + return { + port, + dockerId: stdout.trim() + }; +} + +const RUNNING_SERVERS = new Map, ReturnType>(); + +export function spawnRedisServer(dockerConfig: RedisServerDockerConfig, serverArguments: Array): Promise { + const runningServer = RUNNING_SERVERS.get(serverArguments); + if (runningServer) { + return runningServer; + } + + const dockerPromise = spawnRedisServerDocker(dockerConfig, serverArguments); + RUNNING_SERVERS.set(serverArguments, dockerPromise); + return dockerPromise; +} + +async function dockerRemove(dockerId: string): Promise { + const { stderr } = await execAsync(`docker rm -f ${dockerId}`); + if (stderr) { + throw new Error(`docker rm error - ${stderr}`); + } +} + +after(() => { + return Promise.all( + [...RUNNING_SERVERS.values()].map(async dockerPromise => + await dockerRemove((await dockerPromise).dockerId) + ) + ); +}); + +export interface RedisClusterDockersConfig extends RedisServerDockerConfig { + numberOfNodes?: number; +} + +async function spawnRedisClusterNodeDocker( + dockersConfig: RedisClusterDockersConfig, + serverArguments: Array, + fromSlot: number, + toSlot: number, + waitForState: boolean, + meetPort?: number +): Promise { + const docker = await spawnRedisServerDocker(dockersConfig, [ + ...serverArguments, + '--cluster-enabled', + 'yes', + '--cluster-node-timeout', + '5000' + ]), + client = RedisClient.create({ + socket: { + port: docker.port + } + }); + + await client.connect(); + + try { + const range = []; + for (let i = fromSlot; i < toSlot; i++) { + range.push(i); + } + + const promises: Array> = [client.clusterAddSlots(range)]; + + if (meetPort) { + promises.push(client.clusterMeet('127.0.0.1', meetPort)); + } + + if (waitForState) { + promises.push(waitForClusterState(client)); + } + + await Promise.all(promises); + + return docker; + } finally { + await client.disconnect(); + } +} + +async function waitForClusterState(client: RedisClientType): Promise { + while ((await client.clusterInfo()).state !== 'ok') { + await promiseTimeout(500); + } +} + +const SLOTS = 16384; + +async function spawnRedisClusterDockers(dockersConfig: RedisClusterDockersConfig, serverArguments: Array): Promise> { + const numberOfNodes = dockersConfig.numberOfNodes ?? 3, + slotsPerNode = Math.floor(SLOTS / numberOfNodes), + dockers: Array = []; + for (let i = 0; i < numberOfNodes; i++) { + const fromSlot = i * slotsPerNode, + [ toSlot, waitForState ] = i === numberOfNodes - 1 ? [SLOTS, true] : [fromSlot + slotsPerNode, false]; + dockers.push( + await spawnRedisClusterNodeDocker( + dockersConfig, + serverArguments, + fromSlot, + toSlot, + waitForState, + i === 0 ? undefined : dockers[i - 1].port + ) + ); + } + + const client = RedisClient.create({ + socket: { + port: dockers[0].port + } + }); + + await client.connect(); + + try { + while ((await client.clusterInfo()).state !== 'ok') { + await promiseTimeout(500); + } + } finally { + await client.disconnect(); + } + + return dockers; +} + +const RUNNING_CLUSTERS = new Map, ReturnType>(); + +export function spawnRedisCluster(dockersConfig: RedisClusterDockersConfig, serverArguments: Array): Promise> { + const runningCluster = RUNNING_CLUSTERS.get(serverArguments); + if (runningCluster) { + return runningCluster; + } + + const dockersPromise = spawnRedisClusterDockers(dockersConfig, serverArguments); + RUNNING_CLUSTERS.set(serverArguments, dockersPromise); + return dockersPromise; +} + +after(() => { + return Promise.all( + [...RUNNING_CLUSTERS.values()].map(async dockersPromise => { + return Promise.all( + (await dockersPromise).map(({ dockerId }) => dockerRemove(dockerId)) + ); + }) + ); +}); diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts new file mode 100644 index 00000000000..8e20df75818 --- /dev/null +++ b/packages/test-utils/lib/index.ts @@ -0,0 +1,181 @@ +import { RedisModules, RedisScripts } from '@node-redis/client/lib/commands'; +import RedisClient, { RedisClientOptions, RedisClientType } from '@node-redis/client/lib/client'; +import RedisCluster, { RedisClusterOptions, RedisClusterType } from '@node-redis/client/lib/cluster'; +import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +interface TestUtilsConfig { + dockerImageName: string; + dockerImageVersionArgument: string; + defaultDockerVersion: string; + defaultClientOptions?: Partial>; + defaultClusterOptions?: Partial>; +} + +interface CommonTestOptions { + minimumDockerVersion?: Array; +} + +interface ClientTestOptions extends CommonTestOptions { + serverArguments: Array; + clientOptions?: Partial>; + disableClientSetup?: boolean; +} + +interface ClusterTestOptions extends CommonTestOptions { + serverArguments: Array; + clusterConfiguration?: Partial>; + numberOfNodes?: number; +} + +export default class TestUtils { + static #getVersion(argumentName: string, defaultVersion: string): Array { + return yargs(hideBin(process.argv)) + .option(argumentName, { + type: 'string', + default: defaultVersion + }) + .coerce(argumentName, (arg: string) => { + return arg.split('.').map(x => { + const value = Number(x); + if (Number.isNaN(value)) { + throw new TypeError(`${arg} is not a valid redis version`); + } + + return value; + }); + }) + .demandOption(argumentName) + .parseSync()[argumentName]; + } + + readonly #DOCKER_IMAGE: RedisServerDockerConfig; + + constructor(config: TestUtilsConfig) { + this.#DOCKER_IMAGE = { + image: config.dockerImageName, + version: TestUtils.#getVersion(config.dockerImageVersionArgument, config.defaultDockerVersion) + }; + } + + isVersionGreaterThan(minimumVersion: Array | undefined): boolean { + if (minimumVersion === undefined) return true; + + const lastIndex = Math.min(this.#DOCKER_IMAGE.version.length, minimumVersion.length) - 1; + for (let i = 0; i < lastIndex; i++) { + if (this.#DOCKER_IMAGE.version[i] > minimumVersion[i]) { + return true; + } else if (minimumVersion[i] > this.#DOCKER_IMAGE.version[i]) { + return false; + } + } + + return this.#DOCKER_IMAGE.version[lastIndex] >= minimumVersion[lastIndex]; + } + + isVersionGreaterThanHook(minimumVersion: Array | undefined): void { + const isVersionGreaterThan = this.isVersionGreaterThan.bind(this); + before(function () { + if (!isVersionGreaterThan(minimumVersion)) { + return this.skip(); + } + }); + } + + testWithClient( + title: string, + fn: (client: RedisClientType) => Promise, + options: ClientTestOptions + ): void { + let dockerPromise: ReturnType; + if (this.isVersionGreaterThan(options.minimumDockerVersion)) { + const dockerImage = this.#DOCKER_IMAGE; + before(function () { + this.timeout(30000); + + dockerPromise = spawnRedisServer(dockerImage, options.serverArguments); + return dockerPromise; + }); + } + + it(title, async function() { + if (!dockerPromise) return this.skip(); + + const client = RedisClient.create({ + ...options?.clientOptions, + socket: { + ...options?.clientOptions?.socket, + port: (await dockerPromise).port + } + }); + + if (options.disableClientSetup) { + return fn(client); + } + + await client.connect(); + + try { + await client.flushAll(); + await fn(client); + } finally { + if (client.isOpen) { + await client.flushAll(); + await client.disconnect(); + } + } + }); + } + + static async #clusterFlushAll(cluster: RedisClusterType): Promise { + await Promise.all( + cluster.getMasters().map(({ client }) => client.flushAll()) + ); + } + + testWithCluster( + title: string, + fn: (cluster: RedisClusterType) => Promise, + options: ClusterTestOptions + ): void { + let dockersPromise: ReturnType; + if (this.isVersionGreaterThan(options.minimumDockerVersion)) { + const dockerImage = this.#DOCKER_IMAGE; + before(function () { + this.timeout(30000); + + dockersPromise = spawnRedisCluster({ + ...dockerImage, + numberOfNodes: options?.numberOfNodes + }, options.serverArguments); + return dockersPromise; + }); + } + + it(title, async function () { + if (!dockersPromise) return this.skip(); + + const dockers = await dockersPromise, + cluster = RedisCluster.create({ + ...options.clusterConfiguration, + rootNodes: dockers.map(({ port }) => ({ + socket: { + port + } + })) + }); + + + await cluster.connect(); + + try { + await TestUtils.#clusterFlushAll(cluster); + await fn(cluster); + } finally { + await TestUtils.#clusterFlushAll(cluster); + await cluster.disconnect(); + } + }); + } +} diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json new file mode 100644 index 00000000000..47ddc25acff --- /dev/null +++ b/packages/test-utils/package.json @@ -0,0 +1,26 @@ +{ + "name": "@node-redis/test-utils", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsc", + "test": "echo \"TODO\"" + }, + "peerDependencies": { + "@node-redis/client": "^1.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.7", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.7", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4", + "yargs": "^17.2.1" + } +} diff --git a/packages/test-utils/tsconfig.json b/packages/test-utils/tsconfig.json new file mode 100644 index 00000000000..14fda1d8711 --- /dev/null +++ b/packages/test-utils/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./lib/**/*.ts" + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 00000000000..7df81029664 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,15 @@ +{ + "extends": "@tsconfig/node12/tsconfig.json", + "compilerOptions": { + "declaration": true, + "allowJs": true, + "useDefineForClassFields": true, + "esModuleInterop": false + }, + "files": [ + "./packages/client/lib/ts-declarations/cluster-key-slot.d.ts" + ], + "ts-node": { + "files": true + } +} diff --git a/tsconfig.json b/tsconfig.json index 1f76310034d..285b7ff0a97 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,9 @@ { - "extends": "@tsconfig/node12/tsconfig.json", + "extends": "./tsconfig.base.json", "compilerOptions": { - "outDir": "./dist", - "declaration": true, - "useDefineForClassFields": true, - "allowJs": true + "outDir": "./dist" }, - "files": [ - "./lib/ts-declarations/cluster-key-slot.d.ts", - "./lib/ts-declarations/redis-parser.d.ts" - ], "include": [ - "./index.ts", - "./lib/**/*.ts" - ], - "ts-node": { - "files": true - }, - "typedocOptions": { - "entryPoints": [ - "./index.ts", - "./lib" - ], - "entryPointStrategy": "expand", - "exclude": [ - "./lib/ts-declarations", - "./lib/test-utils.ts" - ], - "theme": "./node_modules/typedoc-github-wiki-theme/dist", - "out": "documentation" - } + "./index.ts" + ] }