diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-config.yml index f17a2992fa..9a98b1c08a 100644 --- a/.github/release-drafter-config.yml +++ b/.github/release-drafter-config.yml @@ -41,4 +41,3 @@ template: | 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 2df438eb19..0000000000 --- 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/tests.yml b/.github/workflows/tests.yml index b6b2dd050e..5942120839 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,6 +28,9 @@ jobs: - name: Install Packages run: npm ci + - name: Build tests tools + run: npm run build:tests-tools + - name: Run Tests run: npm run test -- --forbid-only --redis-version=${{ matrix.redis-version }} diff --git a/.gitignore b/.gitignore index 8d752019aa..9ee58bfbd3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,8 @@ -.vscode/ .idea/ -node_modules/ -dist/ .nyc_output/ +.vscode/ coverage/ -dump.rdb -documentation/ +dist/ +node_modules/ .DS_Store +dump.rdb diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 115395e3fb..0000000000 --- a/.npmignore +++ /dev/null @@ -1,20 +0,0 @@ -.vscode/ -.idea/ -node_modules/ -.nyc_output/ -coverage/ -dump.rdb -documentation/ -CONTRIBUTING.md -tsconfig.json -.deepsource.toml -.nycrc.json -benchmark/ -.github/ -scripts/ -lib/ -index.ts -*.spec.* -dist/lib/test-utils.* -.DS_Store -examples/ diff --git a/.nycrc.json b/.nycrc.json deleted file mode 100644 index 918b308a89..0000000000 --- a/.nycrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "@istanbuljs/nyc-config-typescript", - "exclude": ["**/*.spec.ts", "lib/test-utils/**/*.ts"] -} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbad520508..a041584e6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,10 +47,7 @@ Node Redis has a full test suite with coverage setup. To run the tests, run `npm install` to install dependencies, then run `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/README.md b/README.md index 9fe9e70a25..35648bd72e 100644 --- a/README.md +++ b/README.md @@ -1,296 +1,18 @@ -

- - - -

Node Redis

-

+# Node-Redis monorpo -
- - Coverage Status - - - Downloads - - - Version - - - Chat - -
+### Clients ---- +| Name | Description | +|------------------------------------|-------------| +| [redis](./packages/all-in-one) | | +| [@redis/client](./packages/client) | | -## Installation +### [Modules](https://redis.io/modules) -```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. +| Name | Description | +|------------------------------------|------------------------------------------------------------| +| [@redis/json](./packages/json) | [Redis JSON](https://oss.redis.com/redisjson/) commands | +| [@redis/search](./packages/search) | [Redis Search](https://oss.redis.com/redisearch/) commands | ## Contributing diff --git a/benchmark/.gitignore b/benchmark/.gitignore deleted file mode 100644 index 3c3629e647..0000000000 --- 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 37f8817665..0000000000 --- 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 4afaf8c305..0000000000 --- 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 ab874090c4..0000000000 --- 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/package-lock.json b/package-lock.json index ff1b2e6e56..87ae980524 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,44 +1,15 @@ { - "name": "redis", - "version": "4.0.0-rc.3", + "name": "redis-monorepo", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "redis", - "version": "4.0.0-rc.3", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" - }, + "name": "redis-monorepo", + "workspaces": [ + "./packages/*" + ], "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.11.6", - "@types/sinon": "^10.0.6", - "@types/yallist": "^4.0.1", - "@types/yargs": "^17.0.5", - "@typescript-eslint/eslint-plugin": "^5.2.0", - "@typescript-eslint/parser": "^5.2.0", - "eslint": "^8.1.0", - "mocha": "^9.1.3", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.4.0", - "typedoc": "^0.22.7", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.4", - "yargs": "^17.2.1" - }, - "engines": { - "node": ">=12" + "@tsconfig/node12": "^1.0.9" } }, "node_modules/@babel/code-frame": { @@ -392,9 +363,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A==", + "version": "7.16.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.2.tgz", + "integrity": "sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -481,9 +452,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", - "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", + "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", @@ -492,7 +463,7 @@ "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -500,15 +471,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -518,19 +480,6 @@ "node": ">= 4" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", @@ -546,9 +495,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "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": { @@ -849,6 +798,26 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@redis/client": { + "resolved": "packages/client", + "link": true + }, + "node_modules/@redis/json": { + "resolved": "packages/json", + "link": true + }, + "node_modules/@redis/search": { + "resolved": "packages/search", + "link": true + }, + "node_modules/@redis/test-utils": { + "resolved": "packages/test-utils", + "link": true + }, + "node_modules/@redis/time-series": { + "resolved": "packages/time-series", + "link": true + }, "node_modules/@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -972,9 +941,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==", + "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": { @@ -1023,13 +992,13 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.2.0.tgz", - "integrity": "sha512-qQwg7sqYkBF4CIQSyRQyqsYvP+g/J0To9ZPVNJpfxfekl5RmdvQnFFTVVwpRtaUDFNvjfe/34TgY/dpc3MgNTw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.1.tgz", + "integrity": "sha512-cFImaoIr5Ojj358xI/SDhjog57OK2NqlpxwdcgyxDA3bJlZcJq5CPzUXtpD7CxI2Hm6ATU7w5fQnnkVnmwpHqw==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "5.2.0", - "@typescript-eslint/scope-manager": "5.2.0", + "@typescript-eslint/experimental-utils": "5.3.1", + "@typescript-eslint/scope-manager": "5.3.1", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -1055,15 +1024,15 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.2.0.tgz", - "integrity": "sha512-fWyT3Agf7n7HuZZRpvUYdFYbPk3iDCq6fgu3ulia4c7yxmPnwVBovdSOX7RL+k8u6hLbrXcdAehlWUVpGh6IEw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.1.tgz", + "integrity": "sha512-RgFn5asjZ5daUhbK5Sp0peq0SSMytqcrkNfU4pnDma2D8P3ElZ6JbYjY8IMSFfZAJ0f3x3tnO3vXHweYg0g59w==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.2.0", - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/typescript-estree": "5.2.0", + "@typescript-eslint/scope-manager": "5.3.1", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/typescript-estree": "5.3.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -1079,14 +1048,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.2.0.tgz", - "integrity": "sha512-Uyy4TjJBlh3NuA8/4yIQptyJb95Qz5PX//6p8n7zG0QnN4o3NF9Je3JHbVU7fxf5ncSXTmnvMtd/LDQWDk0YqA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.1.tgz", + "integrity": "sha512-TD+ONlx5c+Qhk21x9gsJAMRohWAUMavSOmJgv3JGy9dgPhuBd5Wok0lmMClZDyJNLLZK1JRKiATzCKZNUmoyfw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.2.0", - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/typescript-estree": "5.2.0", + "@typescript-eslint/scope-manager": "5.3.1", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/typescript-estree": "5.3.1", "debug": "^4.3.2" }, "engines": { @@ -1106,13 +1075,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.2.0.tgz", - "integrity": "sha512-RW+wowZqPzQw8MUFltfKYZfKXqA2qgyi6oi/31J1zfXJRpOn6tCaZtd9b5u9ubnDG2n/EMvQLeZrsLNPpaUiFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.1.tgz", + "integrity": "sha512-XksFVBgAq0Y9H40BDbuPOTUIp7dn4u8oOuhcgGq7EoDP50eqcafkMVGrypyVGvDYHzjhdUCUwuwVUK4JhkMAMg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/visitor-keys": "5.2.0" + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/visitor-keys": "5.3.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1123,9 +1092,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.2.0.tgz", - "integrity": "sha512-cTk6x08qqosps6sPyP2j7NxyFPlCNsJwSDasqPNjEQ8JMD5xxj2NHxcLin5AJQ8pAVwpQ8BMI3bTxR0zxmK9qQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.1.tgz", + "integrity": "sha512-bG7HeBLolxKHtdHG54Uac750eXuQQPpdJfCYuw4ZI3bZ7+GgKClMWM8jExBtp7NSP4m8PmLRM8+lhzkYnSmSxQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1136,13 +1105,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.2.0.tgz", - "integrity": "sha512-RsdXq2XmVgKbm9nLsE3mjNUM7BTr/K4DYR9WfFVMUuozHWtH5gMpiNZmtrMG8GR385EOSQ3kC9HiEMJWimxd/g==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.1.tgz", + "integrity": "sha512-PwFbh/PKDVo/Wct6N3w+E4rLZxUDgsoII/GrWM2A62ETOzJd4M6s0Mu7w4CWsZraTbaC5UQI+dLeyOIFF1PquQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/visitor-keys": "5.2.0", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/visitor-keys": "5.3.1", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -1163,12 +1132,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.2.0.tgz", - "integrity": "sha512-Nk7HizaXWWCUBfLA/rPNKMzXzWS8Wg9qHMuGtT+v2/YpPij4nVXrVJc24N/r5WrrmqK31jCrZxeHqIgqRzs0Xg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.1.tgz", + "integrity": "sha512-3cHUzUuVTuNHx0Gjjt5pEHa87+lzyqOiHXy/Gz+SJOCW1mpw9xQHIIEwnKn+Thph1mgWyZ90nboOcSuZr/jTTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.2.0", + "@typescript-eslint/types": "5.3.1", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -1495,13 +1464,13 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.6.tgz", + "integrity": "sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw==", "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", + "caniuse-lite": "^1.0.30001274", + "electron-to-chromium": "^1.3.886", "escalade": "^3.1.1", "node-releases": "^2.0.1", "picocolors": "^1.0.0" @@ -1636,9 +1605,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001274", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001274.tgz", - "integrity": "sha512-+Nkvv0fHyhISkiMIjnyjmf5YJcQ1IQHZN6U9TLUMroWR38FNwpsC51Gb68yueafX1V6ifOisInSgP9WJFS13ew==", + "version": "1.0.30001278", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz", + "integrity": "sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==", "dev": true, "funding": { "type": "opencollective", @@ -2097,9 +2066,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.885", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.885.tgz", - "integrity": "sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg==", + "version": "1.3.891", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.891.tgz", + "integrity": "sha512-3cpwR82QkIS01CN/dup/4Yr3BiOiRLlZlcAFn/5FbNCunMO9ojqDgEP9JEo1QNLflu3pEnPWve50gHOEKc7r6w==", "dev": true }, "node_modules/emoji-regex": { @@ -2175,12 +2144,12 @@ } }, "node_modules/eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.1.0.tgz", - "integrity": "sha512-JZvNneArGSUsluHWJ8g8MMs3CfIEzwaLx9KyH4tZ2i+R2/rPWzL8c0zg3rHdwYVpN/1sB9gqnjHwz9HoeJpGHw==", + "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.3", + "@eslint/eslintrc": "^1.0.4", "@humanwhocodes/config-array": "^0.6.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -2214,7 +2183,7 @@ "progress": "^2.0.0", "regexpp": "^3.2.0", "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" @@ -2270,9 +2239,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", + "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" @@ -3060,9 +3029,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" @@ -5096,6 +5065,10 @@ "node": ">= 0.10" } }, + "node_modules/redis": { + "resolved": "packages/all-in-one", + "link": true + }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -5883,9 +5856,9 @@ } }, "node_modules/typedoc": { - "version": "0.22.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.7.tgz", - "integrity": "sha512-ndxxp+tU1Wczvdxp4u2/PvT1qjD6hdFdSdehpORHjE+JXmMkl2bftXCR0upHmsnesBG7VCcr8vfgloGHIH8glQ==", + "version": "0.22.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.8.tgz", + "integrity": "sha512-92S+YzyhospdXN5rnkYUTgirdTYqNWY7NP9vco+IqQQoiSXzVSUsawVro+tMyEEsWUS7EMaJ2YOjB9uE0CBi6A==", "dev": true, "dependencies": { "glob": "^7.2.0", @@ -5960,9 +5933,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": { @@ -6385,6 +6358,124 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "packages/all-in-one": { + "name": "redis", + "version": "4.0.0-rc.3", + "license": "MIT", + "dependencies": { + "@redis/client": "^4.0.0-rc", + "@redis/json": "^1.0.0-rc", + "@redis/search": "^1.0.0-rc" + }, + "devDependencies": { + "release-it": "^14.11.6", + "typescript": "^4.4.4" + } + }, + "packages/client": { + "name": "@redis/client", + "version": "4.0.0-rc.3", + "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", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "@types/sinon": "^10.0.6", + "@types/yallist": "^4.0.1", + "@typescript-eslint/eslint-plugin": "^5.2.0", + "@typescript-eslint/parser": "^5.2.0", + "eslint": "^8.1.0", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "sinon": "^11.1.2", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typedoc": "^0.22.7", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.3", + "typescript": "^4.4.4" + }, + "engines": { + "node": ">=12" + } + }, + "packages/json": { + "name": "@redis/json", + "version": "1.0.0-rc.0", + "license": "MIT", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + } + }, + "packages/search": { + "name": "@redis/search", + "version": "1.0.0-rc.0", + "license": "MIT", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + } + }, + "packages/test-utils": { + "name": "@redis/test-utils", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@tsconfig/node12": "^1.0.9", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.6", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4", + "yargs": "^17.2.1" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + } + }, + "packages/time-series": { + "name": "@redis/time-series", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } } }, "dependencies": { @@ -6660,9 +6751,9 @@ } }, "@babel/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A==", + "version": "7.16.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.2.tgz", + "integrity": "sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==", "dev": true }, "@babel/template": { @@ -6727,9 +6818,9 @@ } }, "@eslint/eslintrc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", - "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", + "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", @@ -6738,35 +6829,16 @@ "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "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 - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } } } }, @@ -6782,9 +6854,9 @@ } }, "@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "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": { @@ -7035,6 +7107,88 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@redis/client": { + "version": "file:packages/client", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "@types/sinon": "^10.0.6", + "@types/yallist": "^4.0.1", + "@typescript-eslint/eslint-plugin": "^5.2.0", + "@typescript-eslint/parser": "^5.2.0", + "cluster-key-slot": "1.1.0", + "eslint": "^8.1.0", + "generic-pool": "3.8.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.4.0", + "typedoc": "^0.22.7", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.3", + "typescript": "^4.4.4", + "yallist": "4.0.0" + } + }, + "@redis/json": { + "version": "file:packages/json", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } + }, + "@redis/search": { + "version": "file:packages/search", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } + }, + "@redis/test-utils": { + "version": "file:packages/test-utils", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@tsconfig/node12": "^1.0.9", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.6", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4", + "yargs": "^17.2.1" + } + }, + "@redis/time-series": { + "version": "file:packages/time-series", + "requires": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } + }, "@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -7149,9 +7303,9 @@ "dev": true }, "@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==", + "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": { @@ -7200,13 +7354,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.2.0.tgz", - "integrity": "sha512-qQwg7sqYkBF4CIQSyRQyqsYvP+g/J0To9ZPVNJpfxfekl5RmdvQnFFTVVwpRtaUDFNvjfe/34TgY/dpc3MgNTw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.3.1.tgz", + "integrity": "sha512-cFImaoIr5Ojj358xI/SDhjog57OK2NqlpxwdcgyxDA3bJlZcJq5CPzUXtpD7CxI2Hm6ATU7w5fQnnkVnmwpHqw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "5.2.0", - "@typescript-eslint/scope-manager": "5.2.0", + "@typescript-eslint/experimental-utils": "5.3.1", + "@typescript-eslint/scope-manager": "5.3.1", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -7216,55 +7370,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.2.0.tgz", - "integrity": "sha512-fWyT3Agf7n7HuZZRpvUYdFYbPk3iDCq6fgu3ulia4c7yxmPnwVBovdSOX7RL+k8u6hLbrXcdAehlWUVpGh6IEw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.3.1.tgz", + "integrity": "sha512-RgFn5asjZ5daUhbK5Sp0peq0SSMytqcrkNfU4pnDma2D8P3ElZ6JbYjY8IMSFfZAJ0f3x3tnO3vXHweYg0g59w==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.2.0", - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/typescript-estree": "5.2.0", + "@typescript-eslint/scope-manager": "5.3.1", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/typescript-estree": "5.3.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/parser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.2.0.tgz", - "integrity": "sha512-Uyy4TjJBlh3NuA8/4yIQptyJb95Qz5PX//6p8n7zG0QnN4o3NF9Je3JHbVU7fxf5ncSXTmnvMtd/LDQWDk0YqA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.3.1.tgz", + "integrity": "sha512-TD+ONlx5c+Qhk21x9gsJAMRohWAUMavSOmJgv3JGy9dgPhuBd5Wok0lmMClZDyJNLLZK1JRKiATzCKZNUmoyfw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.2.0", - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/typescript-estree": "5.2.0", + "@typescript-eslint/scope-manager": "5.3.1", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/typescript-estree": "5.3.1", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.2.0.tgz", - "integrity": "sha512-RW+wowZqPzQw8MUFltfKYZfKXqA2qgyi6oi/31J1zfXJRpOn6tCaZtd9b5u9ubnDG2n/EMvQLeZrsLNPpaUiFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.3.1.tgz", + "integrity": "sha512-XksFVBgAq0Y9H40BDbuPOTUIp7dn4u8oOuhcgGq7EoDP50eqcafkMVGrypyVGvDYHzjhdUCUwuwVUK4JhkMAMg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/visitor-keys": "5.2.0" + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/visitor-keys": "5.3.1" } }, "@typescript-eslint/types": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.2.0.tgz", - "integrity": "sha512-cTk6x08qqosps6sPyP2j7NxyFPlCNsJwSDasqPNjEQ8JMD5xxj2NHxcLin5AJQ8pAVwpQ8BMI3bTxR0zxmK9qQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.3.1.tgz", + "integrity": "sha512-bG7HeBLolxKHtdHG54Uac750eXuQQPpdJfCYuw4ZI3bZ7+GgKClMWM8jExBtp7NSP4m8PmLRM8+lhzkYnSmSxQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.2.0.tgz", - "integrity": "sha512-RsdXq2XmVgKbm9nLsE3mjNUM7BTr/K4DYR9WfFVMUuozHWtH5gMpiNZmtrMG8GR385EOSQ3kC9HiEMJWimxd/g==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.1.tgz", + "integrity": "sha512-PwFbh/PKDVo/Wct6N3w+E4rLZxUDgsoII/GrWM2A62ETOzJd4M6s0Mu7w4CWsZraTbaC5UQI+dLeyOIFF1PquQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.2.0", - "@typescript-eslint/visitor-keys": "5.2.0", + "@typescript-eslint/types": "5.3.1", + "@typescript-eslint/visitor-keys": "5.3.1", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -7273,12 +7427,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.2.0.tgz", - "integrity": "sha512-Nk7HizaXWWCUBfLA/rPNKMzXzWS8Wg9qHMuGtT+v2/YpPij4nVXrVJc24N/r5WrrmqK31jCrZxeHqIgqRzs0Xg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.1.tgz", + "integrity": "sha512-3cHUzUuVTuNHx0Gjjt5pEHa87+lzyqOiHXy/Gz+SJOCW1mpw9xQHIIEwnKn+Thph1mgWyZ90nboOcSuZr/jTTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.2.0", + "@typescript-eslint/types": "5.3.1", "eslint-visitor-keys": "^3.0.0" } }, @@ -7519,13 +7673,13 @@ "dev": true }, "browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.6.tgz", + "integrity": "sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", + "caniuse-lite": "^1.0.30001274", + "electron-to-chromium": "^1.3.886", "escalade": "^3.1.1", "node-releases": "^2.0.1", "picocolors": "^1.0.0" @@ -7614,9 +7768,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001274", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001274.tgz", - "integrity": "sha512-+Nkvv0fHyhISkiMIjnyjmf5YJcQ1IQHZN6U9TLUMroWR38FNwpsC51Gb68yueafX1V6ifOisInSgP9WJFS13ew==", + "version": "1.0.30001278", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz", + "integrity": "sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==", "dev": true }, "chalk": { @@ -7963,9 +8117,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.885", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.885.tgz", - "integrity": "sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg==", + "version": "1.3.891", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.891.tgz", + "integrity": "sha512-3cpwR82QkIS01CN/dup/4Yr3BiOiRLlZlcAFn/5FbNCunMO9ojqDgEP9JEo1QNLflu3pEnPWve50gHOEKc7r6w==", "dev": true }, "emoji-regex": { @@ -8026,12 +8180,12 @@ "dev": true }, "eslint": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.1.0.tgz", - "integrity": "sha512-JZvNneArGSUsluHWJ8g8MMs3CfIEzwaLx9KyH4tZ2i+R2/rPWzL8c0zg3rHdwYVpN/1sB9gqnjHwz9HoeJpGHw==", + "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.3", + "@eslint/eslintrc": "^1.0.4", "@humanwhocodes/config-array": "^0.6.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -8065,7 +8219,7 @@ "progress": "^2.0.0", "regexpp": "^3.2.0", "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" @@ -8123,9 +8277,9 @@ } }, "eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", + "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": { @@ -8667,9 +8821,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": { @@ -10220,6 +10374,16 @@ "resolve": "^1.1.6" } }, + "redis": { + "version": "file:packages/all-in-one", + "requires": { + "@redis/client": "^4.0.0-rc", + "@redis/json": "^1.0.0-rc", + "@redis/search": "^1.0.0-rc", + "release-it": "^14.11.6", + "typescript": "^4.4.4" + } + }, "redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -10803,9 +10967,9 @@ } }, "typedoc": { - "version": "0.22.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.7.tgz", - "integrity": "sha512-ndxxp+tU1Wczvdxp4u2/PvT1qjD6hdFdSdehpORHjE+JXmMkl2bftXCR0upHmsnesBG7VCcr8vfgloGHIH8glQ==", + "version": "0.22.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.8.tgz", + "integrity": "sha512-92S+YzyhospdXN5rnkYUTgirdTYqNWY7NP9vco+IqQQoiSXzVSUsawVro+tMyEEsWUS7EMaJ2YOjB9uE0CBi6A==", "dev": true, "requires": { "glob": "^7.2.0", @@ -10854,9 +11018,9 @@ "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 }, diff --git a/package.json b/package.json index f252e4a0fa..e7de3fc867 100644 --- a/package.json +++ b/package.json @@ -1,60 +1,19 @@ { - "name": "redis", - "version": "4.0.0-rc.3", - "description": "A high performance Redis client.", - "keywords": [ - "database", - "redis", - "pubsub" + "name": "redis-monorepo", + "private": true, + "workspaces": [ + "./packages/*" ], - "author": "Matt Ranney ", - "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", "scripts": { - "test": "nyc -r text-summary -r html 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" + "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' ! -name 'all-in-one' -exec npm run build -w {} \\;", + "build:all-in-one": "npm run build -w ./packages/all-in-one", + "build": "npm run build:client && npm run build:test-utils && npm run build:modules && npm run build:all-in-one" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@tsconfig/node12": "^1.0.9", - "@types/mocha": "^9.0.0", - "@types/node": "^16.11.6", - "@types/sinon": "^10.0.6", - "@types/yallist": "^4.0.1", - "@types/yargs": "^17.0.5", - "@typescript-eslint/eslint-plugin": "^5.2.0", - "@typescript-eslint/parser": "^5.2.0", - "eslint": "^8.1.0", - "mocha": "^9.1.3", - "nyc": "^15.1.0", - "release-it": "^14.11.6", - "sinon": "^11.1.2", - "source-map-support": "^0.5.20", - "ts-node": "^10.4.0", - "typedoc": "^0.22.7", - "typedoc-github-wiki-theme": "^0.6.0", - "typedoc-plugin-markdown": "^3.11.3", - "typescript": "^4.4.4", - "yargs": "^17.2.1" - }, - "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" + "@tsconfig/node12": "^1.0.9" + } } diff --git a/packages/all-in-one/index.ts b/packages/all-in-one/index.ts new file mode 100644 index 0000000000..b0cd5c1f8f --- /dev/null +++ b/packages/all-in-one/index.ts @@ -0,0 +1,19 @@ +import { createClient as _createClient } from '@redis/client'; +import { RedisScripts } from '@redis/client/dist/lib/commands'; +import { RedisClientOptions, RedisClientType } from '@redis/client/dist/lib/client'; +import RedisJSON from '@redis/json'; +import RediSearch from '@redis/search'; + +const modules = { + json: RedisJSON, + ft: RediSearch +}; + +export function createClient>( + options?: Omit, 'modules'> +): RedisClientType { + return _createClient({ + ...options, + modules + }); +} diff --git a/packages/all-in-one/package.json b/packages/all-in-one/package.json new file mode 100644 index 0000000000..8fdb714971 --- /dev/null +++ b/packages/all-in-one/package.json @@ -0,0 +1,27 @@ +{ + "name": "redis", + "version": "4.0.0-rc.3", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.ts", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "@redis/client": "^4.0.0-rc", + "@redis/json": "^1.0.0-rc", + "@redis/search": "^1.0.0-rc" + }, + "devDependencies": { + "release-it": "^14.11.6", + "typescript": "^4.4.4" + }, + "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" +} diff --git a/packages/all-in-one/tsconfig.json b/packages/all-in-one/tsconfig.json new file mode 100644 index 0000000000..103760b874 --- /dev/null +++ b/packages/all-in-one/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./index.ts" + ] + } diff --git a/.eslintrc.json b/packages/client/.eslintrc.json similarity index 100% rename from .eslintrc.json rename to packages/client/.eslintrc.json diff --git a/packages/client/.gitignore b/packages/client/.gitignore new file mode 100644 index 0000000000..2d7ddbc106 --- /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 0000000000..b7310e1576 --- /dev/null +++ b/packages/client/.npmignore @@ -0,0 +1,9 @@ +.nyc_output/ +coverage/ +documentation/ +examples/ +lib/ +.nycrc.json +dump.rdb +index.ts +tsconfig.json diff --git a/packages/client/.nycrc.json b/packages/client/.nycrc.json new file mode 100644 index 0000000000..b4e671e178 --- /dev/null +++ b/packages/client/.nycrc.json @@ -0,0 +1,4 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "exclude": ["**/*.spec.ts", "lib/test-utils.ts"] +} diff --git a/CHANGELOG.md b/packages/client/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to packages/client/CHANGELOG.md diff --git a/packages/client/LICENSE b/packages/client/LICENSE new file mode 100644 index 0000000000..db86cc4de7 --- /dev/null +++ b/packages/client/LICENSE @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2016-present Node Redis contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/client/README.md b/packages/client/README.md new file mode 100644 index 0000000000..813f9830ef --- /dev/null +++ b/packages/client/README.md @@ -0,0 +1,294 @@ +

+ + + +

Node Redis

+

+ + + +--- + +## 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. diff --git a/docs/FAQ.md b/packages/client/docs/FAQ.md similarity index 100% rename from docs/FAQ.md rename to packages/client/docs/FAQ.md diff --git a/docs/client-configuration.md b/packages/client/docs/client-configuration.md similarity index 98% rename from docs/client-configuration.md rename to packages/client/docs/client-configuration.md index 11fdb0a681..3b6b7dcad7 100644 --- a/docs/client-configuration.md +++ b/packages/client/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](../../README.md#modules) 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/packages/client/docs/clustering.md similarity index 82% rename from docs/clustering.md rename to packages/client/docs/clustering.md index a84dc3b1aa..3b5ef94a5c 100644 --- a/docs/clustering.md +++ b/packages/client/docs/clustering.md @@ -37,7 +37,9 @@ import { createCluster } from 'redis'; | 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 | | +| 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 diff --git a/docs/isolated-execution.md b/packages/client/docs/isolated-execution.md similarity index 100% rename from docs/isolated-execution.md rename to packages/client/docs/isolated-execution.md diff --git a/docs/v3-to-v4.md b/packages/client/docs/v3-to-v4.md similarity index 100% rename from docs/v3-to-v4.md rename to packages/client/docs/v3-to-v4.md diff --git a/examples/README.md b/packages/client/examples/README.md similarity index 100% rename from examples/README.md rename to packages/client/examples/README.md diff --git a/examples/blocking-list-pop.js b/packages/client/examples/blocking-list-pop.js similarity index 100% rename from examples/blocking-list-pop.js rename to packages/client/examples/blocking-list-pop.js diff --git a/examples/command-with-modifiers.js b/packages/client/examples/command-with-modifiers.js similarity index 100% rename from examples/command-with-modifiers.js rename to packages/client/examples/command-with-modifiers.js diff --git a/examples/connect-as-acl-user.js b/packages/client/examples/connect-as-acl-user.js similarity index 100% rename from examples/connect-as-acl-user.js rename to packages/client/examples/connect-as-acl-user.js diff --git a/examples/lua-multi-incr.js b/packages/client/examples/lua-multi-incr.js similarity index 100% rename from examples/lua-multi-incr.js rename to packages/client/examples/lua-multi-incr.js diff --git a/examples/package-lock.json b/packages/client/examples/package-lock.json similarity index 100% rename from examples/package-lock.json rename to packages/client/examples/package-lock.json diff --git a/examples/package.json b/packages/client/examples/package.json similarity index 64% rename from examples/package.json rename to packages/client/examples/package.json index 4963094b0b..edb8cdacdb 100644 --- a/examples/package.json +++ b/packages/client/examples/package.json @@ -4,11 +4,6 @@ "description": "node-redis 4 example script", "main": "index.js", "private": true, - "scripts": { - }, - "type": "module", - "dependencies": { - "redis": "../" - } + "type": "module" } diff --git a/examples/set-scan.js b/packages/client/examples/set-scan.js similarity index 100% rename from examples/set-scan.js rename to packages/client/examples/set-scan.js diff --git a/index.ts b/packages/client/index.ts similarity index 100% rename from index.ts rename to packages/client/index.ts diff --git a/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts similarity index 100% rename from lib/client/commands-queue.ts rename to packages/client/lib/client/commands-queue.ts diff --git a/lib/client/commands.ts b/packages/client/lib/client/commands.ts similarity index 100% rename from lib/client/commands.ts rename to packages/client/lib/client/commands.ts diff --git a/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts similarity index 98% rename from lib/client/index.spec.ts rename to packages/client/lib/client/index.spec.ts index 51dded18b1..21abe8a25f 100644 --- a/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -444,16 +444,16 @@ describe('Client', () => { } }); - testUtils.testWithClient('executeIsolated', async client => { - await client.sendCommand(['CLIENT', 'SETNAME', 'client']); + // testUtils.testWithClient('executeIsolated', async client => { + // await client.sendCommand(['CLIENT', 'SETNAME', 'client']); - assert.equal( - await client.executeIsolated(isolatedClient => - isolatedClient.sendCommand(['CLIENT', 'GETNAME']) - ), - null - ); - }, GLOBAL.SERVERS.OPEN); + // assert.equal( + // await client.executeIsolated(isolatedClient => + // isolatedClient.sendCommand(['CLIENT', 'GETNAME']) + // ), + // null + // ); + // }, GLOBAL.SERVERS.OPEN); async function killClient(client: RedisClientType): Promise { const onceErrorPromise = once(client, 'error'); diff --git a/lib/client/index.ts b/packages/client/lib/client/index.ts similarity index 100% rename from lib/client/index.ts rename to packages/client/lib/client/index.ts diff --git a/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts similarity index 100% rename from lib/client/multi-command.ts rename to packages/client/lib/client/multi-command.ts diff --git a/lib/client/socket.spec.ts b/packages/client/lib/client/socket.spec.ts similarity index 100% rename from lib/client/socket.spec.ts rename to packages/client/lib/client/socket.spec.ts diff --git a/lib/client/socket.ts b/packages/client/lib/client/socket.ts similarity index 100% rename from lib/client/socket.ts rename to packages/client/lib/client/socket.ts diff --git a/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts similarity index 100% rename from lib/cluster/cluster-slots.ts rename to packages/client/lib/cluster/cluster-slots.ts diff --git a/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts similarity index 100% rename from lib/cluster/commands.ts rename to packages/client/lib/cluster/commands.ts diff --git a/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts similarity index 51% rename from lib/cluster/index.spec.ts rename to packages/client/lib/cluster/index.spec.ts index 66319460f6..43492a6500 100644 --- a/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -47,47 +47,47 @@ describe('Cluster', () => { } }); - testUtils.testWithCluster('should handle live resharding', async cluster => { - const key = 'key', - value = 'value'; - await cluster.set(key, value); + // testUtils.testWithCluster('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); + // 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); + // 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 - ); + // // 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); + // 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 - ); + // // 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; + // const { port: toPort } = to!.client.options!.socket; - await from.client.migrate( - '127.0.0.1', - toPort, - key, - 0, - 10 - ); + // 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 - ); - }, { - serverArguments: [] - }); + // // should be able to get the key from the new node + // assert.equal( + // await cluster.get(key), + // value + // ); + // }, { + // serverArguments: [] + // }); }); diff --git a/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts similarity index 100% rename from lib/cluster/index.ts rename to packages/client/lib/cluster/index.ts diff --git a/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts similarity index 100% rename from lib/cluster/multi-command.ts rename to packages/client/lib/cluster/multi-command.ts 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 100% rename from lib/commander.ts rename to packages/client/lib/commander.ts diff --git a/lib/commands/ACL_CAT.spec.ts b/packages/client/lib/commands/ACL_CAT.spec.ts similarity index 100% rename from lib/commands/ACL_CAT.spec.ts rename to packages/client/lib/commands/ACL_CAT.spec.ts 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 100% rename from lib/commands/ACL_DELUSER.spec.ts rename to packages/client/lib/commands/ACL_DELUSER.spec.ts 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 100% rename from lib/commands/ACL_GENPASS.spec.ts rename to packages/client/lib/commands/ACL_GENPASS.spec.ts 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/lib/commands/ACL_GETUSER.spec.ts b/packages/client/lib/commands/ACL_GETUSER.spec.ts similarity index 100% rename from lib/commands/ACL_GETUSER.spec.ts rename to packages/client/lib/commands/ACL_GETUSER.spec.ts 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 100% rename from lib/commands/ACL_LIST.spec.ts rename to packages/client/lib/commands/ACL_LIST.spec.ts 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 100% rename from lib/commands/ACL_LOAD.spec.ts rename to packages/client/lib/commands/ACL_LOAD.spec.ts 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 100% rename from lib/commands/ACL_LOG.spec.ts rename to packages/client/lib/commands/ACL_LOG.spec.ts 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 100% rename from lib/commands/ACL_LOG_RESET.spec.ts rename to packages/client/lib/commands/ACL_LOG_RESET.spec.ts 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 100% rename from lib/commands/ACL_SAVE.spec.ts rename to packages/client/lib/commands/ACL_SAVE.spec.ts 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 100% rename from lib/commands/ACL_SETUSER.spec.ts rename to packages/client/lib/commands/ACL_SETUSER.spec.ts 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 100% rename from lib/commands/ACL_USERS.spec.ts rename to packages/client/lib/commands/ACL_USERS.spec.ts 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 100% rename from lib/commands/ACL_WHOAMI.spec.ts rename to packages/client/lib/commands/ACL_WHOAMI.spec.ts 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 100% rename from lib/commands/APPEND.spec.ts rename to packages/client/lib/commands/APPEND.spec.ts 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 100% rename from lib/commands/BITCOUNT.spec.ts rename to packages/client/lib/commands/BITCOUNT.spec.ts 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 100% rename from lib/commands/BITFIELD.spec.ts rename to packages/client/lib/commands/BITFIELD.spec.ts 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 100% rename from lib/commands/BITOP.spec.ts rename to packages/client/lib/commands/BITOP.spec.ts 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 100% rename from lib/commands/BITPOS.spec.ts rename to packages/client/lib/commands/BITPOS.spec.ts 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 100% rename from lib/commands/BLMOVE.spec.ts rename to packages/client/lib/commands/BLMOVE.spec.ts 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 100% rename from lib/commands/BLPOP.spec.ts rename to packages/client/lib/commands/BLPOP.spec.ts 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 100% rename from lib/commands/BRPOP.spec.ts rename to packages/client/lib/commands/BRPOP.spec.ts 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 100% rename from lib/commands/BRPOPLPUSH.spec.ts rename to packages/client/lib/commands/BRPOPLPUSH.spec.ts 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 100% rename from lib/commands/BZPOPMAX.spec.ts rename to packages/client/lib/commands/BZPOPMAX.spec.ts 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 100% rename from lib/commands/BZPOPMIN.spec.ts rename to packages/client/lib/commands/BZPOPMIN.spec.ts 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 100% rename from lib/commands/CLIENT_ID.spec.ts rename to packages/client/lib/commands/CLIENT_ID.spec.ts 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 100% rename from lib/commands/CLUSTER_SLOTS.spec.ts rename to packages/client/lib/commands/CLUSTER_SLOTS.spec.ts 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/lib/commands/COMMAND.spec.ts b/packages/client/lib/commands/COMMAND.spec.ts similarity index 65% rename from lib/commands/COMMAND.spec.ts rename to packages/client/lib/commands/COMMAND.spec.ts index baad79845a..04ceab2a07 100644 --- a/lib/commands/COMMAND.spec.ts +++ b/packages/client/lib/commands/COMMAND.spec.ts @@ -11,7 +11,7 @@ describe('COMMAND', () => { ); }); - testUtils.testWithClient('client.command', async client => { - assertPingCommand((await client.command()).find(command => command.name === 'ping')); - }, GLOBAL.SERVERS.OPEN); + // 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 100% rename from lib/commands/COMMAND_COUNT.spec.ts rename to packages/client/lib/commands/COMMAND_COUNT.spec.ts diff --git a/lib/commands/COMMAND_COUNT.ts b/packages/client/lib/commands/COMMAND_COUNT.ts similarity index 100% rename from lib/commands/COMMAND_COUNT.ts rename to packages/client/lib/commands/COMMAND_COUNT.ts diff --git a/lib/commands/COMMAND_GETKEYS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts similarity index 100% rename from lib/commands/COMMAND_GETKEYS.spec.ts rename to packages/client/lib/commands/COMMAND_GETKEYS.spec.ts diff --git a/lib/commands/COMMAND_GETKEYS.ts b/packages/client/lib/commands/COMMAND_GETKEYS.ts similarity index 100% rename from lib/commands/COMMAND_GETKEYS.ts rename to packages/client/lib/commands/COMMAND_GETKEYS.ts diff --git a/lib/commands/COMMAND_INFO.spec.ts b/packages/client/lib/commands/COMMAND_INFO.spec.ts similarity index 100% rename from lib/commands/COMMAND_INFO.spec.ts rename to packages/client/lib/commands/COMMAND_INFO.spec.ts 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/lib/commands/CONFIG_GET.ts b/packages/client/lib/commands/CONFIG_GET.ts similarity index 100% rename from lib/commands/CONFIG_GET.ts rename to packages/client/lib/commands/CONFIG_GET.ts 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 100% rename from lib/commands/COPY.spec.ts rename to packages/client/lib/commands/COPY.spec.ts diff --git a/lib/commands/COPY.ts b/packages/client/lib/commands/COPY.ts similarity index 100% rename from lib/commands/COPY.ts rename to packages/client/lib/commands/COPY.ts diff --git a/lib/commands/DBSIZE.spec.ts b/packages/client/lib/commands/DBSIZE.spec.ts similarity index 100% rename from lib/commands/DBSIZE.spec.ts rename to packages/client/lib/commands/DBSIZE.spec.ts 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 100% rename from lib/commands/DECR.spec.ts rename to packages/client/lib/commands/DECR.spec.ts 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 100% rename from lib/commands/DECRBY.spec.ts rename to packages/client/lib/commands/DECRBY.spec.ts 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 100% rename from lib/commands/DEL.spec.ts rename to packages/client/lib/commands/DEL.spec.ts 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 100% rename from lib/commands/DUMP.spec.ts rename to packages/client/lib/commands/DUMP.spec.ts 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 100% rename from lib/commands/ECHO.spec.ts rename to packages/client/lib/commands/ECHO.spec.ts 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 100% rename from lib/commands/EVAL.spec.ts rename to packages/client/lib/commands/EVAL.spec.ts 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 100% rename from lib/commands/EXISTS.spec.ts rename to packages/client/lib/commands/EXISTS.spec.ts diff --git a/lib/commands/EXISTS.ts b/packages/client/lib/commands/EXISTS.ts similarity index 100% rename from lib/commands/EXISTS.ts rename to packages/client/lib/commands/EXISTS.ts diff --git a/lib/commands/EXPIRE.spec.ts b/packages/client/lib/commands/EXPIRE.spec.ts similarity index 100% rename from lib/commands/EXPIRE.spec.ts rename to packages/client/lib/commands/EXPIRE.spec.ts diff --git a/lib/commands/EXPIRE.ts b/packages/client/lib/commands/EXPIRE.ts similarity index 100% rename from lib/commands/EXPIRE.ts rename to packages/client/lib/commands/EXPIRE.ts diff --git a/lib/commands/EXPIREAT.spec.ts b/packages/client/lib/commands/EXPIREAT.spec.ts similarity index 100% rename from lib/commands/EXPIREAT.spec.ts rename to packages/client/lib/commands/EXPIREAT.spec.ts diff --git a/lib/commands/EXPIREAT.ts b/packages/client/lib/commands/EXPIREAT.ts similarity index 100% rename from lib/commands/EXPIREAT.ts rename to packages/client/lib/commands/EXPIREAT.ts 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 100% rename from lib/commands/FLUSHALL.spec.ts rename to packages/client/lib/commands/FLUSHALL.spec.ts 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 100% rename from lib/commands/FLUSHDB.spec.ts rename to packages/client/lib/commands/FLUSHDB.spec.ts 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 100% rename from lib/commands/GEOADD.spec.ts rename to packages/client/lib/commands/GEOADD.spec.ts 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 100% rename from lib/commands/GEODIST.spec.ts rename to packages/client/lib/commands/GEODIST.spec.ts 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 100% rename from lib/commands/GEOHASH.spec.ts rename to packages/client/lib/commands/GEOHASH.spec.ts 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 100% rename from lib/commands/GEOPOS.spec.ts rename to packages/client/lib/commands/GEOPOS.spec.ts 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 100% rename from lib/commands/GEOSEARCH.spec.ts rename to packages/client/lib/commands/GEOSEARCH.spec.ts 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 100% rename from lib/commands/GEOSEARCHSTORE.spec.ts rename to packages/client/lib/commands/GEOSEARCHSTORE.spec.ts 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 100% rename from lib/commands/GEOSEARCH_WITH.spec.ts rename to packages/client/lib/commands/GEOSEARCH_WITH.spec.ts diff --git a/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts similarity index 100% rename from lib/commands/GEOSEARCH_WITH.ts rename to packages/client/lib/commands/GEOSEARCH_WITH.ts diff --git a/lib/commands/GET.spec.ts b/packages/client/lib/commands/GET.spec.ts similarity index 100% rename from lib/commands/GET.spec.ts rename to packages/client/lib/commands/GET.spec.ts 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 100% rename from lib/commands/GETBIT.spec.ts rename to packages/client/lib/commands/GETBIT.spec.ts 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 100% rename from lib/commands/GETDEL.spec.ts rename to packages/client/lib/commands/GETDEL.spec.ts 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 100% rename from lib/commands/GETEX.spec.ts rename to packages/client/lib/commands/GETEX.spec.ts 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 100% rename from lib/commands/GETRANGE.spec.ts rename to packages/client/lib/commands/GETRANGE.spec.ts 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 100% rename from lib/commands/GETSET.spec.ts rename to packages/client/lib/commands/GETSET.spec.ts 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 100% rename from lib/commands/GET_BUFFER.spec.ts rename to packages/client/lib/commands/GET_BUFFER.spec.ts 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 100% rename from lib/commands/HDEL.spec.ts rename to packages/client/lib/commands/HDEL.spec.ts 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 100% rename from lib/commands/HELLO.spec.ts rename to packages/client/lib/commands/HELLO.spec.ts 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 100% rename from lib/commands/HEXISTS.spec.ts rename to packages/client/lib/commands/HEXISTS.spec.ts diff --git a/lib/commands/HEXISTS.ts b/packages/client/lib/commands/HEXISTS.ts similarity index 100% rename from lib/commands/HEXISTS.ts rename to packages/client/lib/commands/HEXISTS.ts diff --git a/lib/commands/HGET.spec.ts b/packages/client/lib/commands/HGET.spec.ts similarity index 100% rename from lib/commands/HGET.spec.ts rename to packages/client/lib/commands/HGET.spec.ts 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 100% rename from lib/commands/HGETALL.spec.ts rename to packages/client/lib/commands/HGETALL.spec.ts diff --git a/lib/commands/HGETALL.ts b/packages/client/lib/commands/HGETALL.ts similarity index 100% rename from lib/commands/HGETALL.ts rename to packages/client/lib/commands/HGETALL.ts diff --git a/lib/commands/HINCRBY.spec.ts b/packages/client/lib/commands/HINCRBY.spec.ts similarity index 100% rename from lib/commands/HINCRBY.spec.ts rename to packages/client/lib/commands/HINCRBY.spec.ts 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 100% rename from lib/commands/HINCRBYFLOAT.spec.ts rename to packages/client/lib/commands/HINCRBYFLOAT.spec.ts 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 100% rename from lib/commands/HKEYS.spec.ts rename to packages/client/lib/commands/HKEYS.spec.ts 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 100% rename from lib/commands/HLEN.spec.ts rename to packages/client/lib/commands/HLEN.spec.ts 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 100% rename from lib/commands/HMGET.spec.ts rename to packages/client/lib/commands/HMGET.spec.ts 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 100% rename from lib/commands/HRANDFIELD.spec.ts rename to packages/client/lib/commands/HRANDFIELD.spec.ts 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 100% rename from lib/commands/HRANDFIELD_COUNT.spec.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts 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 100% rename from lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts diff --git a/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts similarity index 100% rename from lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts rename to packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts diff --git a/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts similarity index 100% rename from lib/commands/HSCAN.spec.ts rename to packages/client/lib/commands/HSCAN.spec.ts 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 100% rename from lib/commands/HSET.spec.ts rename to packages/client/lib/commands/HSET.spec.ts diff --git a/lib/commands/HSET.ts b/packages/client/lib/commands/HSET.ts similarity index 100% rename from lib/commands/HSET.ts rename to packages/client/lib/commands/HSET.ts diff --git a/lib/commands/HSETNX.spec.ts b/packages/client/lib/commands/HSETNX.spec.ts similarity index 100% rename from lib/commands/HSETNX.spec.ts rename to packages/client/lib/commands/HSETNX.spec.ts diff --git a/lib/commands/HSETNX.ts b/packages/client/lib/commands/HSETNX.ts similarity index 100% rename from lib/commands/HSETNX.ts rename to packages/client/lib/commands/HSETNX.ts diff --git a/lib/commands/HSTRLEN.spec.ts b/packages/client/lib/commands/HSTRLEN.spec.ts similarity index 100% rename from lib/commands/HSTRLEN.spec.ts rename to packages/client/lib/commands/HSTRLEN.spec.ts 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 100% rename from lib/commands/HVALS.spec.ts rename to packages/client/lib/commands/HVALS.spec.ts 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 100% rename from lib/commands/INCR.spec.ts rename to packages/client/lib/commands/INCR.spec.ts 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 100% rename from lib/commands/INCRBY.spec.ts rename to packages/client/lib/commands/INCRBY.spec.ts 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 100% rename from lib/commands/INCRBYFLOAT.spec.ts rename to packages/client/lib/commands/INCRBYFLOAT.spec.ts 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 100% rename from lib/commands/KEYS.spec.ts rename to packages/client/lib/commands/KEYS.spec.ts 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 100% rename from lib/commands/LASTSAVE.spec.ts rename to packages/client/lib/commands/LASTSAVE.spec.ts 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 100% rename from lib/commands/LINDEX.spec.ts rename to packages/client/lib/commands/LINDEX.spec.ts diff --git a/lib/commands/LINDEX.ts b/packages/client/lib/commands/LINDEX.ts similarity index 100% rename from lib/commands/LINDEX.ts rename to packages/client/lib/commands/LINDEX.ts diff --git a/lib/commands/LINSERT.spec.ts b/packages/client/lib/commands/LINSERT.spec.ts similarity index 100% rename from lib/commands/LINSERT.spec.ts rename to packages/client/lib/commands/LINSERT.spec.ts 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 100% rename from lib/commands/LLEN.spec.ts rename to packages/client/lib/commands/LLEN.spec.ts 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 100% rename from lib/commands/LMOVE.spec.ts rename to packages/client/lib/commands/LMOVE.spec.ts 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 100% rename from lib/commands/LOLWUT.spec.ts rename to packages/client/lib/commands/LOLWUT.spec.ts 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 100% rename from lib/commands/LPOP.spec.ts rename to packages/client/lib/commands/LPOP.spec.ts 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 100% rename from lib/commands/LPOP_COUNT.spec.ts rename to packages/client/lib/commands/LPOP_COUNT.spec.ts 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 100% rename from lib/commands/LPOS.spec.ts rename to packages/client/lib/commands/LPOS.spec.ts 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 100% rename from lib/commands/LPOS_COUNT.spec.ts rename to packages/client/lib/commands/LPOS_COUNT.spec.ts 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 100% rename from lib/commands/LPUSH.spec.ts rename to packages/client/lib/commands/LPUSH.spec.ts 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 100% rename from lib/commands/LPUSHX.spec.ts rename to packages/client/lib/commands/LPUSHX.spec.ts 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 100% rename from lib/commands/LRANGE.spec.ts rename to packages/client/lib/commands/LRANGE.spec.ts 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 100% rename from lib/commands/LREM.spec.ts rename to packages/client/lib/commands/LREM.spec.ts 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 100% rename from lib/commands/LSET.spec.ts rename to packages/client/lib/commands/LSET.spec.ts 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 100% rename from lib/commands/LTRIM.spec.ts rename to packages/client/lib/commands/LTRIM.spec.ts diff --git a/lib/commands/LTRIM.ts b/packages/client/lib/commands/LTRIM.ts similarity index 100% rename from lib/commands/LTRIM.ts rename to packages/client/lib/commands/LTRIM.ts diff --git a/lib/commands/MEMORY_DOCTOR.spec.ts b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts similarity index 100% rename from lib/commands/MEMORY_DOCTOR.spec.ts rename to packages/client/lib/commands/MEMORY_DOCTOR.spec.ts 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 100% rename from lib/commands/MEMORY_MALLOC-STATS.spec.ts rename to packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts 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 100% rename from lib/commands/MEMORY_PURGE.spec.ts rename to packages/client/lib/commands/MEMORY_PURGE.spec.ts 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 100% rename from lib/commands/MEMORY_USAGE.spec.ts rename to packages/client/lib/commands/MEMORY_USAGE.spec.ts 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 100% rename from lib/commands/MGET.spec.ts rename to packages/client/lib/commands/MGET.spec.ts 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 100% rename from lib/commands/MOVE.spec.ts rename to packages/client/lib/commands/MOVE.spec.ts diff --git a/lib/commands/MOVE.ts b/packages/client/lib/commands/MOVE.ts similarity index 100% rename from lib/commands/MOVE.ts rename to packages/client/lib/commands/MOVE.ts diff --git a/lib/commands/MSET.spec.ts b/packages/client/lib/commands/MSET.spec.ts similarity index 100% rename from lib/commands/MSET.spec.ts rename to packages/client/lib/commands/MSET.spec.ts 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 100% rename from lib/commands/MSETNX.spec.ts rename to packages/client/lib/commands/MSETNX.spec.ts diff --git a/lib/commands/MSETNX.ts b/packages/client/lib/commands/MSETNX.ts similarity index 100% rename from lib/commands/MSETNX.ts rename to packages/client/lib/commands/MSETNX.ts diff --git a/lib/commands/PERSIST.spec.ts b/packages/client/lib/commands/PERSIST.spec.ts similarity index 100% rename from lib/commands/PERSIST.spec.ts rename to packages/client/lib/commands/PERSIST.spec.ts diff --git a/lib/commands/PERSIST.ts b/packages/client/lib/commands/PERSIST.ts similarity index 100% rename from lib/commands/PERSIST.ts rename to packages/client/lib/commands/PERSIST.ts diff --git a/lib/commands/PEXPIRE.spec.ts b/packages/client/lib/commands/PEXPIRE.spec.ts similarity index 100% rename from lib/commands/PEXPIRE.spec.ts rename to packages/client/lib/commands/PEXPIRE.spec.ts diff --git a/lib/commands/PEXPIRE.ts b/packages/client/lib/commands/PEXPIRE.ts similarity index 100% rename from lib/commands/PEXPIRE.ts rename to packages/client/lib/commands/PEXPIRE.ts diff --git a/lib/commands/PEXPIREAT.spec.ts b/packages/client/lib/commands/PEXPIREAT.spec.ts similarity index 100% rename from lib/commands/PEXPIREAT.spec.ts rename to packages/client/lib/commands/PEXPIREAT.spec.ts diff --git a/lib/commands/PEXPIREAT.ts b/packages/client/lib/commands/PEXPIREAT.ts similarity index 100% rename from lib/commands/PEXPIREAT.ts rename to packages/client/lib/commands/PEXPIREAT.ts diff --git a/lib/commands/PFADD.spec.ts b/packages/client/lib/commands/PFADD.spec.ts similarity index 100% rename from lib/commands/PFADD.spec.ts rename to packages/client/lib/commands/PFADD.spec.ts diff --git a/lib/commands/PFADD.ts b/packages/client/lib/commands/PFADD.ts similarity index 100% rename from lib/commands/PFADD.ts rename to packages/client/lib/commands/PFADD.ts diff --git a/lib/commands/PFCOUNT.spec.ts b/packages/client/lib/commands/PFCOUNT.spec.ts similarity index 100% rename from lib/commands/PFCOUNT.spec.ts rename to packages/client/lib/commands/PFCOUNT.spec.ts 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 100% rename from lib/commands/PFMERGE.spec.ts rename to packages/client/lib/commands/PFMERGE.spec.ts 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 100% rename from lib/commands/PING.spec.ts rename to packages/client/lib/commands/PING.spec.ts 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 100% rename from lib/commands/PSETEX.spec.ts rename to packages/client/lib/commands/PSETEX.spec.ts 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 100% rename from lib/commands/PTTL.spec.ts rename to packages/client/lib/commands/PTTL.spec.ts 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 100% rename from lib/commands/PUBLISH.spec.ts rename to packages/client/lib/commands/PUBLISH.spec.ts 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 100% rename from lib/commands/PUBSUB_CHANNELS.spec.ts rename to packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts 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 100% rename from lib/commands/PUBSUB_NUMPAT.spec.ts rename to packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts 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 100% rename from lib/commands/PUBSUB_NUMSUB.spec.ts rename to packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts 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 100% rename from lib/commands/RANDOMKEY.spec.ts rename to packages/client/lib/commands/RANDOMKEY.spec.ts 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 100% rename from lib/commands/RENAME.spec.ts rename to packages/client/lib/commands/RENAME.spec.ts 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 100% rename from lib/commands/RENAMENX.spec.ts rename to packages/client/lib/commands/RENAMENX.spec.ts diff --git a/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts similarity index 100% rename from lib/commands/RENAMENX.ts rename to packages/client/lib/commands/RENAMENX.ts 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 100% rename from lib/commands/ROLE.spec.ts rename to packages/client/lib/commands/ROLE.spec.ts 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 100% rename from lib/commands/RPOP.spec.ts rename to packages/client/lib/commands/RPOP.spec.ts 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 100% rename from lib/commands/RPOPLPUSH.spec.ts rename to packages/client/lib/commands/RPOPLPUSH.spec.ts 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 100% rename from lib/commands/RPOP_COUNT.spec.ts rename to packages/client/lib/commands/RPOP_COUNT.spec.ts 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 100% rename from lib/commands/RPUSH.spec.ts rename to packages/client/lib/commands/RPUSH.spec.ts 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 100% rename from lib/commands/RPUSHX.spec.ts rename to packages/client/lib/commands/RPUSHX.spec.ts 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 100% rename from lib/commands/SADD.spec.ts rename to packages/client/lib/commands/SADD.spec.ts 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 100% rename from lib/commands/SCAN.spec.ts rename to packages/client/lib/commands/SCAN.spec.ts 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 100% rename from lib/commands/SCARD.spec.ts rename to packages/client/lib/commands/SCARD.spec.ts 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 100% rename from lib/commands/SCRIPT_DEBUG.spec.ts rename to packages/client/lib/commands/SCRIPT_DEBUG.spec.ts 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 100% rename from lib/commands/SCRIPT_EXISTS.spec.ts rename to packages/client/lib/commands/SCRIPT_EXISTS.spec.ts diff --git a/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts similarity index 100% rename from lib/commands/SCRIPT_EXISTS.ts rename to packages/client/lib/commands/SCRIPT_EXISTS.ts diff --git a/lib/commands/SCRIPT_FLUSH.spec.ts b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts similarity index 100% rename from lib/commands/SCRIPT_FLUSH.spec.ts rename to packages/client/lib/commands/SCRIPT_FLUSH.spec.ts 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 100% rename from lib/commands/SCRIPT_LOAD.spec.ts rename to packages/client/lib/commands/SCRIPT_LOAD.spec.ts 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 100% rename from lib/commands/SDIFF.spec.ts rename to packages/client/lib/commands/SDIFF.spec.ts 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 100% rename from lib/commands/SDIFFSTORE.spec.ts rename to packages/client/lib/commands/SDIFFSTORE.spec.ts 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 100% rename from lib/commands/SET.spec.ts rename to packages/client/lib/commands/SET.spec.ts diff --git a/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts similarity index 100% rename from lib/commands/SET.ts rename to packages/client/lib/commands/SET.ts diff --git a/lib/commands/SETBIT.spec.ts b/packages/client/lib/commands/SETBIT.spec.ts similarity index 100% rename from lib/commands/SETBIT.spec.ts rename to packages/client/lib/commands/SETBIT.spec.ts 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 100% rename from lib/commands/SETEX.spec.ts rename to packages/client/lib/commands/SETEX.spec.ts 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 100% rename from lib/commands/SETNX .spec.ts rename to packages/client/lib/commands/SETNX .spec.ts diff --git a/lib/commands/SETNX.ts b/packages/client/lib/commands/SETNX.ts similarity index 100% rename from lib/commands/SETNX.ts rename to packages/client/lib/commands/SETNX.ts diff --git a/lib/commands/SETRANGE.spec.ts b/packages/client/lib/commands/SETRANGE.spec.ts similarity index 100% rename from lib/commands/SETRANGE.spec.ts rename to packages/client/lib/commands/SETRANGE.spec.ts 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 100% rename from lib/commands/SINTER.spec.ts rename to packages/client/lib/commands/SINTER.spec.ts 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 100% rename from lib/commands/SINTERSTORE.spec.ts rename to packages/client/lib/commands/SINTERSTORE.spec.ts 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 100% rename from lib/commands/SISMEMBER.spec.ts rename to packages/client/lib/commands/SISMEMBER.spec.ts diff --git a/lib/commands/SISMEMBER.ts b/packages/client/lib/commands/SISMEMBER.ts similarity index 100% rename from lib/commands/SISMEMBER.ts rename to packages/client/lib/commands/SISMEMBER.ts diff --git a/lib/commands/SMEMBERS.spec.ts b/packages/client/lib/commands/SMEMBERS.spec.ts similarity index 100% rename from lib/commands/SMEMBERS.spec.ts rename to packages/client/lib/commands/SMEMBERS.spec.ts 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 100% rename from lib/commands/SMISMEMBER.spec.ts rename to packages/client/lib/commands/SMISMEMBER.spec.ts diff --git a/lib/commands/SMISMEMBER.ts b/packages/client/lib/commands/SMISMEMBER.ts similarity index 100% rename from lib/commands/SMISMEMBER.ts rename to packages/client/lib/commands/SMISMEMBER.ts diff --git a/lib/commands/SMOVE.spec.ts b/packages/client/lib/commands/SMOVE.spec.ts similarity index 100% rename from lib/commands/SMOVE.spec.ts rename to packages/client/lib/commands/SMOVE.spec.ts diff --git a/lib/commands/SMOVE.ts b/packages/client/lib/commands/SMOVE.ts similarity index 100% rename from lib/commands/SMOVE.ts rename to packages/client/lib/commands/SMOVE.ts diff --git a/lib/commands/SORT.spec.ts b/packages/client/lib/commands/SORT.spec.ts similarity index 100% rename from lib/commands/SORT.spec.ts rename to packages/client/lib/commands/SORT.spec.ts 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 100% rename from lib/commands/SPOP.spec.ts rename to packages/client/lib/commands/SPOP.spec.ts 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 100% rename from lib/commands/SRANDMEMBER.spec.ts rename to packages/client/lib/commands/SRANDMEMBER.spec.ts 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 100% rename from lib/commands/SRANDMEMBER_COUNT.spec.ts rename to packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts 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 100% rename from lib/commands/SREM.spec.ts rename to packages/client/lib/commands/SREM.spec.ts 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 100% rename from lib/commands/SSCAN.spec.ts rename to packages/client/lib/commands/SSCAN.spec.ts 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 100% rename from lib/commands/STRLEN.spec.ts rename to packages/client/lib/commands/STRLEN.spec.ts 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 100% rename from lib/commands/SUNION.spec.ts rename to packages/client/lib/commands/SUNION.spec.ts 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 100% rename from lib/commands/SUNIONSTORE.spec.ts rename to packages/client/lib/commands/SUNIONSTORE.spec.ts 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 100% rename from lib/commands/SWAPDB.spec.ts rename to packages/client/lib/commands/SWAPDB.spec.ts 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 55% rename from lib/commands/TIME.spec.ts rename to packages/client/lib/commands/TIME.spec.ts index bbaa7942db..1139d18d53 100644 --- a/lib/commands/TIME.spec.ts +++ b/packages/client/lib/commands/TIME.spec.ts @@ -10,9 +10,9 @@ describe('TIME', () => { ); }); - 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); + // 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 100% rename from lib/commands/TOUCH.spec.ts rename to packages/client/lib/commands/TOUCH.spec.ts 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 100% rename from lib/commands/TTL.spec.ts rename to packages/client/lib/commands/TTL.spec.ts 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 100% rename from lib/commands/TYPE.spec.ts rename to packages/client/lib/commands/TYPE.spec.ts 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 100% rename from lib/commands/UNLINK.spec.ts rename to packages/client/lib/commands/UNLINK.spec.ts 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 100% rename from lib/commands/UNWATCH.spec.ts rename to packages/client/lib/commands/UNWATCH.spec.ts 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 100% rename from lib/commands/WAIT.spec.ts rename to packages/client/lib/commands/WAIT.spec.ts 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 100% rename from lib/commands/XACK.spec.ts rename to packages/client/lib/commands/XACK.spec.ts 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 100% rename from lib/commands/XADD.spec.ts rename to packages/client/lib/commands/XADD.spec.ts 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 100% rename from lib/commands/XAUTOCLAIM.spec.ts rename to packages/client/lib/commands/XAUTOCLAIM.spec.ts 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 100% rename from lib/commands/XAUTOCLAIM_JUSTID.spec.ts rename to packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts 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 100% rename from lib/commands/XCLAIM.spec.ts rename to packages/client/lib/commands/XCLAIM.spec.ts diff --git a/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts similarity index 100% rename from lib/commands/XCLAIM.ts rename to packages/client/lib/commands/XCLAIM.ts diff --git a/lib/commands/XCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts similarity index 100% rename from lib/commands/XCLAIM_JUSTID.spec.ts rename to packages/client/lib/commands/XCLAIM_JUSTID.spec.ts 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 100% rename from lib/commands/XDEL.spec.ts rename to packages/client/lib/commands/XDEL.spec.ts 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 100% rename from lib/commands/XGROUP_CREATE.spec.ts rename to packages/client/lib/commands/XGROUP_CREATE.spec.ts 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 100% rename from lib/commands/XGROUP_CREATECONSUMER.spec.ts rename to packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts diff --git a/lib/commands/XGROUP_CREATECONSUMER.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts similarity index 100% rename from lib/commands/XGROUP_CREATECONSUMER.ts rename to packages/client/lib/commands/XGROUP_CREATECONSUMER.ts diff --git a/lib/commands/XGROUP_DELCONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts similarity index 100% rename from lib/commands/XGROUP_DELCONSUMER.spec.ts rename to packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts 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 100% rename from lib/commands/XGROUP_DESTROY.spec.ts rename to packages/client/lib/commands/XGROUP_DESTROY.spec.ts diff --git a/lib/commands/XGROUP_DESTROY.ts b/packages/client/lib/commands/XGROUP_DESTROY.ts similarity index 100% rename from lib/commands/XGROUP_DESTROY.ts rename to packages/client/lib/commands/XGROUP_DESTROY.ts diff --git a/lib/commands/XGROUP_SETID.spec.ts b/packages/client/lib/commands/XGROUP_SETID.spec.ts similarity index 100% rename from lib/commands/XGROUP_SETID.spec.ts rename to packages/client/lib/commands/XGROUP_SETID.spec.ts 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 100% rename from lib/commands/XINFO_CONSUMERS.spec.ts rename to packages/client/lib/commands/XINFO_CONSUMERS.spec.ts 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 100% rename from lib/commands/XINFO_GROUPS.spec.ts rename to packages/client/lib/commands/XINFO_GROUPS.spec.ts 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 100% rename from lib/commands/XINFO_STREAM.spec.ts rename to packages/client/lib/commands/XINFO_STREAM.spec.ts 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 100% rename from lib/commands/XLEN.spec.ts rename to packages/client/lib/commands/XLEN.spec.ts 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 100% rename from lib/commands/XPENDING.spec.ts rename to packages/client/lib/commands/XPENDING.spec.ts 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 100% rename from lib/commands/XPENDING_RANGE.spec.ts rename to packages/client/lib/commands/XPENDING_RANGE.spec.ts diff --git a/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts similarity index 100% rename from lib/commands/XPENDING_RANGE.ts rename to packages/client/lib/commands/XPENDING_RANGE.ts diff --git a/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts similarity index 100% rename from lib/commands/XRANGE.spec.ts rename to packages/client/lib/commands/XRANGE.spec.ts diff --git a/lib/commands/XRANGE.ts b/packages/client/lib/commands/XRANGE.ts similarity index 100% rename from lib/commands/XRANGE.ts rename to packages/client/lib/commands/XRANGE.ts diff --git a/lib/commands/XREAD.spec.ts b/packages/client/lib/commands/XREAD.spec.ts similarity index 100% rename from lib/commands/XREAD.spec.ts rename to packages/client/lib/commands/XREAD.spec.ts diff --git a/lib/commands/XREAD.ts b/packages/client/lib/commands/XREAD.ts similarity index 100% rename from lib/commands/XREAD.ts rename to packages/client/lib/commands/XREAD.ts diff --git a/lib/commands/XREADGROUP.spec.ts b/packages/client/lib/commands/XREADGROUP.spec.ts similarity index 100% rename from lib/commands/XREADGROUP.spec.ts rename to packages/client/lib/commands/XREADGROUP.spec.ts diff --git a/lib/commands/XREADGROUP.ts b/packages/client/lib/commands/XREADGROUP.ts similarity index 100% rename from lib/commands/XREADGROUP.ts rename to packages/client/lib/commands/XREADGROUP.ts diff --git a/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts similarity index 100% rename from lib/commands/XREVRANGE.spec.ts rename to packages/client/lib/commands/XREVRANGE.spec.ts diff --git a/lib/commands/XREVRANGE.ts b/packages/client/lib/commands/XREVRANGE.ts similarity index 100% rename from lib/commands/XREVRANGE.ts rename to packages/client/lib/commands/XREVRANGE.ts diff --git a/lib/commands/XTRIM.spec.ts b/packages/client/lib/commands/XTRIM.spec.ts similarity index 100% rename from lib/commands/XTRIM.spec.ts rename to packages/client/lib/commands/XTRIM.spec.ts 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 100% rename from lib/commands/ZADD.spec.ts rename to packages/client/lib/commands/ZADD.spec.ts diff --git a/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts similarity index 100% rename from lib/commands/ZADD.ts rename to packages/client/lib/commands/ZADD.ts diff --git a/lib/commands/ZCARD.spec.ts b/packages/client/lib/commands/ZCARD.spec.ts similarity index 100% rename from lib/commands/ZCARD.spec.ts rename to packages/client/lib/commands/ZCARD.spec.ts 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 100% rename from lib/commands/ZCOUNT.spec.ts rename to packages/client/lib/commands/ZCOUNT.spec.ts diff --git a/lib/commands/ZCOUNT.ts b/packages/client/lib/commands/ZCOUNT.ts similarity index 100% rename from lib/commands/ZCOUNT.ts rename to packages/client/lib/commands/ZCOUNT.ts diff --git a/lib/commands/ZDIFF.spec.ts b/packages/client/lib/commands/ZDIFF.spec.ts similarity index 100% rename from lib/commands/ZDIFF.spec.ts rename to packages/client/lib/commands/ZDIFF.spec.ts 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 100% rename from lib/commands/ZDIFFSTORE.spec.ts rename to packages/client/lib/commands/ZDIFFSTORE.spec.ts 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 100% rename from lib/commands/ZDIFF_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts diff --git a/lib/commands/ZDIFF_WITHSCORES.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts similarity index 100% rename from lib/commands/ZDIFF_WITHSCORES.ts rename to packages/client/lib/commands/ZDIFF_WITHSCORES.ts diff --git a/lib/commands/ZINCRBY.spec.ts b/packages/client/lib/commands/ZINCRBY.spec.ts similarity index 100% rename from lib/commands/ZINCRBY.spec.ts rename to packages/client/lib/commands/ZINCRBY.spec.ts diff --git a/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts similarity index 100% rename from lib/commands/ZINCRBY.ts rename to packages/client/lib/commands/ZINCRBY.ts diff --git a/lib/commands/ZINTER.spec.ts b/packages/client/lib/commands/ZINTER.spec.ts similarity index 100% rename from lib/commands/ZINTER.spec.ts rename to packages/client/lib/commands/ZINTER.spec.ts 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 100% rename from lib/commands/ZINTERSTORE.spec.ts rename to packages/client/lib/commands/ZINTERSTORE.spec.ts 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 100% rename from lib/commands/ZINTER_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts diff --git a/lib/commands/ZINTER_WITHSCORES.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.ts similarity index 100% rename from lib/commands/ZINTER_WITHSCORES.ts rename to packages/client/lib/commands/ZINTER_WITHSCORES.ts diff --git a/lib/commands/ZLEXCOUNT.spec.ts b/packages/client/lib/commands/ZLEXCOUNT.spec.ts similarity index 100% rename from lib/commands/ZLEXCOUNT.spec.ts rename to packages/client/lib/commands/ZLEXCOUNT.spec.ts 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 100% rename from lib/commands/ZMSCORE.spec.ts rename to packages/client/lib/commands/ZMSCORE.spec.ts diff --git a/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts similarity index 100% rename from lib/commands/ZMSCORE.ts rename to packages/client/lib/commands/ZMSCORE.ts diff --git a/lib/commands/ZPOPMAX.spec.ts b/packages/client/lib/commands/ZPOPMAX.spec.ts similarity index 100% rename from lib/commands/ZPOPMAX.spec.ts rename to packages/client/lib/commands/ZPOPMAX.spec.ts 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 100% rename from lib/commands/ZPOPMAX_COUNT.spec.ts rename to packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts diff --git a/lib/commands/ZPOPMAX_COUNT.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.ts similarity index 100% rename from lib/commands/ZPOPMAX_COUNT.ts rename to packages/client/lib/commands/ZPOPMAX_COUNT.ts diff --git a/lib/commands/ZPOPMIN.spec.ts b/packages/client/lib/commands/ZPOPMIN.spec.ts similarity index 100% rename from lib/commands/ZPOPMIN.spec.ts rename to packages/client/lib/commands/ZPOPMIN.spec.ts 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 100% rename from lib/commands/ZPOPMIN_COUNT.spec.ts rename to packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts diff --git a/lib/commands/ZPOPMIN_COUNT.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.ts similarity index 100% rename from lib/commands/ZPOPMIN_COUNT.ts rename to packages/client/lib/commands/ZPOPMIN_COUNT.ts diff --git a/lib/commands/ZRANDMEMBER.spec.ts b/packages/client/lib/commands/ZRANDMEMBER.spec.ts similarity index 100% rename from lib/commands/ZRANDMEMBER.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER.spec.ts 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 100% rename from lib/commands/ZRANDMEMBER_COUNT.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts 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 100% rename from lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts diff --git a/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts similarity index 100% rename from lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts rename to packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts diff --git a/lib/commands/ZRANGE.spec.ts b/packages/client/lib/commands/ZRANGE.spec.ts similarity index 100% rename from lib/commands/ZRANGE.spec.ts rename to packages/client/lib/commands/ZRANGE.spec.ts diff --git a/lib/commands/ZRANGE.ts b/packages/client/lib/commands/ZRANGE.ts similarity index 100% rename from lib/commands/ZRANGE.ts rename to packages/client/lib/commands/ZRANGE.ts diff --git a/lib/commands/ZRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts similarity index 100% rename from lib/commands/ZRANGEBYLEX.spec.ts rename to packages/client/lib/commands/ZRANGEBYLEX.spec.ts diff --git a/lib/commands/ZRANGEBYLEX.ts b/packages/client/lib/commands/ZRANGEBYLEX.ts similarity index 100% rename from lib/commands/ZRANGEBYLEX.ts rename to packages/client/lib/commands/ZRANGEBYLEX.ts diff --git a/lib/commands/ZRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts similarity index 100% rename from lib/commands/ZRANGEBYSCORE.spec.ts rename to packages/client/lib/commands/ZRANGEBYSCORE.spec.ts diff --git a/lib/commands/ZRANGEBYSCORE.ts b/packages/client/lib/commands/ZRANGEBYSCORE.ts similarity index 100% rename from lib/commands/ZRANGEBYSCORE.ts rename to packages/client/lib/commands/ZRANGEBYSCORE.ts diff --git a/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts similarity index 100% rename from lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts diff --git a/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts similarity index 100% rename from lib/commands/ZRANGEBYSCORE_WITHSCORES.ts rename to packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts diff --git a/lib/commands/ZRANGESTORE.spec.ts b/packages/client/lib/commands/ZRANGESTORE.spec.ts similarity index 100% rename from lib/commands/ZRANGESTORE.spec.ts rename to packages/client/lib/commands/ZRANGESTORE.spec.ts diff --git a/lib/commands/ZRANGESTORE.ts b/packages/client/lib/commands/ZRANGESTORE.ts similarity index 100% rename from lib/commands/ZRANGESTORE.ts rename to packages/client/lib/commands/ZRANGESTORE.ts diff --git a/lib/commands/ZRANGE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts similarity index 100% rename from lib/commands/ZRANGE_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts diff --git a/lib/commands/ZRANGE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts similarity index 100% rename from lib/commands/ZRANGE_WITHSCORES.ts rename to packages/client/lib/commands/ZRANGE_WITHSCORES.ts diff --git a/lib/commands/ZRANK.spec.ts b/packages/client/lib/commands/ZRANK.spec.ts similarity index 100% rename from lib/commands/ZRANK.spec.ts rename to packages/client/lib/commands/ZRANK.spec.ts 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 100% rename from lib/commands/ZREM.spec.ts rename to packages/client/lib/commands/ZREM.spec.ts 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 100% rename from lib/commands/ZREMRANGEBYLEX.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts 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 100% rename from lib/commands/ZREMRANGEBYRANK.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts 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 100% rename from lib/commands/ZREMRANGEBYSCORE.spec.ts rename to packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts 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 100% rename from lib/commands/ZREVRANK.spec.ts rename to packages/client/lib/commands/ZREVRANK.spec.ts 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 100% rename from lib/commands/ZSCAN.spec.ts rename to packages/client/lib/commands/ZSCAN.spec.ts 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 100% rename from lib/commands/ZSCORE.spec.ts rename to packages/client/lib/commands/ZSCORE.spec.ts diff --git a/lib/commands/ZSCORE.ts b/packages/client/lib/commands/ZSCORE.ts similarity index 100% rename from lib/commands/ZSCORE.ts rename to packages/client/lib/commands/ZSCORE.ts diff --git a/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts similarity index 100% rename from lib/commands/ZUNION.spec.ts rename to packages/client/lib/commands/ZUNION.spec.ts 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 100% rename from lib/commands/ZUNIONSTORE.spec.ts rename to packages/client/lib/commands/ZUNIONSTORE.spec.ts 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 100% rename from lib/commands/ZUNION_WITHSCORES.spec.ts rename to packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts diff --git a/lib/commands/ZUNION_WITHSCORES.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.ts similarity index 100% rename from lib/commands/ZUNION_WITHSCORES.ts rename to packages/client/lib/commands/ZUNION_WITHSCORES.ts diff --git a/lib/commands/generic-transformers.spec.ts b/packages/client/lib/commands/generic-transformers.spec.ts similarity index 100% rename from lib/commands/generic-transformers.spec.ts rename to packages/client/lib/commands/generic-transformers.spec.ts diff --git a/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts similarity index 100% rename from lib/commands/generic-transformers.ts rename to packages/client/lib/commands/generic-transformers.ts 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 100% rename from lib/errors.ts rename to packages/client/lib/errors.ts 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/lib/test-utils/index.ts b/packages/client/lib/test-utils.ts similarity index 93% rename from lib/test-utils/index.ts rename to packages/client/lib/test-utils.ts index 69bfc440c9..85057da841 100644 --- a/lib/test-utils/index.ts +++ b/packages/client/lib/test-utils.ts @@ -1,6 +1,6 @@ -import TestUtils from './test-utils'; +import TestUtils from '@redis/test-utils'; import { SinonSpy } from 'sinon'; -import { promiseTimeout } from '../utils'; +import { promiseTimeout } from './utils'; export default new TestUtils({ defaultDockerVersion: '6.2', 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/ts-declarations/redis-parser.d.ts b/packages/client/lib/ts-declarations/redis-parser.d.ts similarity index 100% rename from lib/ts-declarations/redis-parser.d.ts rename to packages/client/lib/ts-declarations/redis-parser.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 0000000000..30be25d26a --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,49 @@ +{ + "name": "@redis/client", + "version": "4.0.0-rc.3", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "test": "nyc -r text-summary -r html 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", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "@types/sinon": "^10.0.6", + "@types/yallist": "^4.0.1", + "@typescript-eslint/eslint-plugin": "^5.2.0", + "@typescript-eslint/parser": "^5.2.0", + "eslint": "^8.1.0", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "sinon": "^11.1.2", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typedoc": "^0.22.7", + "typedoc-github-wiki-theme": "^0.6.0", + "typedoc-plugin-markdown": "^3.11.3", + "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" +} diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 0000000000..1700c9097b --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.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/.nycrc.json b/packages/json/.nycrc.json new file mode 100644 index 0000000000..b4e671e178 --- /dev/null +++ b/packages/json/.nycrc.json @@ -0,0 +1,4 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "exclude": ["**/*.spec.ts", "lib/test-utils.ts"] +} diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts new file mode 100644 index 0000000000..ab53837a00 --- /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 0000000000..2935d19299 --- /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 0000000000..7a47d67126 --- /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 0000000000..5860b59cb3 --- /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 0000000000..4b9d58b2ca --- /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 0000000000..8585765701 --- /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 0000000000..f0a3ec40a4 --- /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 0000000000..818397b7f8 --- /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 0000000000..a80b8c3cbc --- /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 0000000000..5d8785a8d9 --- /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 0000000000..c254e1b6a0 --- /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 0000000000..2de444eeeb --- /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 0000000000..468c994f2f --- /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 0000000000..da60b1d952 --- /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 0000000000..a957b9584a --- /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 0000000000..090d4dbe85 --- /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 0000000000..923bb997fc --- /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 0000000000..cb2df3d605 --- /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 0000000000..ed831689a9 --- /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 0000000000..8b69dc8053 --- /dev/null +++ b/packages/json/lib/commands/GET.ts @@ -0,0 +1,41 @@ +import { pushVerdictArguments } from '@redis/client/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 0000000000..456e160dd5 --- /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 0000000000..582b73bf85 --- /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 0000000000..56dede68bd --- /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 0000000000..e3d8887ea3 --- /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 0000000000..3e2581a3cd --- /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 0000000000..2082916619 --- /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 0000000000..6288c11239 --- /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 0000000000..a9465c9160 --- /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 0000000000..35b6589c87 --- /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 0000000000..aa800e97f7 --- /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 0000000000..8b70962d1c --- /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 0000000000..2b56bf1f05 --- /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 0000000000..8f8586a204 --- /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 0000000000..f50a42bf5d --- /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 0000000000..a37eaa1d91 --- /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 0000000000..eea384c93f --- /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 0000000000..cf163d3c19 --- /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 0000000000..93f5d563ba --- /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 0000000000..5cecfb827a --- /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 0000000000..7fd55f625d --- /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 0000000000..91b4f7dc4b --- /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 0000000000..bc0e103e8c --- /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 0000000000..140e781d91 --- /dev/null +++ b/packages/json/lib/test-utils.ts @@ -0,0 +1,21 @@ +import TestUtils from '@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 0000000000..ebd7f8f76f --- /dev/null +++ b/packages/json/package.json @@ -0,0 +1,24 @@ +{ + "name": "@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 html mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "build": "tsc" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } +} diff --git a/packages/json/tsconfig.json b/packages/json/tsconfig.json new file mode 100644 index 0000000000..fdb86c004c --- /dev/null +++ b/packages/json/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./lib/**/*.ts" + ] +} diff --git a/packages/search/.nycrc.json b/packages/search/.nycrc.json new file mode 100644 index 0000000000..b4e671e178 --- /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/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts new file mode 100644 index 0000000000..2a6647c97a --- /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 0000000000..affc98b51d --- /dev/null +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -0,0 +1,283 @@ +import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { pushVerdictArgument, transformReplyTuples, TuplesObject } from '@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 0000000000..7bb2452838 --- /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 0000000000..552c1add69 --- /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 0000000000..5255ba835d --- /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 0000000000..434b4df3de --- /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 0000000000..79421b1a20 --- /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 0000000000..ac64ef57c3 --- /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 0000000000..8614f44342 --- /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 0000000000..fbf1f1164b --- /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 0000000000..59cb63a3d8 --- /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 0000000000..93b76d79ed --- /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 0000000000..2ac68cc971 --- /dev/null +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -0,0 +1,347 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { RedisSearchLanguages, SchemaFieldTypes, SchemaTextFieldPhonetics, transformArguments } from './CREATE'; + +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'] + ); + }); + }); + + 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'] + ); + }); + + it('with CASESENSITIVE', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + CASESENSITIVE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'CASESENSITIVE'] + ); + }); + + 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 0000000000..94c063ec50 --- /dev/null +++ b/packages/search/lib/commands/CREATE.ts @@ -0,0 +1,222 @@ +import { pushOptionalVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { PropertyName } from '.'; + +export enum SchemaFieldTypes { + TEXT = 'TEXT', + NUMERIC = 'NUMERIC', + GEO = 'GEO', + TAG = 'TAG', +} + +type CreateSchemaField> = T | ({ + type: T; + AS?: string; + CASESENSITIVE?: true; + 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 +} + +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' +} + +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); + } + + break; + } + + if (fieldOptions.CASESENSITIVE) { + args.push('CASESENSITIVE'); + } + + 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 0000000000..b5f29dd408 --- /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 0000000000..60af11fd41 --- /dev/null +++ b/packages/search/lib/commands/DICTADD.ts @@ -0,0 +1,8 @@ +import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { pushVerdictArguments } from '@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 0000000000..5ffa6b6b84 --- /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 0000000000..a1b728f192 --- /dev/null +++ b/packages/search/lib/commands/DICTDEL.ts @@ -0,0 +1,8 @@ +import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { pushVerdictArguments } from '@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 0000000000..9896fb9440 --- /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 0000000000..1427bb42cb --- /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 0000000000..751e274ba6 --- /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 0000000000..7897a9dd82 --- /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 0000000000..dd55e03871 --- /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 0000000000..c41cd9a4aa --- /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 0000000000..238ef44eaa --- /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 0000000000..db97fb9c8d --- /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 0000000000..fa50a4b0cd --- /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 0000000000..42451114c8 --- /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 0000000000..e315ea5230 --- /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 0000000000..efe9c899ac --- /dev/null +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -0,0 +1,243 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { RedisSearchLanguages, 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 0000000000..6b14a0a18f --- /dev/null +++ b/packages/search/lib/commands/SEARCH.ts @@ -0,0 +1,202 @@ +import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { pushOptionalVerdictArgument, pushVerdictArgument, transformReplyTuples } from '@redis/client/dist/lib/commands/generic-transformers'; +import { type } from 'os'; +import { PropertyName, pushSortByArguments, SortByOptions } from '.'; +import { RedisSearchLanguages } from './CREATE'; + +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 0000000000..bacbe118b3 --- /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 0000000000..ae4cb3cdce --- /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 0000000000..23294eb4ab --- /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 0000000000..d68f0d9884 --- /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 0000000000..3d89e3b9a7 --- /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 0000000000..be2d4262ca --- /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 '@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 0000000000..c24c2ff086 --- /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 0000000000..558cedeaa0 --- /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 0000000000..a4a87ebe89 --- /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 0000000000..7eaff4697e --- /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 0000000000..e60daa917a --- /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 0000000000..bad5bff299 --- /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 0000000000..0900d91b8d --- /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 0000000000..3b2fe7667b --- /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 0000000000..2ea680df95 --- /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 0000000000..15b3da6126 --- /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 0000000000..4b0cb0c8b3 --- /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 0000000000..5f1e71aaf7 --- /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 0000000000..bf7fed8493 --- /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 0000000000..3384ea59d9 --- /dev/null +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -0,0 +1,23 @@ +import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisCommandArguments } from '@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 0000000000..1f90939bb0 --- /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 0000000000..54342f0c9e --- /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 0000000000..602c29975f --- /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 0000000000..588ec837c3 --- /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 0000000000..f0afa304a9 --- /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 0000000000..f54a71e0e0 --- /dev/null +++ b/packages/search/lib/commands/index.ts @@ -0,0 +1,133 @@ +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 '@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 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 0000000000..bc0e103e8c --- /dev/null +++ b/packages/search/lib/index.ts @@ -0,0 +1 @@ +export { default } from './commands'; diff --git a/packages/search/lib/test-utils.ts b/packages/search/lib/test-utils.ts new file mode 100644 index 0000000000..c68504c21d --- /dev/null +++ b/packages/search/lib/test-utils.ts @@ -0,0 +1,21 @@ +import TestUtils from '@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 0000000000..dc435cbd36 --- /dev/null +++ b/packages/search/package.json @@ -0,0 +1,24 @@ +{ + "name": "@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 html mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "build": "tsc" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@redis/test-utils": "*", + "@types/node": "^16.11.6", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "source-map-support": "^0.5.20", + "ts-node": "^10.4.0", + "typescript": "^4.4.4" + } +} diff --git a/packages/search/tsconfig.json b/packages/search/tsconfig.json new file mode 100644 index 0000000000..fdb86c004c --- /dev/null +++ b/packages/search/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "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 0000000000..23fc0b3a51 --- /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 0000000000..244977e83c --- /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/lib/test-utils/dockers.ts b/packages/test-utils/lib/dockers.ts similarity index 90% rename from lib/test-utils/dockers.ts rename to packages/test-utils/lib/dockers.ts index 3e48618ee4..28bd1e4905 100644 --- a/lib/test-utils/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -1,8 +1,9 @@ import { createConnection } from 'net'; import { once } from 'events'; -import { RedisModules, RedisScripts } from '../commands'; -import RedisClient, { RedisClientType } from '../client'; -import { promiseTimeout } from '../utils'; +import { RedisModules, RedisScripts } from '@redis/client/lib/commands'; +import RedisClient, { RedisClientType } from '@redis/client/lib/client'; +import { promiseTimeout } from '@redis/client/lib/utils'; +import path from 'path'; import { promisify } from 'util'; import { exec } from 'child_process'; const execAsync = promisify(exec); @@ -45,11 +46,17 @@ export interface RedisServerDocker { 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 ${image}:${version.join('.')} ` + - `--save --port ${port.toString()} ${serverArguments.join(' ')}` + '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) { diff --git a/lib/test-utils/test-utils.ts b/packages/test-utils/lib/index.ts similarity index 83% rename from lib/test-utils/test-utils.ts rename to packages/test-utils/lib/index.ts index a550e3f707..d6692cace6 100644 --- a/lib/test-utils/test-utils.ts +++ b/packages/test-utils/lib/index.ts @@ -1,10 +1,18 @@ -import { RedisModules, RedisScripts } from '../commands'; -import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; -import RedisCluster, { RedisClusterOptions, RedisClusterType } from '../cluster'; +import { RedisModules, RedisScripts } from '@redis/client/lib/commands'; +import RedisClient, { RedisClientOptions, RedisClientType } from '@redis/client/lib/client'; +import RedisCluster, { RedisClusterOptions, RedisClusterType } from '@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; } @@ -20,20 +28,14 @@ interface ClusterTestOptions ext clusterConfiguration?: Partial>; } -interface TestsUtilsConfig { - dockerImageName: string; - dockerImageVersionArgument: string; - defaultDockerVersion: string; -} - -export default class TestUtils { - static #getVersion(config: TestsUtilsConfig): Array { +export default class TestUtils { + static #getVersion(argumentName: string, defaultVersion: string): Array { return yargs(hideBin(process.argv)) - .option('redis-version', { + .option(argumentName, { type: 'string', - default: config.defaultDockerVersion + default: defaultVersion }) - .coerce(config.dockerImageVersionArgument, (arg: string) => { + .coerce(argumentName, (arg: string) => { return arg.split('.').map(x => { const value = Number(x); if (Number.isNaN(value)) { @@ -43,16 +45,16 @@ export default class TestUtils { return value; }); }) - .demandOption(config.dockerImageVersionArgument) - .parseSync()[config.dockerImageVersionArgument]; + .demandOption(argumentName) + .parseSync()[argumentName]; } readonly #DOCKER_IMAGE: RedisServerDockerConfig; - constructor(config: TestsUtilsConfig) { + constructor(config: TestUtilsConfig) { this.#DOCKER_IMAGE = { image: config.dockerImageName, - version: TestUtils.#getVersion(config) + version: TestUtils.#getVersion(config.dockerImageVersionArgument, config.defaultDockerVersion) }; } @@ -84,7 +86,7 @@ export default class TestUtils { title: string, fn: (client: RedisClientType) => Promise, options: ClientTestOptions - ): Mocha.Test { + ): void { let dockerPromise: ReturnType; if (this.isVersionGreaterThan(options.minimumDockerVersion)) { const dockerImage = this.#DOCKER_IMAGE; @@ -96,7 +98,7 @@ export default class TestUtils { }); } - return it(title, async function() { + it(title, async function() { if (!dockerPromise) return this.skip(); const client = RedisClient.create({ @@ -111,10 +113,10 @@ export default class TestUtils { return fn(client); } - try { - await client.connect(); - await client.flushAll(); + await client.connect(); + try { + await client.flushAll(); await fn(client); } finally { if (client.isOpen) { @@ -135,7 +137,7 @@ export default class TestUtils { title: string, fn: (cluster: RedisClusterType) => Promise, options: ClusterTestOptions - ): Mocha.Test { + ): void { let dockersPromise: ReturnType; if (this.isVersionGreaterThan(options.minimumDockerVersion)) { const dockerImage = this.#DOCKER_IMAGE; @@ -147,7 +149,7 @@ export default class TestUtils { }); } - return it(title, async function () { + it(title, async function () { if (!dockersPromise) return this.skip(); const dockers = await dockersPromise, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json new file mode 100644 index 0000000000..0c934ace9f --- /dev/null +++ b/packages/test-utils/package.json @@ -0,0 +1,27 @@ +{ + "name": "@redis/test-utils", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsc", + "test": "echo \"TODO\"" + }, + "peerDependencies": { + "@redis/client": "^4.0.0-rc" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@tsconfig/node12": "^1.0.9", + "@types/mocha": "^9.0.0", + "@types/node": "^16.11.6", + "@types/yargs": "^17.0.5", + "mocha": "^9.1.3", + "nyc": "^15.1.0", + "release-it": "^14.11.6", + "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 0000000000..fdb86c004c --- /dev/null +++ b/packages/test-utils/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "./dist" + }, + "include": [ + "./lib/**/*.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 1f76310034..fa46effbdc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,33 +1,15 @@ { - "extends": "@tsconfig/node12/tsconfig.json", + "extends": "@tsconfig/node12/tsconfig", "compilerOptions": { - "outDir": "./dist", "declaration": true, - "useDefineForClassFields": true, - "allowJs": true + "allowJs": true, + "useDefineForClassFields": true }, "files": [ - "./lib/ts-declarations/cluster-key-slot.d.ts", - "./lib/ts-declarations/redis-parser.d.ts" - ], - "include": [ - "./index.ts", - "./lib/**/*.ts" + "./packages/client/lib/ts-declarations/cluster-key-slot.d.ts", + "./packages/client/lib/ts-declarations/redis-parser.d.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" } }