From 935993a84ae3d1e2dfcd8da5622feb67ede338f4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 5 Apr 2023 13:03:44 -0400 Subject: [PATCH 001/325] wip --- md/RESP3.md | 32 ++++++++++++++++++ md/v4-to-v5.md | 75 +++++++++++++++++++++++++++++++++++++++++++ md/v5-new-features.md | 30 +++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 md/RESP3.md create mode 100644 md/v4-to-v5.md create mode 100644 md/v5-new-features.md diff --git a/md/RESP3.md b/md/RESP3.md new file mode 100644 index 00000000000..c212b6fdf22 --- /dev/null +++ b/md/RESP3.md @@ -0,0 +1,32 @@ +# RESP3 => JS type mapping: + +- Null (`_`) => `null` +- Boolean (`#`) => `boolean` +- Number (`:`) => `number | string` +- Big Number (`(`) => `BigInt | string` +- Double (`,`) => `number | string` +- Simple String (`+`) => `string | Buffer` +- Blob String (`$`) => `string | Buffer` +- Verbatim String (`=`) => `string | Buffer | VerbatimString` +- Simple Error (`-`) => `ErrorReply` +- Blob Error (`!`) => `ErrorReply` +- Array (`*`) => `Array` +- Set (`~`) => `Array | Set` +- Map (`%`) => `object | Map | Array` +- Push (`>`) => `Array` => PubSub push/`'push'` event + +> NOTE: the first type is the default type + +## Verbatim String + +## Map keys and Set members + +When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decode as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. + +## Not Implemented + +These parts of RESP3 are not implemented in Redis itself (at the time of writing this), so we did not implemented them in the client as well: + +- [Attribute type](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#attribute-type) +- [Streamed strings](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-strings) +- [Streamed aggregated data types](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-aggregated-data-types) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md new file mode 100644 index 00000000000..f0f3442f93b --- /dev/null +++ b/md/v4-to-v5.md @@ -0,0 +1,75 @@ +# v4 to v5 migration guide + +## Commands + +Some command arguments/replies changed to be more aligned with Redis: + +- `ACL GETUSER`: `selectors` +- `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] +- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants] +- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` +- `HEXISTS`: `boolean` -> `number` [^boolean-to-number] +- `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). +- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`? +- `HSETNX`: `boolean` -> `number` [^boolean-to-number] +- `ZINTER`: instead of `client.ZINTER('11, { WEIGHTS: [1] })` use `client.ZINTER({ key: '1', weight: 1 }])` +- `SETNX`: `boolean` -> `number` [^boolean-to-number] +- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] +- `EXPIRE`: `boolean` -> `number` [^boolean-to-number] +- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `MOVE`: `boolean` -> `number` [^boolean-to-number] +- `PEXPIRE`: `boolean` -> `number` [^boolean-to-number] +- `PEXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `RENAMENX`: `boolean` -> `number` [^boolean-to-number] +- `HSCAN`: `tuples` has been renamed to `entries` +- `PFADD`: `boolean` -> `number` [^boolean-to-number] + +[^enum-to-constants]: + TODO + +[^boolean-to-number] + TODO + +## Command Options + +in v4, command options are passed as a first optional argument: + +```javascript +await client.get('key'); // `string | null` +await client.get(client.commandOptions({ returnBuffers: true }), 'key'); // `Buffer | null` +``` + +which has a couple of flaws: +1. The arguments types is checked in runtime, which hit performance. +2. Makes code suggestions less readable/usable, due to "function overloading". +3. Overall makes the "user code" not very readable. + +### The new API + +With the new API instead of passing the options directrly to the commands, we use a "proxy client" to store the options: + +```javascript +await client.get('key'); // `string | null` + +const proxyClient = client.withCommandOptions({ + flags: { + [TYPES.BLOB_STRING]: Buffer + } +}); + +await proxyClient.get('key'); // `Buffer | null` +``` + +`withCommandOptions` can be used to override all the command options, without reusing any of the existing ones. +On top of that, these functions can be used to override a specific option: +- `withFlags` - override `flags` only. +- `asap` - override `asap` to `true`. +- `isolated` - override `isolated` to `true`. + +## Quit VS Disconnect + +close +quit +disconnect + +TODO diff --git a/md/v5-new-features.md b/md/v5-new-features.md new file mode 100644 index 00000000000..8b762a3a59b --- /dev/null +++ b/md/v5-new-features.md @@ -0,0 +1,30 @@ +# RESP3 Support + +```javascript +client.hGetAll('key'); // Record + +client.withFlags({ + [TYPES.MAP]: Map +}).hGetAll('key'); // Map + +client.withFlags({ + [TYPES.MAP]: Map, + [TYPES.BLOB_STRING]: Buffer +}).hGetAll('key'); // Map +``` + +# `Multi.exec<'typed'>` + +```javascript +client.multi() + .ping() + .exec(); // Array + +client.multi() + .ping() + .exec<'typed'>(); // [string] +``` + +# Request & Reply Policies + +see [here](../docs/clustering.md#command-routing). From 7f880a64d29711f790d083124446c701e6233c66 Mon Sep 17 00:00:00 2001 From: Simon Prickett Date: Thu, 6 Apr 2023 20:29:01 +0100 Subject: [PATCH 002/325] Worked on phrasing etc for v5 doc changes. --- docs/clustering.md | 6 +++--- md/RESP3.md | 6 +++--- md/v4-to-v5.md | 29 +++++++++++++++-------------- md/v5-new-features.md | 4 ++++ 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/docs/clustering.md b/docs/clustering.md index 28ea0e2964c..7b8b66a9ad4 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -32,7 +32,7 @@ const value = await cluster.get('key'); | Property | Default | Description | |------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| rootNodes | | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster, 3 should be enough to reliably connect and obtain the cluster configuration from the server | +| 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 | | minimizeConnections | `false` | When `true`, `.connect()` will only discover the cluster topology, without actually connecting to all the nodes. Useful for short-term or Pub/Sub-only connections. | @@ -107,7 +107,7 @@ createCluster({ ### Commands that operate on Redis Keys -Commands such as `GET`, `SET`, etc. are routed by the first key, for instance `MGET 1 2 3` will be routed by the key `1`. +Commands such as `GET`, `SET`, etc. are routed by the first key specified. For example `MGET 1 2 3` will be routed by the key `1`. ### [Server Commands](https://redis.io/commands#server) @@ -115,4 +115,4 @@ Admin commands such as `MEMORY STATS`, `FLUSHALL`, etc. are not attached to the ### "Forwarded Commands" -Certain commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. This client sends these commands to a random node in order to spread the load across the cluster. +Certain commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. The client sends these commands to a random node in order to spread the load across the cluster. diff --git a/md/RESP3.md b/md/RESP3.md index c212b6fdf22..2c684be2b14 100644 --- a/md/RESP3.md +++ b/md/RESP3.md @@ -1,4 +1,4 @@ -# RESP3 => JS type mapping: +# RESP3 => JS Type Mappings: - Null (`_`) => `null` - Boolean (`#`) => `boolean` @@ -21,11 +21,11 @@ ## Map keys and Set members -When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decode as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. +When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. ## Not Implemented -These parts of RESP3 are not implemented in Redis itself (at the time of writing this), so we did not implemented them in the client as well: +These parts of RESP3 are not yet implemented in Redis itself (at the time of writing), so are not yet implemented in the Node-Redis client either: - [Attribute type](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#attribute-type) - [Streamed strings](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-strings) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index f0f3442f93b..fd5de1ca13b 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -2,7 +2,7 @@ ## Commands -Some command arguments/replies changed to be more aligned with Redis: +Some command arguments/replies have changed to align more closely to data types returned by Redis: - `ACL GETUSER`: `selectors` - `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] @@ -32,21 +32,21 @@ Some command arguments/replies changed to be more aligned with Redis: ## Command Options -in v4, command options are passed as a first optional argument: +In v4, command options are passed as a first optional argument: ```javascript await client.get('key'); // `string | null` await client.get(client.commandOptions({ returnBuffers: true }), 'key'); // `Buffer | null` ``` -which has a couple of flaws: -1. The arguments types is checked in runtime, which hit performance. -2. Makes code suggestions less readable/usable, due to "function overloading". -3. Overall makes the "user code" not very readable. +This has a couple of flaws: +1. The argument types are checked in runtime, which is a performance hit. +2. Code suggestions are less readable/usable, due to "function overloading". +3. Overall, "user code" is not as readable as it could be. -### The new API +### The new API for v5 -With the new API instead of passing the options directrly to the commands, we use a "proxy client" to store the options: +With the new API, instead of passing the options directly to the commands we use a "proxy client" to store them: ```javascript await client.get('key'); // `string | null` @@ -60,16 +60,17 @@ const proxyClient = client.withCommandOptions({ await proxyClient.get('key'); // `Buffer | null` ``` -`withCommandOptions` can be used to override all the command options, without reusing any of the existing ones. -On top of that, these functions can be used to override a specific option: +`withCommandOptions` can be used to override all of the command options, without reusing any existing ones. + +To override just a specific option, use the following functions: - `withFlags` - override `flags` only. - `asap` - override `asap` to `true`. - `isolated` - override `isolated` to `true`. ## Quit VS Disconnect -close -quit -disconnect +The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Rather than sending a `QUIT` command to the server, the client can simply close the network connection. + +Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`. -TODO +TODO difference between `close` and `disconnect`... diff --git a/md/v5-new-features.md b/md/v5-new-features.md index 8b762a3a59b..b9ac5860833 100644 --- a/md/v5-new-features.md +++ b/md/v5-new-features.md @@ -15,6 +15,10 @@ client.withFlags({ # `Multi.exec<'typed'>` +We have introduced the ability to perform a 'typed' `MULTI`/`EXEC` transaction. Rather than returning `Array`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible. + +Example: + ```javascript client.multi() .ping() From 02b3beee9949c454554a6137039a64dd61da8312 Mon Sep 17 00:00:00 2001 From: Simon Prickett Date: Thu, 6 Apr 2023 20:31:44 +0100 Subject: [PATCH 003/325] Removed quite repetition of 'Rather' --- md/v4-to-v5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index fd5de1ca13b..401cce3fea6 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -69,7 +69,7 @@ To override just a specific option, use the following functions: ## Quit VS Disconnect -The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Rather than sending a `QUIT` command to the server, the client can simply close the network connection. +The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection. Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`. From 5c6fb19a9aa1817627ffc6c66f25a08d069e65c7 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 10 Apr 2023 01:46:11 -0400 Subject: [PATCH 004/325] Update v4-to-v5.md --- md/v4-to-v5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index 401cce3fea6..3bdd9deb711 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -27,7 +27,7 @@ Some command arguments/replies have changed to align more closely to data types [^enum-to-constants]: TODO -[^boolean-to-number] +[^boolean-to-number]: TODO ## Command Options From 1d6c78072a9f284356e80375dbc7b2296ce4a78f Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 10 Apr 2023 02:07:54 -0400 Subject: [PATCH 005/325] Update v4-to-v5.md --- md/v4-to-v5.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index 3bdd9deb711..ea54446c3cb 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -24,11 +24,9 @@ Some command arguments/replies have changed to align more closely to data types - `HSCAN`: `tuples` has been renamed to `entries` - `PFADD`: `boolean` -> `number` [^boolean-to-number] -[^enum-to-constants]: - TODO +[^enum-to-constants]: TODO -[^boolean-to-number]: - TODO +[^boolean-to-number]: TODO ## Command Options From 35d32e5b6424fb15cfc98774d4ebd48ab815c0ac Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Sat, 22 Apr 2023 15:27:56 -0400 Subject: [PATCH 006/325] Update v4-to-v5.md --- md/v4-to-v5.md | 56 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index ea54446c3cb..c04b54a3730 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -1,33 +1,5 @@ # v4 to v5 migration guide -## Commands - -Some command arguments/replies have changed to align more closely to data types returned by Redis: - -- `ACL GETUSER`: `selectors` -- `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] -- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants] -- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` -- `HEXISTS`: `boolean` -> `number` [^boolean-to-number] -- `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). -- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`? -- `HSETNX`: `boolean` -> `number` [^boolean-to-number] -- `ZINTER`: instead of `client.ZINTER('11, { WEIGHTS: [1] })` use `client.ZINTER({ key: '1', weight: 1 }])` -- `SETNX`: `boolean` -> `number` [^boolean-to-number] -- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] -- `EXPIRE`: `boolean` -> `number` [^boolean-to-number] -- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number] -- `MOVE`: `boolean` -> `number` [^boolean-to-number] -- `PEXPIRE`: `boolean` -> `number` [^boolean-to-number] -- `PEXPIREAT`: `boolean` -> `number` [^boolean-to-number] -- `RENAMENX`: `boolean` -> `number` [^boolean-to-number] -- `HSCAN`: `tuples` has been renamed to `entries` -- `PFADD`: `boolean` -> `number` [^boolean-to-number] - -[^enum-to-constants]: TODO - -[^boolean-to-number]: TODO - ## Command Options In v4, command options are passed as a first optional argument: @@ -72,3 +44,31 @@ The `QUIT` command has been deprecated in Redis 7.2 and should now also be consi Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`. TODO difference between `close` and `disconnect`... + +## Commands + +Some command arguments/replies have changed to align more closely to data types returned by Redis: + +- `ACL GETUSER`: `selectors` +- `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] +- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants] +- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` +- `HEXISTS`: `boolean` -> `number` [^boolean-to-number] +- `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). +- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`? +- `HSETNX`: `boolean` -> `number` [^boolean-to-number] +- `ZINTER`: instead of `client.ZINTER('11, { WEIGHTS: [1] })` use `client.ZINTER({ key: '1', weight: 1 }])` +- `SETNX`: `boolean` -> `number` [^boolean-to-number] +- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] +- `EXPIRE`: `boolean` -> `number` [^boolean-to-number] +- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `MOVE`: `boolean` -> `number` [^boolean-to-number] +- `PEXPIRE`: `boolean` -> `number` [^boolean-to-number] +- `PEXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `RENAMENX`: `boolean` -> `number` [^boolean-to-number] +- `HSCAN`: `tuples` has been renamed to `entries` +- `PFADD`: `boolean` -> `number` [^boolean-to-number] + +[^enum-to-constants]: TODO + +[^boolean-to-number]: TODO From 9faa3e77c4dc472668ac3aab4375e98933255274 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 23 Apr 2023 07:56:15 -0400 Subject: [PATCH 007/325] WIP --- ...er-config.yml => release-drafter-base.yml} | 2 + benchmark/lib/ping/ioredis-auto-pipeline.js | 20 + benchmark/lib/ping/local-resp2.js | 21 + .../lib/ping/local-resp3-module-with-flags.js | 27 + benchmark/lib/ping/local-resp3-module.js | 27 + benchmark/lib/ping/local-resp3.js | 21 + benchmark/lib/ping/v4.js | 2 +- benchmark/lib/runner.js | 12 +- benchmark/package-lock.json | 448 +- benchmark/package.json | 9 +- md/RESP2-to-RESP3.md | 1 + md/Redis-todo.md | 12 + package-lock.json | 4268 ++++++++--------- package.json | 4 +- packages/bloom/lib/commands/bloom/INSERT.ts | 4 +- .../lib/commands/count-min-sketch/QUERY.ts | 4 +- packages/bloom/lib/commands/cuckoo/index.ts | 4 +- packages/bloom/lib/commands/t-digest/MERGE.ts | 4 +- packages/bloom/lib/commands/top-k/ADD.ts | 4 +- packages/bloom/lib/commands/top-k/COUNT.ts | 4 +- packages/bloom/lib/commands/top-k/QUERY.ts | 4 +- packages/bloom/package.json | 8 +- packages/client/.eslintrc.json | 26 +- packages/client/index.ts | 28 +- packages/client/lib/RESP/decoder-ts.ts | 1043 ++++ .../{client/RESP2 => RESP}/decoder.spec.ts | 0 packages/client/lib/RESP/decoder.ts | 1159 +++++ packages/client/lib/RESP/encoder.spec.ts | 33 + packages/client/lib/RESP/encoder.ts | 28 + packages/client/lib/RESP/types.ts | 417 ++ packages/client/lib/RESP/verbatim-string.ts | 8 + .../lib/client/RESP2/composers/buffer.spec.ts | 14 - .../lib/client/RESP2/composers/buffer.ts | 18 - .../lib/client/RESP2/composers/interface.ts | 7 - .../lib/client/RESP2/composers/string.spec.ts | 14 - .../lib/client/RESP2/composers/string.ts | 22 - packages/client/lib/client/RESP2/decoder.ts | 257 - .../client/lib/client/RESP2/encoder.spec.ts | 33 - packages/client/lib/client/RESP2/encoder.ts | 28 - packages/client/lib/client/commands-queue.ts | 502 +- packages/client/lib/client/commands.ts | 359 -- packages/client/lib/client/index.ts | 1566 +++--- packages/client/lib/client/multi-command.ts | 395 +- packages/client/lib/client/pub-sub.ts | 696 +-- packages/client/lib/client/socket.ts | 474 +- packages/client/lib/cluster/cluster-slots.ts | 1015 ++-- packages/client/lib/cluster/commands.ts | 637 --- packages/client/lib/cluster/index.ts | 911 ++-- packages/client/lib/cluster/multi-command.ts | 282 +- packages/client/lib/command-options.ts | 14 - packages/client/lib/commander.ts | 230 +- packages/client/lib/commands/ACL_CAT.spec.ts | 40 +- packages/client/lib/commands/ACL_CAT.ts | 17 +- .../client/lib/commands/ACL_DELUSER.spec.ts | 42 +- packages/client/lib/commands/ACL_DELUSER.ts | 19 +- .../client/lib/commands/ACL_DRYRUN.spec.ts | 28 +- packages/client/lib/commands/ACL_DRYRUN.ts | 26 +- .../client/lib/commands/ACL_GENPASS.spec.ts | 39 +- packages/client/lib/commands/ACL_GENPASS.ts | 14 +- .../client/lib/commands/ACL_GETUSER.spec.ts | 58 +- packages/client/lib/commands/ACL_GETUSER.ts | 76 +- packages/client/lib/commands/ACL_LIST.spec.ts | 26 +- packages/client/lib/commands/ACL_LIST.ts | 13 +- packages/client/lib/commands/ACL_LOAD.spec.ts | 18 +- packages/client/lib/commands/ACL_LOAD.ts | 13 +- packages/client/lib/commands/ACL_LOG.spec.ts | 90 +- packages/client/lib/commands/ACL_LOG.ts | 76 +- .../client/lib/commands/ACL_LOG_RESET.spec.ts | 25 +- packages/client/lib/commands/ACL_LOG_RESET.ts | 14 +- packages/client/lib/commands/ACL_SAVE.spec.ts | 18 +- packages/client/lib/commands/ACL_SAVE.ts | 13 +- packages/client/lib/commands/ACL_SETUSER.ts | 20 +- packages/client/lib/commands/ACL_USERS.ts | 13 +- packages/client/lib/commands/ACL_WHOAMI.ts | 15 +- packages/client/lib/commands/APPEND.spec.ts | 27 +- packages/client/lib/commands/APPEND.ts | 18 +- packages/client/lib/commands/ASKING.ts | 13 +- packages/client/lib/commands/AUTH.spec.ts | 38 +- packages/client/lib/commands/AUTH.ts | 25 +- packages/client/lib/commands/BGREWRITEAOF.ts | 13 +- packages/client/lib/commands/BGSAVE.ts | 27 +- packages/client/lib/commands/BITCOUNT.ts | 44 +- packages/client/lib/commands/BITFIELD.spec.ts | 83 +- packages/client/lib/commands/BITFIELD.ts | 115 +- .../client/lib/commands/BITFIELD_RO.spec.ts | 45 +- packages/client/lib/commands/BITFIELD_RO.ts | 31 +- packages/client/lib/commands/BITOP.spec.ts | 50 +- packages/client/lib/commands/BITOP.ts | 27 +- packages/client/lib/commands/BITPOS.ts | 27 +- packages/client/lib/commands/BLMOVE.ts | 37 +- packages/client/lib/commands/BLMPOP.ts | 28 +- packages/client/lib/commands/BLPOP.ts | 40 +- packages/client/lib/commands/BRPOP.ts | 26 +- packages/client/lib/commands/BRPOPLPUSH.ts | 21 +- packages/client/lib/commands/BZMPOP.ts | 14 + packages/client/lib/commands/BZPOPMAX.ts | 4 +- packages/client/lib/commands/BZPOPMIN.ts | 4 +- .../lib/commands/CLIENT_CACHING.spec.ts | 28 +- .../client/lib/commands/CLIENT_CACHING.ts | 18 +- .../lib/commands/CLIENT_GETNAME.spec.ts | 14 +- .../client/lib/commands/CLIENT_GETNAME.ts | 17 +- .../lib/commands/CLIENT_GETREDIR.spec.ts | 14 +- .../client/lib/commands/CLIENT_GETREDIR.ts | 14 +- .../client/lib/commands/CLIENT_ID.spec.ts | 26 +- packages/client/lib/commands/CLIENT_ID.ts | 12 +- packages/client/lib/commands/CLIENT_INFO.ts | 148 +- .../client/lib/commands/CLIENT_KILL.spec.ts | 192 +- packages/client/lib/commands/CLIENT_KILL.ts | 146 +- packages/client/lib/commands/CLIENT_LIST.ts | 56 +- .../client/lib/commands/CLIENT_NO-EVICT.ts | 18 +- packages/client/lib/commands/CLIENT_PAUSE.ts | 23 +- .../client/lib/commands/CLIENT_SETNAME.ts | 12 +- .../client/lib/commands/CLIENT_UNPAUSE.ts | 12 +- .../client/lib/commands/CLUSTER_ADDSLOTS.ts | 20 +- .../lib/commands/CLUSTER_ADDSLOTSRANGE.ts | 18 +- .../client/lib/commands/CLUSTER_BUMPEPOCH.ts | 12 +- .../commands/CLUSTER_COUNT-FAILURE-REPORTS.ts | 12 +- .../lib/commands/CLUSTER_COUNTKEYSINSLOT.ts | 12 +- .../client/lib/commands/CLUSTER_DELSLOTS.ts | 20 +- .../lib/commands/CLUSTER_DELSLOTSRANGE.ts | 18 +- .../client/lib/commands/CLUSTER_FAILOVER.ts | 24 +- .../client/lib/commands/CLUSTER_FLUSHSLOTS.ts | 12 +- .../client/lib/commands/CLUSTER_FORGET.ts | 12 +- .../lib/commands/CLUSTER_GETKEYSINSLOT.ts | 12 +- .../client/lib/commands/CLUSTER_KEYSLOT.ts | 11 +- packages/client/lib/commands/CLUSTER_MEET.ts | 11 +- packages/client/lib/commands/CLUSTER_MYID.ts | 11 +- .../client/lib/commands/CLUSTER_REPLICATE.ts | 11 +- packages/client/lib/commands/CLUSTER_SLOTS.ts | 71 +- packages/client/lib/commands/CONFIG_GET.ts | 13 +- .../client/lib/commands/CONFIG_RESETSTAT.ts | 11 +- .../client/lib/commands/CONFIG_REWRITE.ts | 11 +- packages/client/lib/commands/CONFIG_SET.ts | 33 +- packages/client/lib/commands/COPY.ts | 32 +- packages/client/lib/commands/DBSIZE.ts | 12 +- packages/client/lib/commands/DECR.ts | 14 +- packages/client/lib/commands/DECRBY.ts | 19 +- packages/client/lib/commands/DEL.ts | 20 +- packages/client/lib/commands/DISCARD.ts | 11 +- packages/client/lib/commands/DUMP.ts | 15 +- packages/client/lib/commands/ECHO.ts | 14 +- packages/client/lib/commands/EXISTS.ts | 25 +- packages/client/lib/commands/EXPIRE.ts | 21 +- packages/client/lib/commands/EXPIREAT.ts | 27 +- packages/client/lib/commands/EXPIRETIME.ts | 15 +- packages/client/lib/commands/FAILOVER.ts | 37 +- packages/client/lib/commands/FLUSHALL.ts | 25 +- packages/client/lib/commands/FLUSHDB.ts | 14 +- .../client/lib/commands/FUNCTION_DELETE.ts | 13 +- packages/client/lib/commands/FUNCTION_DUMP.ts | 13 +- .../client/lib/commands/FUNCTION_FLUSH.ts | 18 +- packages/client/lib/commands/FUNCTION_KILL.ts | 13 +- .../client/lib/commands/FUNCTION_STATS.ts | 139 +- packages/client/lib/commands/GEOHASH.ts | 4 +- packages/client/lib/commands/GEOPOS.ts | 4 +- packages/client/lib/commands/GET.ts | 17 +- packages/client/lib/commands/GETDEL.ts | 15 +- packages/client/lib/commands/GETEX.ts | 40 +- packages/client/lib/commands/GETRANGE.ts | 21 +- packages/client/lib/commands/GETSET.ts | 18 +- packages/client/lib/commands/HDEL.ts | 21 +- packages/client/lib/commands/HELLO.ts | 109 +- packages/client/lib/commands/HEXISTS.ts | 18 +- packages/client/lib/commands/HGET.ts | 20 +- packages/client/lib/commands/HGETALL.ts | 24 +- packages/client/lib/commands/HINCRBY.ts | 27 +- packages/client/lib/commands/HINCRBYFLOAT.ts | 27 +- packages/client/lib/commands/HKEYS.ts | 15 +- packages/client/lib/commands/HLEN.ts | 15 +- packages/client/lib/commands/HMGET.ts | 29 +- packages/client/lib/commands/HRANDFIELD.ts | 17 +- .../client/lib/commands/HRANDFIELD_COUNT.ts | 24 +- .../HRANDFIELD_COUNT_WITHVALUES.spec.ts | 21 - .../commands/HRANDFIELD_COUNT_WITHVALUES.ts | 46 +- packages/client/lib/commands/HSCAN.ts | 60 +- packages/client/lib/commands/HSET.ts | 96 +- packages/client/lib/commands/HSETNX.ts | 23 +- packages/client/lib/commands/HSTRLEN.ts | 20 +- packages/client/lib/commands/HVALS.ts | 15 +- packages/client/lib/commands/INCR.ts | 14 +- packages/client/lib/commands/INCRBY.ts | 17 +- packages/client/lib/commands/INCRBYFLOAT.ts | 17 +- packages/client/lib/commands/INFO.ts | 16 +- packages/client/lib/commands/KEYS.ts | 12 +- packages/client/lib/commands/LCS.ts | 31 +- packages/client/lib/commands/LCS_IDX.ts | 80 +- .../lib/commands/LCS_IDX_WITHMATCHLEN.ts | 82 +- packages/client/lib/commands/LCS_LEN.ts | 25 +- packages/client/lib/commands/LINDEX.ts | 20 +- packages/client/lib/commands/LINSERT.ts | 33 +- packages/client/lib/commands/LLEN.ts | 17 +- packages/client/lib/commands/LMOVE.ts | 30 +- packages/client/lib/commands/LMPOP.ts | 32 +- packages/client/lib/commands/LOLWUT.ts | 25 +- packages/client/lib/commands/LPOP.ts | 14 +- packages/client/lib/commands/LPOP_COUNT.ts | 18 +- packages/client/lib/commands/LPOS.ts | 35 +- packages/client/lib/commands/LPOS_COUNT.ts | 27 +- packages/client/lib/commands/LPUSH.ts | 20 +- packages/client/lib/commands/LPUSHX.ts | 21 +- packages/client/lib/commands/LRANGE.ts | 29 +- packages/client/lib/commands/LREM.ts | 29 +- packages/client/lib/commands/LSET.ts | 29 +- packages/client/lib/commands/LTRIM.ts | 28 +- packages/client/lib/commands/MGET.ts | 19 +- packages/client/lib/commands/MIGRATE.ts | 83 +- packages/client/lib/commands/MODULE_LIST.ts | 26 +- packages/client/lib/commands/MODULE_LOAD.ts | 20 +- packages/client/lib/commands/MODULE_UNLOAD.ts | 13 +- packages/client/lib/commands/MOVE.ts | 12 +- packages/client/lib/commands/MSET.ts | 35 +- packages/client/lib/commands/MSETNX.ts | 29 +- .../client/lib/commands/OBJECT_ENCODING.ts | 17 +- packages/client/lib/commands/OBJECT_FREQ.ts | 17 +- .../client/lib/commands/OBJECT_IDLETIME.ts | 17 +- .../client/lib/commands/OBJECT_REFCOUNT.ts | 17 +- packages/client/lib/commands/PERSIST.ts | 14 +- packages/client/lib/commands/PEXPIRE.ts | 25 +- packages/client/lib/commands/PEXPIREAT.ts | 29 +- packages/client/lib/commands/PEXPIRETIME.ts | 17 +- packages/client/lib/commands/PFADD.ts | 22 +- packages/client/lib/commands/PFCOUNT.ts | 21 +- packages/client/lib/commands/PFMERGE.ts | 21 +- packages/client/lib/commands/PING.spec.ts | 54 +- packages/client/lib/commands/PING.ts | 16 +- packages/client/lib/commands/PSETEX.ts | 30 +- packages/client/lib/commands/PTTL.ts | 17 +- packages/client/lib/commands/PUBLISH.ts | 18 +- .../client/lib/commands/PUBSUB_CHANNELS.ts | 16 +- packages/client/lib/commands/PUBSUB_NUMPAT.ts | 13 +- packages/client/lib/commands/PUBSUB_NUMSUB.ts | 33 +- .../lib/commands/PUBSUB_SHARDCHANNELS.ts | 23 +- packages/client/lib/commands/RANDOMKEY.ts | 14 +- packages/client/lib/commands/READONLY.ts | 13 +- packages/client/lib/commands/READWRITE.ts | 13 +- packages/client/lib/commands/RENAME.ts | 17 +- packages/client/lib/commands/RENAMENX.ts | 17 +- packages/client/lib/commands/REPLICAOF.ts | 13 +- packages/client/lib/commands/ROLE.ts | 126 +- packages/client/lib/commands/RPOP.ts | 14 +- packages/client/lib/commands/RPOPLPUSH.ts | 20 +- packages/client/lib/commands/RPOP_COUNT.ts | 17 +- packages/client/lib/commands/RPUSH.ts | 24 +- packages/client/lib/commands/RPUSHX.ts | 24 +- packages/client/lib/commands/SADD.ts | 24 +- packages/client/lib/commands/SCAN.ts | 33 +- packages/client/lib/commands/SCARD.ts | 13 +- packages/client/lib/commands/SCRIPT_EXISTS.ts | 4 +- packages/client/lib/commands/SDIFF.ts | 27 +- packages/client/lib/commands/SDIFFSTORE.ts | 24 +- packages/client/lib/commands/SET.ts | 58 +- packages/client/lib/commands/SETEX.ts | 28 +- packages/client/lib/commands/SETNX.ts | 17 +- packages/client/lib/commands/SETRANGE.ts | 27 +- packages/client/lib/commands/SINTER.ts | 27 +- packages/client/lib/commands/SINTERCARD.ts | 35 +- packages/client/lib/commands/SINTERSTORE.ts | 4 +- packages/client/lib/commands/SMEMBERS.ts | 15 +- packages/client/lib/commands/SREM.ts | 4 +- packages/client/lib/commands/SSCAN.ts | 39 +- packages/client/lib/commands/STRLEN.ts | 17 +- packages/client/lib/commands/SUNION.ts | 4 +- packages/client/lib/commands/SUNIONSTORE.ts | 4 +- packages/client/lib/commands/TOUCH.ts | 4 +- packages/client/lib/commands/TTL.ts | 17 +- packages/client/lib/commands/TYPE.ts | 17 +- packages/client/lib/commands/UNLINK.ts | 4 +- packages/client/lib/commands/UNWATCH.ts | 12 +- packages/client/lib/commands/WAIT.ts | 12 +- packages/client/lib/commands/WATCH.ts | 4 +- packages/client/lib/commands/XACK.ts | 4 +- packages/client/lib/commands/XCLAIM.ts | 4 +- packages/client/lib/commands/XDEL.ts | 4 +- packages/client/lib/commands/ZADD.ts | 69 +- packages/client/lib/commands/ZCARD.ts | 17 +- packages/client/lib/commands/ZCOUNT.ts | 33 +- packages/client/lib/commands/ZDIFF.ts | 25 +- packages/client/lib/commands/ZDIFFSTORE.ts | 25 +- .../client/lib/commands/ZDIFF_WITHSCORES.ts | 30 +- packages/client/lib/commands/ZINCRBY.ts | 33 +- packages/client/lib/commands/ZINTER.ts | 86 +- packages/client/lib/commands/ZINTERCARD.ts | 36 +- packages/client/lib/commands/ZINTERSTORE.ts | 45 +- .../client/lib/commands/ZINTER_WITHSCORES.ts | 45 +- packages/client/lib/commands/ZLEXCOUNT.ts | 33 +- packages/client/lib/commands/ZMPOP.ts | 72 +- packages/client/lib/commands/ZMSCORE.ts | 32 +- packages/client/lib/commands/ZREM.ts | 4 +- packages/client/lib/commands/ZSCAN.ts | 57 +- packages/client/lib/commands/ZUNION.ts | 4 +- packages/client/lib/commands/ZUNIONSTORE.ts | 4 +- .../lib/commands/generic-transformers.spec.ts | 34 +- .../lib/commands/generic-transformers.ts | 62 +- packages/client/lib/commands/index.ts | 421 +- packages/client/lib/errors.ts | 4 + packages/client/lib/lua-script.ts | 22 +- packages/client/lib/multi-command.ts | 117 +- packages/client/package.json | 18 +- packages/client/test.mjs | 338 ++ packages/graph/package.json | 8 +- packages/json/lib/commands/GET.ts | 4 +- packages/json/package.json | 8 +- packages/old/RESP3-old/decoder.ts | 423 ++ packages/old/RESP3-old/encoder.ts | 0 .../old/RESP3-old/nested-decoders/abstract.ts | 6 + .../RESP3-old/nested-decoders/map-to-array.ts | 28 + .../old/RESP3-old/nested-decoders/to-array.ts | 20 + .../old/RESP3-old/nested-decoders/to-map.ts | 28 + .../RESP3-old/nested-decoders/to-object.ts | 28 + .../old/RESP3-old/nested-decoders/to-set.ts | 20 + packages/old/RESP3-old/types.ts | 101 + packages/search/lib/commands/AGGREGATE.ts | 4 +- packages/search/lib/commands/CREATE.ts | 6 +- packages/search/lib/commands/DICTADD.ts | 4 +- packages/search/lib/commands/DICTDEL.ts | 4 +- packages/search/lib/commands/SYNUPDATE.ts | 4 +- packages/search/lib/commands/index.ts | 12 +- packages/search/package.json | 8 +- packages/test-utils/lib/dockers.ts | 362 +- packages/test-utils/lib/index.ts | 403 +- packages/test-utils/package.json | 6 +- .../time-series/lib/commands/QUERYINDEX.ts | 4 +- packages/time-series/lib/commands/index.ts | 6 +- packages/time-series/package.json | 8 +- req-res-parser/a.sh | 7 + req-res-parser/req-res-parser.mjs | 1018 ++++ 326 files changed, 14501 insertions(+), 10812 deletions(-) rename .github/{release-drafter-config.yml => release-drafter-base.yml} (97%) create mode 100644 benchmark/lib/ping/ioredis-auto-pipeline.js create mode 100644 benchmark/lib/ping/local-resp2.js create mode 100644 benchmark/lib/ping/local-resp3-module-with-flags.js create mode 100644 benchmark/lib/ping/local-resp3-module.js create mode 100644 benchmark/lib/ping/local-resp3.js create mode 100644 md/RESP2-to-RESP3.md create mode 100644 md/Redis-todo.md create mode 100644 packages/client/lib/RESP/decoder-ts.ts rename packages/client/lib/{client/RESP2 => RESP}/decoder.spec.ts (100%) create mode 100644 packages/client/lib/RESP/decoder.ts create mode 100644 packages/client/lib/RESP/encoder.spec.ts create mode 100644 packages/client/lib/RESP/encoder.ts create mode 100644 packages/client/lib/RESP/types.ts create mode 100644 packages/client/lib/RESP/verbatim-string.ts delete mode 100644 packages/client/lib/client/RESP2/composers/buffer.spec.ts delete mode 100644 packages/client/lib/client/RESP2/composers/buffer.ts delete mode 100644 packages/client/lib/client/RESP2/composers/interface.ts delete mode 100644 packages/client/lib/client/RESP2/composers/string.spec.ts delete mode 100644 packages/client/lib/client/RESP2/composers/string.ts delete mode 100644 packages/client/lib/client/RESP2/decoder.ts delete mode 100644 packages/client/lib/client/RESP2/encoder.spec.ts delete mode 100644 packages/client/lib/client/RESP2/encoder.ts delete mode 100644 packages/client/lib/client/commands.ts delete mode 100644 packages/client/lib/cluster/commands.ts delete mode 100644 packages/client/lib/command-options.ts delete mode 100644 packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts create mode 100644 packages/client/test.mjs create mode 100644 packages/old/RESP3-old/decoder.ts create mode 100644 packages/old/RESP3-old/encoder.ts create mode 100644 packages/old/RESP3-old/nested-decoders/abstract.ts create mode 100644 packages/old/RESP3-old/nested-decoders/map-to-array.ts create mode 100644 packages/old/RESP3-old/nested-decoders/to-array.ts create mode 100644 packages/old/RESP3-old/nested-decoders/to-map.ts create mode 100644 packages/old/RESP3-old/nested-decoders/to-object.ts create mode 100644 packages/old/RESP3-old/nested-decoders/to-set.ts create mode 100644 packages/old/RESP3-old/types.ts create mode 100644 req-res-parser/a.sh create mode 100644 req-res-parser/req-res-parser.mjs diff --git a/.github/release-drafter-config.yml b/.github/release-drafter-base.yml similarity index 97% rename from .github/release-drafter-config.yml rename to .github/release-drafter-base.yml index 9a98b1c08a3..cd99c28b1f8 100644 --- a/.github/release-drafter-config.yml +++ b/.github/release-drafter-base.yml @@ -1,5 +1,7 @@ name-template: 'Version $NEXT_PATCH_VERSION' tag-template: 'v$NEXT_PATCH_VERSION' +include-path: + - {{ }} autolabeler: - label: 'chore' files: diff --git a/benchmark/lib/ping/ioredis-auto-pipeline.js b/benchmark/lib/ping/ioredis-auto-pipeline.js new file mode 100644 index 00000000000..ee400fe6ca9 --- /dev/null +++ b/benchmark/lib/ping/ioredis-auto-pipeline.js @@ -0,0 +1,20 @@ +import Redis from 'ioredis'; + +export default async (host) => { + const client = new Redis({ + host, + lazyConnect: true, + enableAutoPipelining: true + }); + + await client.connect(); + + return { + benchmark() { + return client.ping(); + }, + teardown() { + return client.disconnect(); + } + } +}; diff --git a/benchmark/lib/ping/local-resp2.js b/benchmark/lib/ping/local-resp2.js new file mode 100644 index 00000000000..873698a131f --- /dev/null +++ b/benchmark/lib/ping/local-resp2.js @@ -0,0 +1,21 @@ +import { createClient } from 'redis-local'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + RESP: 2 + }); + + await client.connect(); + + return { + benchmark() { + return client.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/ping/local-resp3-module-with-flags.js b/benchmark/lib/ping/local-resp3-module-with-flags.js new file mode 100644 index 00000000000..2af849b938b --- /dev/null +++ b/benchmark/lib/ping/local-resp3-module-with-flags.js @@ -0,0 +1,27 @@ +import { createClient } from 'redis-local'; +import PING from 'redis-local/dist/lib/commands/PING.js'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + RESP: 3, + modules: { + module: { + ping: PING.default + } + } + }); + + await client.connect(); + + return { + benchmark() { + return client.withFlags({}).module.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/ping/local-resp3-module.js b/benchmark/lib/ping/local-resp3-module.js new file mode 100644 index 00000000000..66f6e3ec291 --- /dev/null +++ b/benchmark/lib/ping/local-resp3-module.js @@ -0,0 +1,27 @@ +import { createClient } from 'redis-local'; +import PING from 'redis-local/dist/lib/commands/PING.js'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + RESP: 3, + modules: { + module: { + ping: PING.default + } + } + }); + + await client.connect(); + + return { + benchmark() { + return client.module.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/ping/local-resp3.js b/benchmark/lib/ping/local-resp3.js new file mode 100644 index 00000000000..a4ee4f24a2a --- /dev/null +++ b/benchmark/lib/ping/local-resp3.js @@ -0,0 +1,21 @@ +import { createClient } from 'redis-local'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + RESP: 3 + }); + + await client.connect(); + + return { + benchmark() { + return client.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/ping/v4.js b/benchmark/lib/ping/v4.js index 69aa3c06929..c570aa1477f 100644 --- a/benchmark/lib/ping/v4.js +++ b/benchmark/lib/ping/v4.js @@ -1,4 +1,4 @@ -import { createClient } from '@redis/client'; +import { createClient } from 'redis-v4'; export default async (host) => { const client = createClient({ diff --git a/benchmark/lib/runner.js b/benchmark/lib/runner.js index a96ff55cab0..3787cbabd1b 100644 --- a/benchmark/lib/runner.js +++ b/benchmark/lib/runner.js @@ -71,13 +71,13 @@ const benchmarkStart = process.hrtime.bigint(), histogram = await run(times), benchmarkNanoseconds = process.hrtime.bigint() - benchmarkStart, json = { - timestamp, + // timestamp, operationsPerSecond: times / Number(benchmarkNanoseconds) * 1_000_000_000, - p0: histogram.getValueAtPercentile(0), - p50: histogram.getValueAtPercentile(50), - p95: histogram.getValueAtPercentile(95), - p99: histogram.getValueAtPercentile(99), - p100: histogram.getValueAtPercentile(100) + // p0: histogram.getValueAtPercentile(0), + // p50: histogram.getValueAtPercentile(50), + // p95: histogram.getValueAtPercentile(95), + // p99: histogram.getValueAtPercentile(99), + // p100: histogram.getValueAtPercentile(100) }; console.log(`[${basename(path)}]:`); console.table(json); diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index 828b42803eb..4ec89ea2f98 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -1,31 +1,36 @@ { "name": "@redis/client-benchmark", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@redis/client-benchmark", "dependencies": { - "@redis/client": "../packages/client", "hdr-histogram-js": "3.0.0", - "ioredis": "5.3.0", - "redis-v3": "npm:redis@3.1.2", - "yargs": "17.6.2" + "ioredis": "5", + "redis-local": "file:../packages/client", + "redis-v3": "npm:redis@3", + "redis-v4": "npm:redis@4", + "yargs": "17.7.1" } }, "node_modules/@assemblyscript/loader": { "version": "0.19.23", - "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz", - "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==" + "license": "Apache-2.0" }, "node_modules/@ioredis/commands": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.1.1.tgz", - "integrity": "sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg==" + "version": "1.2.0", + "license": "MIT" + }, + "node_modules/@redis/bloom": { + "version": "1.2.0", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } }, "node_modules/@redis/client": { - "version": "1.5.0", - "resolved": "file:../packages/client", + "version": "1.5.6", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -36,18 +41,44 @@ "node": ">=14" } }, + "node_modules/@redis/graph": { + "version": "1.1.0", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/json": { + "version": "1.0.4", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/search": { + "version": "1.1.2", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/time-series": { + "version": "1.0.4", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, "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==", + "license": "MIT", "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==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -60,8 +91,6 @@ }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -75,12 +104,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -92,16 +121,14 @@ }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } }, "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==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -111,13 +138,11 @@ }, "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==" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -132,45 +157,39 @@ }, "node_modules/denque": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "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==" + "license": "MIT" }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/generic-pool": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/hdr-histogram-js": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-3.0.0.tgz", - "integrity": "sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==", + "license": "BSD", "dependencies": { "@assemblyscript/loader": "^0.19.21", "base64-js": "^1.2.0", @@ -181,9 +200,8 @@ } }, "node_modules/ioredis": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.0.tgz", - "integrity": "sha512-Id9jKHhsILuIZpHc61QkagfVdUj2Rag5GzG1TGEvRNeM7dtTOjICgjC+tvqYxi//PuX2wjQ+Xjva2ONBuf92Pw==", + "version": "5.3.1", + "license": "MIT", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -205,49 +223,55 @@ }, "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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/lodash.defaults": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + "license": "MIT" }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" }, "node_modules/pako": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + "license": "(MIT AND Zlib)" }, "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==" + "license": "MIT" }, "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=", + "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/redis-local": { + "name": "@redis/client", + "version": "1.5.6", + "resolved": "file:../packages/client", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/redis-parser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "license": "MIT", "dependencies": { "redis-errors": "^1.0.0" }, @@ -258,8 +282,7 @@ "node_modules/redis-v3": { "name": "redis", "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", - "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "license": "MIT", "dependencies": { "denque": "^1.5.0", "redis-commands": "^1.7.0", @@ -276,29 +299,41 @@ }, "node_modules/redis-v3/node_modules/denque": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } }, + "node_modules/redis-v4": { + "name": "redis", + "version": "4.6.5", + "license": "MIT", + "workspaces": [ + "./packages/*" + ], + "dependencies": { + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.6", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.2", + "@redis/time-series": "1.0.4" + } + }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/standard-as-callback": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -310,8 +345,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -321,8 +355,7 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -337,21 +370,18 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "version": "17.7.1", + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -367,264 +397,10 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { "node": ">=12" } } - }, - "dependencies": { - "@assemblyscript/loader": { - "version": "0.19.23", - "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz", - "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==" - }, - "@ioredis/commands": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.1.1.tgz", - "integrity": "sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg==" - }, - "@redis/client": { - "version": "1.5.0", - "requires": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - } - }, - "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" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" - }, - "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==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - }, - "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==" - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "hdr-histogram-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-3.0.0.tgz", - "integrity": "sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==", - "requires": { - "@assemblyscript/loader": "^0.19.21", - "base64-js": "^1.2.0", - "pako": "^1.0.3" - } - }, - "ioredis": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.0.tgz", - "integrity": "sha512-Id9jKHhsILuIZpHc61QkagfVdUj2Rag5GzG1TGEvRNeM7dtTOjICgjC+tvqYxi//PuX2wjQ+Xjva2ONBuf92Pw==", - "requires": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - } - }, - "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==" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "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" - } - }, - "redis-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" - }, - "dependencies": { - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "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" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - } } } diff --git a/benchmark/package.json b/benchmark/package.json index 79b0facda83..51357ce0326 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -7,10 +7,11 @@ "start": "node ." }, "dependencies": { - "@redis/client": "../packages/client", "hdr-histogram-js": "3.0.0", - "ioredis": "5.3.0", - "redis-v3": "npm:redis@3.1.2", - "yargs": "17.6.2" + "ioredis": "5", + "redis-v3": "npm:redis@3", + "redis-v4": "npm:redis@4", + "redis-local": "file:../packages/client", + "yargs": "17.7.1" } } diff --git a/md/RESP2-to-RESP3.md b/md/RESP2-to-RESP3.md new file mode 100644 index 00000000000..6f34ae8f41f --- /dev/null +++ b/md/RESP2-to-RESP3.md @@ -0,0 +1 @@ +https://docs.google.com/document/d/1Bg4jxEYiWnbCl4Oa2GCk5xaWde7HLa6GcNGg1sFwDAY/edit# diff --git a/md/Redis-todo.md b/md/Redis-todo.md new file mode 100644 index 00000000000..eab52a4ce15 --- /dev/null +++ b/md/Redis-todo.md @@ -0,0 +1,12 @@ +# Missing functionality + +- `HEXISTS`: accepts one field only, should be the same as `EXISTS` + +# Replies + +`String` -> `Double`: +- `INCRBYFLOAT` +- `HINCRBYFLOAT` + +`Number` -> `Boolean`: +- `HSETNX` (deprecated) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3ff77cd4bcd..56f66c8abcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,15 +22,14 @@ "devDependencies": { "@tsconfig/node14": "^1.0.3", "gh-pages": "^5.0.0", - "release-it": "^15.6.0", - "typescript": "^4.9.5" + "release-it": "^15.9.3", + "typescript": "^5.0.2" } }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -41,9 +40,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -52,34 +50,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.19.4", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.19.6", "dev": true, + "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", + "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/generator": "^7.19.6", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helpers": "^7.19.4", + "@babel/parser": "^7.19.6", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.1", "semver": "^6.3.0" }, "engines": { @@ -90,15 +86,21 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.19.6", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.19.4", "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -107,9 +109,8 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -120,15 +121,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.19.3", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.20.5", + "@babel/compat-data": "^7.19.3", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { @@ -138,23 +137,29 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.19.0", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -162,9 +167,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -174,9 +178,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -185,31 +188,29 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.19.6", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-simple-access": "^7.19.4", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.6", + "@babel/types": "^7.19.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.19.4", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.19.4" }, "engines": { "node": ">=6.9.0" @@ -217,9 +218,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -229,40 +229,36 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.18.6", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.19.4", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.4", + "@babel/types": "^7.19.4" }, "engines": { "node": ">=6.9.0" @@ -270,9 +266,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -284,9 +279,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -296,9 +290,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -310,42 +303,37 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -354,10 +342,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "version": "7.19.6", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -366,33 +353,31 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.18.10", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", + "version": "7.19.6", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", + "@babel/generator": "^7.19.6", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", + "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", + "@babel/parser": "^7.19.6", + "@babel/types": "^7.19.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -402,18 +387,16 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "version": "7.19.4", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -425,9 +408,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -437,23 +419,46 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", + "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -468,6 +473,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -484,9 +498,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -503,15 +516,13 @@ }, "node_modules/@iarna/toml": { "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -525,18 +536,28 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/load-nyc-config/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, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -545,20 +566,54 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", - "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2" }, @@ -571,18 +626,16 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -593,33 +646,29 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -627,9 +676,8 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -640,18 +688,16 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -725,12 +771,12 @@ "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", + "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0" + "@octokit/types": "^9.0.0" }, "engines": { "node": ">= 14" @@ -739,21 +785,6 @@ "@octokit/core": ">=4" } }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^14.0.0" - } - }, "node_modules/@octokit/plugin-request-log": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", @@ -764,12 +795,12 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz", - "integrity": "sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", + "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", "dev": true, "dependencies": { - "@octokit/types": "^8.1.1", + "@octokit/types": "^9.0.0", "deprecation": "^2.3.1" }, "engines": { @@ -779,21 +810,6 @@ "@octokit/core": ">=3" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", - "dev": true - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.2.1.tgz", - "integrity": "sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^14.0.0" - } - }, "node_modules/@octokit/request": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", @@ -846,15 +862,15 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", + "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", "dev": true, "dependencies": { "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^5.0.0", + "@octokit/plugin-paginate-rest": "^6.0.0", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.7.0" + "@octokit/plugin-rest-endpoint-methods": "^7.0.0" }, "engines": { "node": ">= 14" @@ -870,10 +886,9 @@ } }, "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "version": "1.0.1", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" }, @@ -883,9 +898,8 @@ }, "node_modules/@pnpm/npm-conf": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-1.0.5.tgz", - "integrity": "sha512-hD8ml183638O3R6/Txrh0L8VzGOrFXgRtRDG4qQC4tONdZ5Z1M+tlUUDUvrjYdmK6G+JTBTeaCLMna11cXzi8A==", "dev": true, + "license": "MIT", "dependencies": { "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" @@ -924,9 +938,8 @@ }, "node_modules/@sindresorhus/is": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", - "integrity": "sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -953,9 +966,9 @@ } }, "node_modules/@sinonjs/samsam": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-7.0.1.tgz", - "integrity": "sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", @@ -971,9 +984,8 @@ }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dev": true, + "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -983,36 +995,31 @@ }, "node_modules/@tootallnate/once": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", @@ -1033,9 +1040,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", - "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==", + "version": "18.15.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", + "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", "dev": true }, "node_modules/@types/semver": { @@ -1046,29 +1053,26 @@ }, "node_modules/@types/sinon": { "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", - "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yallist": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", - "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { - "version": "17.0.22", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", - "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1076,24 +1080,23 @@ }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", - "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", + "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/type-utils": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/type-utils": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -1114,48 +1117,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/parser": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", - "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", + "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "debug": "^4.3.4" }, "engines": { @@ -1175,13 +1145,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", - "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", + "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0" + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1192,13 +1162,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", - "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", + "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.53.0", - "@typescript-eslint/utils": "5.53.0", + "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/utils": "5.57.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1219,9 +1189,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", - "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", + "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1232,13 +1202,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", - "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", + "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/visitor-keys": "5.57.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1258,81 +1228,19 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/utils": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", - "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", + "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.57.0", + "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/typescript-estree": "5.57.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -1346,47 +1254,14 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", + "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", - "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.53.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "5.57.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1397,10 +1272,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.8.1", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1419,18 +1293,16 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -1440,9 +1312,8 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1469,33 +1340,21 @@ }, "node_modules/ansi-align": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.1.0" } }, - "node_modules/ansi-align/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-align/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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ansi-align/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==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1505,31 +1364,18 @@ "node": ">=8" } }, - "node_modules/ansi-align/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-colors": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", - "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.1.0.tgz", + "integrity": "sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==", "dev": true, "dependencies": { "type-fest": "^3.0.0" @@ -1541,16 +1387,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.7.1.tgz", + "integrity": "sha512-8LZNdvuztgxCF4eYpEmPYUPS0lbbByM2qHcp2oMxHZhWLIQB9QE36EeQ1PKwsUIDZXEP8HCBEmkBbT1//kLU4Q==", "dev": true, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/ansi-sequence-parser": { @@ -1560,22 +1414,23 @@ "dev": true }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "4.3.0", "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "version": "3.1.2", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1586,9 +1441,8 @@ }, "node_modules/append-transform": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, + "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -1598,39 +1452,32 @@ }, "node_modules/archy": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1656,9 +1503,8 @@ }, "node_modules/ast-types": { "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.1" }, @@ -1674,9 +1520,8 @@ }, "node_modules/async-retry": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "dev": true, + "license": "MIT", "dependencies": { "retry": "0.13.1" } @@ -1695,9 +1540,8 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1725,11 +1569,19 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1746,10 +1598,9 @@ } }, "node_modules/boxen": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.1.tgz", - "integrity": "sha512-8k2eH6SRAK00NDl1iX5q17RJ8rfl53TajdYxE3ssMLehbg487dEVgsad4pIsZb/QqBgYWIl6JOauMTLGX2Kpkw==", + "version": "7.0.0", "dev": true, + "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^7.0.0", @@ -1768,10 +1619,9 @@ } }, "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "version": "7.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -1779,11 +1629,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boxen/node_modules/chalk": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/boxen/node_modules/type-fest": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -1791,11 +1651,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1803,9 +1674,8 @@ }, "node_modules/braces": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1815,14 +1685,11 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.4", "dev": true, "funding": [ { @@ -1834,11 +1701,12 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" }, "bin": { "browserslist": "cli.js" @@ -1873,24 +1741,36 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/cacheable-lookup": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" } @@ -1915,9 +1795,8 @@ }, "node_modules/caching-transform": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, + "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1952,17 +1831,14 @@ }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001457", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz", - "integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==", + "version": "1.0.30001425", "dev": true, "funding": [ { @@ -1973,15 +1849,19 @@ "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz", - "integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==", + "version": "4.1.2", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -1995,8 +1875,6 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -2004,6 +1882,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2022,9 +1901,8 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2033,34 +1911,22 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.5.0", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-boxes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2105,51 +1971,27 @@ } }, "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "version": "8.0.1", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/cliui/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, "node_modules/cliui/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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cliui/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==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2159,30 +2001,20 @@ "node": ">=8" } }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/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==", + "version": "7.0.0", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/clone": { @@ -2204,9 +2036,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==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2216,33 +2047,28 @@ }, "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commondir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/config-chain": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -2250,15 +2076,13 @@ }, "node_modules/config-chain/node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/configstore": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", - "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "dot-prop": "^6.0.1", "graceful-fs": "^4.2.6", @@ -2275,20 +2099,18 @@ }, "node_modules/convert-source-map": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cosmiconfig": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", - "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "dependencies": { "import-fresh": "^3.2.1", @@ -2298,19 +2120,20 @@ }, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" } }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2320,11 +2143,49 @@ "node": ">= 8" } }, + "node_modules/cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", + "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "node_modules/cross-spawn-async/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/cross-spawn-async/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/cross-spawn-async/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, "node_modules/crypto-random-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^1.0.1" }, @@ -2337,9 +2198,8 @@ }, "node_modules/crypto-random-string/node_modules/type-fest": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2358,9 +2218,8 @@ }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2375,18 +2234,16 @@ }, "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -2399,9 +2256,8 @@ }, "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2411,24 +2267,132 @@ }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", + "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^5.0.0", + "xdg-default-browser": "^2.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/default-browser/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } }, "node_modules/default-require-extensions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, + "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -2453,20 +2417,22 @@ }, "node_modules/defer-to-connect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-properties": { @@ -2487,9 +2453,8 @@ }, "node_modules/degenerator": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", - "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", "dev": true, + "license": "MIT", "dependencies": { "ast-types": "^0.13.2", "escodegen": "^1.8.1", @@ -2502,9 +2467,8 @@ }, "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2517,9 +2481,8 @@ }, "node_modules/diff": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -2538,9 +2501,8 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -2550,9 +2512,8 @@ }, "node_modules/dot-prop": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -2565,15 +2526,13 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz", - "integrity": "sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==", - "dev": true + "version": "1.4.284", + "dev": true, + "license": "ISC" }, "node_modules/email-addresses": { "version": "5.0.0", @@ -2583,9 +2542,8 @@ }, "node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.2", @@ -2702,24 +2660,21 @@ }, "node_modules/es6-error": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-goat": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", - "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2728,12 +2683,11 @@ } }, "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "version": "4.0.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2741,9 +2695,8 @@ }, "node_modules/escodegen": { "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^4.2.0", @@ -2763,9 +2716,8 @@ }, "node_modules/escodegen/node_modules/levn": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -2776,9 +2728,8 @@ }, "node_modules/escodegen/node_modules/optionator": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -2793,8 +2744,6 @@ }, "node_modules/escodegen/node_modules/prelude-ls": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -2802,9 +2751,8 @@ }, "node_modules/escodegen/node_modules/type-check": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -2813,12 +2761,15 @@ } }, "node_modules/eslint": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", - "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.1", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2829,10 +2780,9 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -2853,7 +2803,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -2881,99 +2830,22 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2984,90 +2856,16 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -3083,9 +2881,8 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3095,9 +2892,9 @@ } }, "node_modules/esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -3117,9 +2914,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3129,40 +2925,37 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/execa": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", - "human-signals": "^3.0.1", + "human-signals": "^4.3.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", @@ -3171,14 +2964,26 @@ "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/external-editor": { - "version": "3.1.0", + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, @@ -3233,15 +3038,13 @@ }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.13.0", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -3285,11 +3088,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -3299,27 +3125,24 @@ }, "node_modules/file-uri-to-path": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", - "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/filename-reserved-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/filenamify": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, + "license": "MIT", "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -3334,9 +3157,8 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3346,9 +3168,8 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -3362,32 +3183,32 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -3398,9 +3219,8 @@ }, "node_modules/flatted": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", @@ -3413,9 +3233,8 @@ }, "node_modules/foreground-child": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -3425,10 +3244,9 @@ } }, "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "version": "2.1.3", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.17" } @@ -3447,8 +3265,6 @@ }, "node_modules/fromentries": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { @@ -3463,13 +3279,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/fs-extra": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -3481,28 +3297,11 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "license": "ISC" }, "node_modules/ftp": { "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", "dev": true, "dependencies": { "readable-stream": "1.1.x", @@ -3514,15 +3313,13 @@ }, "node_modules/ftp/node_modules/isarray": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ftp/node_modules/readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -3532,15 +3329,13 @@ }, "node_modules/ftp/node_modules/string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -3571,26 +3366,23 @@ }, "node_modules/generic-pool": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -3611,18 +3403,16 @@ }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3648,9 +3438,8 @@ }, "node_modules/get-uri": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", - "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "1", "data-uri-to-buffer": "3", @@ -3665,9 +3454,8 @@ }, "node_modules/get-uri/node_modules/data-uri-to-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -3694,11 +3482,38 @@ "node": ">=10" } }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/git-up": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "dev": true, + "license": "MIT", "dependencies": { "is-ssh": "^1.4.0", "parse-url": "^8.1.0" @@ -3706,23 +3521,21 @@ }, "node_modules/git-url-parse": { "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", "dev": true, + "license": "MIT", "dependencies": { "git-up": "^7.0.0" } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "7.2.0", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.1.1", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -3735,9 +3548,8 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -3746,10 +3558,9 @@ } }, "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "version": "3.0.0", "dev": true, + "license": "MIT", "dependencies": { "ini": "2.0.0" }, @@ -3775,18 +3586,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", @@ -3803,19 +3602,23 @@ } }, "node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gopd": { @@ -3831,15 +3634,15 @@ } }, "node_modules/got": { - "version": "12.5.3", - "resolved": "https://registry.npmjs.org/got/-/got-12.5.3.tgz", - "integrity": "sha512-8wKnb9MGU8IPGRIo+/ukTy9XLJBwDiCpIf5TVzQ9Cpol50eMTpBq2GAuDsuDIz7hTYmZgMgC1e9ydr6kSDWs3w==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.0.tgz", + "integrity": "sha512-WTcaQ963xV97MN3x0/CbAriXFZcXCfgxVp91I+Ze6pawQOa7SgzwSx2zIJJsX+kTajMnVs0xcFD1TxZKFqhdnQ==", "dev": true, "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.1", + "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", @@ -3857,21 +3660,18 @@ }, "node_modules/graceful-fs": { "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/grapheme-splitter": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -3890,9 +3690,8 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3950,9 +3749,8 @@ }, "node_modules/has-yarn": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", - "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -3962,9 +3760,8 @@ }, "node_modules/hasha": { "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, + "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -3976,41 +3773,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hasha/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/html-escaper": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-cache-semantics": { "version": "4.1.1", @@ -4020,9 +3802,8 @@ }, "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -4036,9 +3817,8 @@ }, "node_modules/http-proxy-agent": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -4049,10 +3829,9 @@ } }, "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "version": "2.1.11", "dev": true, + "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -4063,9 +3842,8 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -4075,19 +3853,18 @@ } }, "node_modules/human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "dev": true, "engines": { - "node": ">=12.20.0" + "node": ">=14.18.0" } }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -4116,10 +3893,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.2.0", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -4142,36 +3918,32 @@ }, "node_modules/import-lazy": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -4179,43 +3951,80 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ini": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/inquirer": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", - "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.5.tgz", + "integrity": "sha512-3ygAIh8gcZavV9bj6MTdYddG2zPSYswP808fKS46NOwlF0zZljVpnLCHODDqItWJDbDpLb3aouAxGaJbkxoppA==", "dev": true, "dependencies": { "ansi-escapes": "^6.0.0", - "chalk": "^5.1.2", + "chalk": "^5.2.0", "cli-cursor": "^4.0.0", "cli-width": "^4.0.0", "external-editor": "^3.0.3", "figures": "^5.0.0", "lodash": "^4.17.21", - "mute-stream": "0.0.8", + "mute-stream": "1.0.0", "ora": "^6.1.2", "run-async": "^2.4.0", - "rxjs": "^7.5.7", + "rxjs": "^7.8.0", "string-width": "^5.1.2", "strip-ansi": "^7.0.1", "through": "^2.3.6", - "wrap-ansi": "^8.0.1" + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/internal-slot": { @@ -4234,18 +4043,16 @@ }, "node_modules/interpret": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/ip": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-arguments": { "version": "1.1.1", @@ -4264,13 +4071,13 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-typed-array": "^1.1.10" }, "funding": { @@ -4297,9 +4104,8 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4337,9 +4143,8 @@ }, "node_modules/is-ci": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, + "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -4349,9 +4154,8 @@ }, "node_modules/is-core-module": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -4375,15 +4179,15 @@ } }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4391,27 +4195,24 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -4419,11 +4220,28 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, + "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" @@ -4470,9 +4288,8 @@ }, "node_modules/is-npm": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4482,9 +4299,8 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4506,27 +4322,24 @@ }, "node_modules/is-obj": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-path-inside": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4579,20 +4392,18 @@ }, "node_modules/is-ssh": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", "dev": true, + "license": "MIT", "dependencies": { "protocols": "^2.0.1" } }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "version": "2.0.1", "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4649,17 +4460,15 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "version": "0.1.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4679,9 +4488,8 @@ }, "node_modules/is-windows": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4698,11 +4506,25 @@ "node": ">=8" } }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-yarn-global": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", - "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "version": "0.4.0", "dev": true, + "license": "MIT", "engines": { "node": ">=12" } @@ -4715,24 +4537,21 @@ }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -4742,9 +4561,8 @@ }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -4755,11 +4573,18 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, + "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -4774,9 +4599,8 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -4788,9 +4612,8 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -4802,9 +4625,8 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -4836,26 +4658,19 @@ } }, "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "version": "4.1.5", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4865,9 +4680,8 @@ }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -4895,9 +4709,8 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", @@ -4919,9 +4732,8 @@ }, "node_modules/jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4943,9 +4755,8 @@ }, "node_modules/latest-version": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", "dev": true, + "license": "MIT", "dependencies": { "package-json": "^8.1.0" }, @@ -4958,9 +4769,8 @@ }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -4976,15 +4786,17 @@ "dev": true }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -4995,9 +4807,8 @@ }, "node_modules/lodash.flattendeep": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.get": { "version": "4.4.2", @@ -5007,21 +4818,19 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "version": "4.1.0", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5041,18 +4850,16 @@ }, "node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/lunr": { "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/macos-release": { "version": "3.1.0", @@ -5068,9 +4875,8 @@ }, "node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -5081,11 +4887,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/marked": { "version": "4.2.12", @@ -5174,9 +4987,8 @@ }, "node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5185,10 +4997,9 @@ } }, "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "version": "1.2.7", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5233,405 +5044,178 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/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==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/mocha/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==", + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", "dev": true, + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/mocha/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", "dev": true, + "license": "ISC", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/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==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, + "has-flag": "^4.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/ms": { + "version": "2.1.2", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "*" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/mocha/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/netmask": { + "version": "2.0.2", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4.0" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/new-github-release-url": { + "version": "2.0.0", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "type-fest": "^2.5.1" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/new-github-release-url/node_modules/type-fest": { + "version": "2.19.0", "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", - "dev": true, - "dependencies": { - "type-fest": "^2.5.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/new-github-release-url/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "node_modules/nise": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", @@ -5661,9 +5245,9 @@ } }, "node_modules/node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", "dev": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", @@ -5680,9 +5264,8 @@ }, "node_modules/node-preload": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, + "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -5691,16 +5274,14 @@ } }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true + "version": "2.0.6", + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5746,9 +5327,8 @@ }, "node_modules/nyc": { "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -5785,20 +5365,145 @@ "node": ">=8.9" } }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, "engines": { "node": ">=8" } }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5841,9 +5546,8 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -5864,17 +5568,18 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", + "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", + "default-browser": "^3.1.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", "is-wsl": "^2.2.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5882,9 +5587,8 @@ }, "node_modules/optionator": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -5898,18 +5602,18 @@ } }, "node_modules/ora": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", - "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz", + "integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==", "dev": true, "dependencies": { - "bl": "^5.0.0", "chalk": "^5.0.0", "cli-cursor": "^4.0.0", "cli-spinners": "^2.6.1", "is-interactive": "^2.0.0", "is-unicode-supported": "^1.1.0", "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" }, @@ -5920,13 +5624,80 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "dev": true, + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/os-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.0.1.tgz", - "integrity": "sha512-0EQpaHUHq7olp2/YFUr+0vZi9tMpDTblHGz+Ch5RntKxiRXOAY0JOz1UlxhSjMSksHvkm13eD6elJj3M8Ht/kw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", + "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", "dev": true, "dependencies": { - "macos-release": "^3.0.1", + "macos-release": "^3.1.0", "windows-release": "^5.0.1" }, "engines": { @@ -5947,45 +5718,44 @@ }, "node_modules/p-cancelable": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.20" } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -5995,18 +5765,16 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pac-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", - "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -6024,9 +5792,8 @@ }, "node_modules/pac-resolver": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", - "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", "dev": true, + "license": "MIT", "dependencies": { "degenerator": "^3.0.2", "ip": "^1.1.5", @@ -6038,9 +5805,8 @@ }, "node_modules/package-hash": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, + "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -6053,9 +5819,8 @@ }, "node_modules/package-json": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.0.tgz", - "integrity": "sha512-hySwcV8RAWeAfPsXb9/HGSPn8lwDnv6fabH+obUZKX169QknRkRhPxd1yMubpKDskLFATkl3jHpNtVtDPFA0Wg==", "dev": true, + "license": "MIT", "dependencies": { "got": "^12.1.0", "registry-auth-token": "^5.0.1", @@ -6069,39 +5834,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6134,54 +5866,48 @@ }, "node_modules/parse-path": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", "dev": true, + "license": "MIT", "dependencies": { "protocols": "^2.0.0" } }, "node_modules/parse-url": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "dev": true, + "license": "MIT", "dependencies": { "parse-path": "^7.0.0" } }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-to-regexp": { "version": "1.8.0", @@ -6209,15 +5935,13 @@ }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -6227,27 +5951,24 @@ }, "node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, + "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -6257,9 +5978,8 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -6267,20 +5987,66 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/process-on-spawn": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, + "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -6310,21 +6076,18 @@ }, "node_modules/proto-list": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/protocols": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", - "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^6.0.0", "debug": "4", @@ -6341,8 +6104,13 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, "node_modules/punycode": { @@ -6356,9 +6124,8 @@ }, "node_modules/pupa": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", "dev": true, + "license": "MIT", "dependencies": { "escape-goat": "^4.0.0" }, @@ -6371,8 +6138,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -6387,13 +6152,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6403,18 +6168,16 @@ }, "node_modules/randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.1", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6427,9 +6190,8 @@ }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -6442,23 +6204,21 @@ }, "node_modules/rc/node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -6471,9 +6231,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -6483,8 +6242,6 @@ }, "node_modules/rechoir": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "dependencies": { "resolve": "^1.1.6" @@ -6510,23 +6267,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/registry-auth-token": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.1.tgz", - "integrity": "sha512-UfxVOj8seK1yaIOiieV4FIP01vfBDLsY0H9sQzi9EbbUdJiuuBjJgLa1DpImXMNPnVkBD4eVxTEXcrZA6kfpJA==", "dev": true, + "license": "MIT", "dependencies": { "@pnpm/npm-conf": "^1.0.4" }, @@ -6536,9 +6280,8 @@ }, "node_modules/registry-url": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", "dev": true, + "license": "MIT", "dependencies": { "rc": "1.2.8" }, @@ -6550,29 +6293,29 @@ } }, "node_modules/release-it": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.6.0.tgz", - "integrity": "sha512-NXewgzO8QV1LOFjn2K7/dgE1Y1cG+2JiLOU/x9X/Lq9UdFn2hTH1r9SSrufCxG+y/Rp+oN8liYTsNptKrj92kg==", + "version": "15.9.3", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.9.3.tgz", + "integrity": "sha512-yFZTGJ9lH075zEAiVB4w58GgQ+bFR4by+eNClN3sdLtTLwbEm9VXrISt+8vO1fHDH83557Fns5ub1FuhAY/a3A==", "dev": true, "dependencies": { "@iarna/toml": "2.2.5", - "@octokit/rest": "19.0.5", + "@octokit/rest": "19.0.7", "async-retry": "1.3.3", - "chalk": "5.1.2", - "cosmiconfig": "8.0.0", - "execa": "6.1.0", + "chalk": "5.2.0", + "cosmiconfig": "8.1.3", + "execa": "7.1.1", "git-url-parse": "13.1.0", - "globby": "13.1.2", - "got": "12.5.3", - "inquirer": "9.1.4", + "globby": "13.1.3", + "got": "12.6.0", + "inquirer": "9.1.5", "is-ci": "3.0.1", "lodash": "4.17.21", "mime-types": "2.1.35", "new-github-release-url": "2.0.0", - "node-fetch": "3.3.0", - "open": "8.4.0", - "ora": "6.1.2", - "os-name": "5.0.1", + "node-fetch": "3.3.1", + "open": "9.0.0", + "ora": "6.3.0", + "os-name": "5.1.0", "promise.allsettled": "1.0.6", "proxy-agent": "5.0.0", "semver": "7.3.8", @@ -6589,10 +6332,22 @@ "node": ">=14.9" } }, + "node_modules/release-it/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/release-it/node_modules/globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz", + "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", @@ -6608,33 +6363,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/release-it/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/release-it/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/release-it/node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -6647,17 +6375,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/release-it/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/release-it/node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } }, "node_modules/release-zalgo": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, + "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -6667,24 +6396,21 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -6699,9 +6425,8 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", @@ -6718,32 +6443,134 @@ "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, "dependencies": { - "lowercase-keys": "^3.0.0" + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/run-applescript/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==", @@ -6752,7 +6579,19 @@ "node": ">=6" } }, - "node_modules/restore-cursor/node_modules/onetime": { + "node_modules/run-applescript/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript/node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", @@ -6767,38 +6606,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/run-applescript/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=6" } }, "node_modules/run-async": { @@ -6812,8 +6626,6 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -6829,6 +6641,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -6844,8 +6657,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -6860,7 +6671,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.0.0", @@ -6878,24 +6690,27 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.8", "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/semver-diff": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", - "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -6906,11 +6721,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver-diff/node_modules/lru-cache": { + "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -6918,53 +6732,33 @@ "node": ">=10" } }, - "node_modules/semver-diff/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-diff/node_modules/yallist": { + "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serialize-javascript": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6974,18 +6768,16 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shelljs": { "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -7026,21 +6818,20 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sinon": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.1.tgz", - "integrity": "sha512-PZXKc08f/wcA/BMRGBze2Wmw50CWPiAH3E21EOi4B49vJ616vW4DQh4fQrqsYox2aNR/N3kCqLuB0PwwOucQrg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.3.tgz", + "integrity": "sha512-si3geiRkeovP7Iel2O+qGL4NrO9vbMf3KsrJEi0ghP1l5aBkB5UxARea5j0FUsSqH3HLBh0dQPAyQ8fObRUqHw==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "10.0.2", - "@sinonjs/samsam": "^7.0.1", - "diff": "^5.0.0", - "nise": "^5.1.2", + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.1.0", + "nise": "^5.1.4", "supports-color": "^7.2.0" }, "funding": { @@ -7048,6 +6839,24 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/sinon/node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7059,9 +6868,8 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -7069,9 +6877,8 @@ }, "node_modules/socks": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, + "license": "MIT", "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -7083,9 +6890,8 @@ }, "node_modules/socks-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "4", @@ -7097,24 +6903,21 @@ }, "node_modules/socks/node_modules/ip": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7122,9 +6925,8 @@ }, "node_modules/spawn-wrap": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -7139,19 +6941,32 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -7175,9 +6990,8 @@ }, "node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -7190,6 +7004,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -7219,29 +7058,33 @@ } }, "node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "6.0.1", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -7256,9 +7099,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -7268,9 +7110,8 @@ }, "node_modules/strip-outer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7280,18 +7121,16 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7301,9 +7140,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7313,9 +7151,8 @@ }, "node_modules/test-exclude": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -7327,9 +7164,8 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through": { "version": "2.3.8", @@ -7337,6 +7173,15 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/titleize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", + "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -7351,18 +7196,16 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -7372,9 +7215,8 @@ }, "node_modules/toidentifier": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } @@ -7387,9 +7229,8 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7399,18 +7240,16 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7451,24 +7290,21 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true + "version": "2.4.0", + "dev": true, + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -7481,15 +7317,13 @@ }, "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -7507,12 +7341,12 @@ } }, "node_modules/type-fest": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.0.tgz", - "integrity": "sha512-RqTRtKTzvPpNdDUp1dVkKQRunlPITk4mXeqFlAZoJsS+fLRn8AdPK0TcQDumGayhU7fjlBfiBjsq3pe3rIfXZQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { - "node": ">=14.16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7534,22 +7368,21 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, + "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { - "version": "0.23.25", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.25.tgz", - "integrity": "sha512-O1he153qVyoCgJYSvIyY3bPP1wAJTegZfa6tL3APinSZhJOf8CSd8F/21M6ex8pUY/fuY6n0jAsT4fIuMGA6sA==", + "version": "0.23.28", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.28.tgz", + "integrity": "sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==", "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.2.12", - "minimatch": "^6.1.6", + "minimatch": "^7.1.3", "shiki": "^0.14.1" }, "bin": { @@ -7559,7 +7392,7 @@ "node": ">= 14.14" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -7572,9 +7405,9 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", - "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", + "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7587,16 +7420,16 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/unbox-primitive": { @@ -7616,9 +7449,8 @@ }, "node_modules/unique-string": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", "dev": true, + "license": "MIT", "dependencies": { "crypto-random-string": "^4.0.0" }, @@ -7637,26 +7469,31 @@ }, "node_modules/universalify": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "dev": true, "funding": [ { @@ -7668,6 +7505,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -7681,9 +7519,8 @@ }, "node_modules/update-notifier": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", - "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boxen": "^7.0.0", "chalk": "^5.0.1", @@ -7707,38 +7544,16 @@ "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, - "node_modules/update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, "node_modules/uri-js": { "version": "4.4.1", @@ -7751,9 +7566,8 @@ }, "node_modules/url-join": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -7766,24 +7580,21 @@ }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vm2": { - "version": "3.9.14", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.14.tgz", - "integrity": "sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA==", + "version": "3.9.11", "dev": true, + "license": "MIT", "dependencies": { "acorn": "^8.7.0", "acorn-walk": "^8.2.0" @@ -7843,9 +7654,8 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -7874,9 +7684,8 @@ }, "node_modules/which-module": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/which-typed-array": { "version": "1.1.9", @@ -7900,9 +7709,8 @@ }, "node_modules/widest-line": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^5.0.1" }, @@ -7915,9 +7723,8 @@ }, "node_modules/wildcard-match": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", - "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/windows-release": { "version": "5.1.0", @@ -7966,18 +7773,6 @@ "node": ">=10.17.0" } }, - "node_modules/windows-release/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/windows-release/node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -8025,18 +7820,16 @@ }, "node_modules/word-wrap": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "8.1.0", @@ -8055,17 +7848,51 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -8075,9 +7902,8 @@ }, "node_modules/xdg-basedir": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8085,63 +7911,104 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", + "node_modules/xdg-default-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", + "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", "dev": true, + "dependencies": { + "execa": "^0.2.2", + "titleize": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">=4" + } + }, + "node_modules/xdg-default-browser/node_modules/execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", + "dev": true, + "dependencies": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/xdg-default-browser/node_modules/npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", + "dev": true, + "dependencies": { + "path-key": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xdg-default-browser/node_modules/path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, + "node_modules/xregexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dev": true, "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=8" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "20.2.4", "dev": true, + "license": "ISC", "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -8154,9 +8021,8 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8166,9 +8032,8 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8176,26 +8041,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/yargs/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==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8205,45 +8059,26 @@ "node": ">=8" } }, - "node_modules/yargs/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "version": "21.1.1", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=12" } }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8258,13 +8093,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8282,19 +8117,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "@types/sinon": "^10.0.13", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.53.0", - "@typescript-eslint/parser": "^5.53.0", - "eslint": "^8.34.0", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", + "eslint": "^8.36.0", "nyc": "^15.1.0", - "release-it": "^15.6.0", - "sinon": "^15.0.1", + "release-it": "^15.9.3", + "sinon": "^15.0.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "engines": { "node": ">=14" @@ -8302,8 +8137,7 @@ }, "packages/client/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "packages/graph": { "name": "@redis/graph", @@ -8312,13 +8146,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8331,13 +8165,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8350,13 +8184,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8367,133 +8201,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "^18.14.1", - "@types/yargs": "^17.0.22", + "@types/node": "^18.15.10", + "@types/yargs": "^17.0.24", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typescript": "^4.9.5", + "typescript": "^5.0.2", "yargs": "^17.7.1" }, "peerDependencies": { "@redis/client": "^1.0.0" } }, - "packages/test-utils/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "packages/test-utils/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/test-utils/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==", - "dev": true - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "packages/test-utils/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "packages/test-utils/node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, "packages/time-series": { "name": "@redis/time-series", "version": "1.0.4", @@ -8501,13 +8221,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "peerDependencies": { "@redis/client": "^1.0.0" diff --git a/package.json b/package.json index def009747ca..3be6fe2175b 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "devDependencies": { "@tsconfig/node14": "^1.0.3", "gh-pages": "^5.0.0", - "release-it": "^15.6.0", - "typescript": "^4.9.5" + "release-it": "^15.9.3", + "typescript": "^5.0.2" }, "repository": { "type": "git", diff --git a/packages/bloom/lib/commands/bloom/INSERT.ts b/packages/bloom/lib/commands/bloom/INSERT.ts index f6deb7a8612..4c3cec0f79b 100644 --- a/packages/bloom/lib/commands/bloom/INSERT.ts +++ b/packages/bloom/lib/commands/bloom/INSERT.ts @@ -1,4 +1,4 @@ -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; export const FIRST_KEY_INDEX = 1; @@ -39,7 +39,7 @@ export function transformArguments( } args.push('ITEMS'); - return pushVerdictArguments(args, items); + return pushVariadicArguments(args, items); } export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; diff --git a/packages/bloom/lib/commands/count-min-sketch/QUERY.ts b/packages/bloom/lib/commands/count-min-sketch/QUERY.ts index 13a71c9b1de..a34a9e9b9a0 100644 --- a/packages/bloom/lib/commands/count-min-sketch/QUERY.ts +++ b/packages/bloom/lib/commands/count-min-sketch/QUERY.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,7 +9,7 @@ export function transformArguments( key: string, items: string | Array ): RedisCommandArguments { - return pushVerdictArguments(['CMS.QUERY', key], items); + return pushVariadicArguments(['CMS.QUERY', key], items); } export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/cuckoo/index.ts b/packages/bloom/lib/commands/cuckoo/index.ts index 96b4453bc39..c34bdde503d 100644 --- a/packages/bloom/lib/commands/cuckoo/index.ts +++ b/packages/bloom/lib/commands/cuckoo/index.ts @@ -10,7 +10,7 @@ import * as INSERTNX from './INSERTNX'; import * as LOADCHUNK from './LOADCHUNK'; import * as RESERVE from './RESERVE'; import * as SCANDUMP from './SCANDUMP'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; export default { @@ -58,5 +58,5 @@ export function pushInsertOptions( } args.push('ITEMS'); - return pushVerdictArguments(args, items); + return pushVariadicArguments(args, items); } diff --git a/packages/bloom/lib/commands/t-digest/MERGE.ts b/packages/bloom/lib/commands/t-digest/MERGE.ts index 5119d0b9e18..1aebe6fa47b 100644 --- a/packages/bloom/lib/commands/t-digest/MERGE.ts +++ b/packages/bloom/lib/commands/t-digest/MERGE.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { CompressionOption, pushCompressionArgument } from '.'; export const FIRST_KEY_INDEX = 1; @@ -13,7 +13,7 @@ export function transformArguments( srcKeys: RedisCommandArgument | Array, options?: MergeOptions ): RedisCommandArguments { - const args = pushVerdictArgument( + const args = pushVariadicArgument( ['TDIGEST.MERGE', destKey], srcKeys ); diff --git a/packages/bloom/lib/commands/top-k/ADD.ts b/packages/bloom/lib/commands/top-k/ADD.ts index beee3a2206c..125c2e71bef 100644 --- a/packages/bloom/lib/commands/top-k/ADD.ts +++ b/packages/bloom/lib/commands/top-k/ADD.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: string, items: string | Array ): RedisCommandArguments { - return pushVerdictArguments(['TOPK.ADD', key], items); + return pushVariadicArguments(['TOPK.ADD', key], items); } export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/top-k/COUNT.ts b/packages/bloom/lib/commands/top-k/COUNT.ts index fc8cf557dca..cb877ecc25f 100644 --- a/packages/bloom/lib/commands/top-k/COUNT.ts +++ b/packages/bloom/lib/commands/top-k/COUNT.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,7 +9,7 @@ export function transformArguments( key: string, items: string | Array ): RedisCommandArguments { - return pushVerdictArguments(['TOPK.COUNT', key], items); + return pushVariadicArguments(['TOPK.COUNT', key], items); } export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/top-k/QUERY.ts b/packages/bloom/lib/commands/top-k/QUERY.ts index 94943a26fd7..55451df3d45 100644 --- a/packages/bloom/lib/commands/top-k/QUERY.ts +++ b/packages/bloom/lib/commands/top-k/QUERY.ts @@ -1,5 +1,5 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,7 +9,7 @@ export function transformArguments( key: string, items: string | Array ): RedisCommandArguments { - return pushVerdictArguments(['TOPK.QUERY', key], items); + return pushVariadicArguments(['TOPK.QUERY', key], items); } export declare function transformReply(): Array; diff --git a/packages/bloom/package.json b/packages/bloom/package.json index d4eef193d84..aae71bb442e 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -18,12 +18,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" } } diff --git a/packages/client/.eslintrc.json b/packages/client/.eslintrc.json index 4536bc31338..3037932fd97 100644 --- a/packages/client/.eslintrc.json +++ b/packages/client/.eslintrc.json @@ -1,15 +1,15 @@ { - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "rules": { - "semi": [2, "always"] - } + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "semi": [2, "always"] } +} diff --git a/packages/client/index.ts b/packages/client/index.ts index 8b21c5d5a32..7bb2f239469 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -1,24 +1,18 @@ -import RedisClient from './lib/client'; -import RedisCluster from './lib/cluster'; - -export { RedisClientType, RedisClientOptions } from './lib/client'; - -export { RedisModules, RedisFunctions, RedisScripts } from './lib/commands'; +export { RedisModules, RedisFunctions, RedisScripts, RespVersions } from './lib/RESP/types'; +export { VerbatimString } from './lib/RESP/verbatim-string'; +export { defineScript } from './lib/lua-script'; +// export * from './lib/errors'; +import RedisClient, { RedisClientType, RedisClientOptions } from './lib/client'; +export { RedisClientType, RedisClientOptions }; export const createClient = RedisClient.create; -export const commandOptions = RedisClient.commandOptions; - -export { RedisClusterType, RedisClusterOptions } from './lib/cluster'; - +import RedisCluster, { RedisClusterType, RedisClusterOptions } from './lib/cluster'; +export { RedisClusterType, RedisClusterOptions }; export const createCluster = RedisCluster.create; -export { defineScript } from './lib/lua-script'; - -export * from './lib/errors'; - -export { GeoReplyWith } from './lib/commands/generic-transformers'; +// export { GeoReplyWith } from './lib/commands/generic-transformers'; -export { SetOptions } from './lib/commands/SET'; +// export { SetOptions } from './lib/commands/SET'; -export { RedisFlushModes } from './lib/commands/FLUSHALL'; +// export { RedisFlushModes } from './lib/commands/FLUSHALL'; diff --git a/packages/client/lib/RESP/decoder-ts.ts b/packages/client/lib/RESP/decoder-ts.ts new file mode 100644 index 00000000000..0586940f692 --- /dev/null +++ b/packages/client/lib/RESP/decoder-ts.ts @@ -0,0 +1,1043 @@ +// import { ErrorReply } from '../../errors'; +// import { Flags, ReplyUnion, RespTypesUnion, ReplyWithFlags, RespTypes, Flag } from './types'; + +// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md +// export const TYPES = { +// NULL: 95, // _ +// BOOLEAN: 35, // # +// NUMBER: 58, // : +// BIG_NUMBER: 40, // ( +// DOUBLE: 44, // , +// SIMPLE_STRING: 43, // + +// BLOB_STRING: 36, // $ +// VERBATIM_STRING: 61, // = +// SIMPLE_ERROR: 45, // - +// BLOB_ERROR: 33, // ! +// ARRAY: 42, // * +// SET: 126, // ~ +// MAP: 37, // % +// PUSH: 62 // > +// } as const; + +// const ASCII = { +// '\r': 13, +// 't': 116, +// '-': 45, +// '0': 48, +// '.': 46, +// 'i': 105, +// 'n': 110 +// } as const; + +// // this was written with performance in mind, so it's not very readable... sorry :( + +// interface DecoderConfig { +// // TODO: on parser error? +// // TODO: types +// onReply(reply: unknown): unknown; +// onErrorReply(reply: unknown): unknown; +// onPush(push: unknown): unknown; +// getFlags(): Flags; +// } + +// type ValueCb = DecoderConfig['onReply'] | DecoderConfig['onErrorReply'] | DecoderConfig['onPush']; + +// type Next = (chunk: Buffer) => ValueOrNext; + +// type ValueOrNext = T | Next; + +// export class Decoder { +// #config: DecoderConfig; + +// #cursor = 0; + +// #next: Next | undefined; + +// constructor(config: DecoderConfig) { +// this.#config = config; +// } + +// reset() { +// this.#cursor = 0; +// this.#next = undefined; +// } + +// write(chunk: Buffer) { +// if (this.#cursor >= chunk.length) { +// this.#cursor -= chunk.length; +// return; +// } + +// if (this.#next) { +// if (this.#next(chunk) || this.#cursor >= chunk.length) { +// this.#cursor -= chunk.length; +// return; +// } +// } + +// do { +// const flags = this.#config.getFlags(), +// type = chunk[this.#cursor] as RespTypesUnion; + +// if (++this.#cursor === chunk.length) { +// this.#next = this.#continueDecodeTypeValue.bind(this, type, flags); +// break; +// } + +// if (this.#decodeTypeValue(type, flags, chunk)) { +// break; +// } +// } while (this.#cursor < chunk.length); +// this.#cursor -= chunk.length; +// } + +// #continueDecodeTypeValue( +// type: RespTypesUnion, +// flags: Flags, +// chunk: Buffer +// ) { +// this.#next = undefined; +// return this.#decodeTypeValue(type, flags, chunk); +// } + +// #decodeTypeValue( +// type: RespTypesUnion, +// flags: Flags, +// chunk: Buffer +// ) { +// switch (type) { +// case TYPES.NULL: +// this.#config.onReply(this.#decodeNull()); +// return false; + +// case TYPES.BOOLEAN: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeBoolean(chunk) +// ); + +// case TYPES.NUMBER: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeNumber(chunk) +// ); + +// case TYPES.BIG_NUMBER: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk) +// ); + +// case TYPES.DOUBLE: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeDouble(flags[TYPES.DOUBLE], chunk) +// ); + +// case TYPES.SIMPLE_STRING: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeDouble(flags[TYPES.DOUBLE], chunk) +// ); + +// case TYPES.BLOB_STRING: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeBlobString(flags[TYPES.BLOB_STRING], chunk) +// ); + +// case TYPES.VERBATIM_STRING: +// throw new Error('TODO: verbatim string'); + +// case TYPES.SIMPLE_ERROR: +// return this.#handleDecodedValue( +// this.#config.onErrorReply, +// this.#decodeSimpleError(chunk) +// ); + +// case TYPES.BLOB_ERROR: +// return this.#handleDecodedValue( +// this.#config.onErrorReply, +// this.#decodeBlobError(chunk) +// ); + +// case TYPES.ARRAY: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeArray(flags, chunk) +// ); + +// case TYPES.SET: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeSet(flags, chunk) +// ); + +// case TYPES.MAP: +// return this.#handleDecodedValue( +// this.#config.onReply, +// this.#decodeMap(flags, chunk) +// ); + +// case TYPES.PUSH: +// return this.#handleDecodedValue( +// this.#config.onPush, +// this.#decodeArray(flags, chunk) +// ); +// } +// } + +// #handleDecodedValue(cb: ValueCb, value: ValueOrNext) { +// if (typeof value === 'function') { +// this.#next = this.#continueDecodeValue.bind(this, cb, value); +// return true; +// } + +// cb(value); +// return false; +// } + +// #continueDecodeValue( +// cb: ValueCb, +// next: Next, +// chunk: Buffer +// ) { +// this.#next = undefined; +// return this.#handleDecodedValue(cb, next(chunk)); +// } + +// #decodeNull() { +// this.#cursor += 2; // skip \r\n +// return null; +// } + +// #decodeBoolean(chunk: Buffer) { +// const boolean = chunk[this.#cursor] === ASCII['t']; +// this.#cursor += 3; // skip {t | f}\r\n +// return boolean; +// } + +// #decodeNumber(chunk: Buffer) { +// const isNegative = chunk[this.#cursor] === ASCII['-']; +// if (isNegative && ++this.#cursor === chunk.length) { +// return this.#continueDecodeNumber.bind( +// this, +// isNegative, +// this.#decodeUnsingedNumber.bind(this, 0) +// ); +// } + +// const number = this.#decodeUnsingedNumber(0, chunk); +// return typeof number === 'function' ? +// this.#continueDecodeNumber.bind(this, isNegative, number) : +// isNegative ? -number : number; +// } + +// #continueDecodeNumber( +// isNegative: boolean, +// numberCb: Next, +// chunk: Buffer +// ): ValueOrNext { +// const number = numberCb(chunk); +// return typeof number === 'function' ? +// this.#continueDecodeNumber.bind(this, isNegative, number) : +// isNegative ? -number : number; +// } + +// #decodeUnsingedNumber( +// number: number, +// chunk: Buffer +// ): ValueOrNext { +// let cursor = this.#cursor; +// do { +// const byte = chunk[cursor]; +// if (byte === ASCII['\r']) { +// this.#cursor = cursor + 2; // skip \r\n +// return number; +// } +// number = number * 10 + byte - ASCII['0']; +// } while (++cursor < chunk.length); + +// this.#cursor = cursor; +// return this.#decodeUnsingedNumber.bind(this, number); +// } + +// #decodeBigNumber(flag: Flags[typeof TYPES.BIG_NUMBER], chunk: Buffer) { +// if (flag === String) { +// return this.#decodeSimpleString(String, chunk); +// } + +// const isNegative = chunk[this.#cursor] === ASCII['-']; +// if (isNegative && ++this.#cursor === chunk.length) { +// return this.#continueDecodeBigNumber.bind( +// this, +// isNegative, +// this.#decodeUnsingedBigNumber.bind(this, 0n) +// ); +// } + +// const bigNumber = this.#decodeUnsingedBigNumber(0n, chunk); +// return typeof bigNumber === 'function' ? +// this.#continueDecodeBigNumber.bind(this, isNegative, bigNumber) : +// isNegative ? -bigNumber : bigNumber; +// } + +// #continueDecodeBigNumber( +// isNegative: boolean, +// bigNumberCb: Next, +// chunk: Buffer +// ): ValueOrNext { +// const bigNumber = bigNumberCb(chunk); +// return typeof bigNumber === 'function' ? +// this.#continueDecodeBigNumber.bind(this, isNegative, bigNumber) : +// isNegative ? -bigNumber : bigNumber; +// } + +// #decodeUnsingedBigNumber( +// bigNumber: bigint, +// chunk: Buffer +// ): ValueOrNext { +// let cursor = this.#cursor; +// do { +// const byte = chunk[cursor]; +// if (byte === ASCII['\r']) { +// this.#cursor = cursor + 2; // skip \r\n +// return bigNumber; +// } +// bigNumber = bigNumber * 10n + BigInt(byte - ASCII['0']); +// } while (++cursor < chunk.length); + +// this.#cursor = cursor; +// return this.#decodeUnsingedBigNumber.bind(this, bigNumber); +// } + +// #decodeDouble(flag: Flags[RespTypes['DOUBLE']], chunk: Buffer) { +// if (flag === String) { +// return this.#decodeSimpleString(String, chunk); +// } + +// switch (chunk[this.#cursor]) { +// case ASCII['n']: +// this.#cursor += 5; // skip nan\r\n +// return NaN; + +// case ASCII['-']: +// return ++this.#cursor === chunk.length ? +// this.#decodeDoubleInteger.bind(this, true, 0, chunk) : +// this.#decodeDoubleInteger(true, 0, chunk); + +// default: +// return this.#decodeDoubleInteger(false, 0, chunk); +// } +// } + +// #decodeDoubleInteger( +// isNegative: boolean, +// integer: number, +// chunk: Buffer +// ) { +// if (chunk[this.#cursor] === ASCII['i']) { +// this.#cursor += 5; // skip inf\r\n +// return isNegative ? -Infinity : Infinity; +// } + +// return this.#continueDecodeDoubleInteger(isNegative, integer, chunk); +// } + +// #continueDecodeDoubleInteger( +// isNegative: boolean, +// integer: number, +// chunk: Buffer +// ): ValueOrNext { +// let cursor = this.#cursor; +// do { +// const byte = chunk[cursor]; +// switch (byte) { +// case ASCII['.']: +// this.#cursor = ++cursor; +// return cursor < chunk.length ? +// this.#decodeDoubleDecimal(isNegative, 0, integer, chunk) : +// this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer); + +// case ASCII['\r']: +// this.#cursor = cursor + 2; // skip \r\n +// return isNegative ? -integer : integer; + +// default: +// integer = integer * 10 + byte - ASCII['0']; +// } +// } while (++cursor < chunk.length); + +// this.#cursor = cursor; +// return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer); +// } + +// // Precalculated multipliers for decimal points to improve performance +// // "A Number only keeps about 17 decimal places of precision" +// // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number +// static #DOUBLE_DECIMAL_MULTIPLIERS = [ +// 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, +// 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, +// 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 +// ]; + +// #decodeDoubleDecimal( +// isNegative: boolean, +// decimalIndex: number, +// double: number, +// chunk: Buffer +// ): ValueOrNext { +// let cursor = this.#cursor; +// do { +// const byte = chunk[cursor]; +// if (byte === ASCII['\r']) { +// this.#cursor = cursor + 2; // skip \r\n +// return isNegative ? -double : double; +// } + +// if (decimalIndex < Decoder.#DOUBLE_DECIMAL_MULTIPLIERS.length) { +// double += (byte - ASCII['0']) * Decoder.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; +// } +// } while (++cursor < chunk.length); + +// this.#cursor = cursor; +// return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); +// } + +// #findCRLF(chunk: Buffer, cursor: number) { +// while (chunk[cursor] !== ASCII['\r']) { +// if (++cursor === chunk.length) { +// this.#cursor = chunk.length; +// return -1; +// } +// } + +// this.#cursor = cursor + 2; // skip \r\n +// return cursor; +// } + +// #decodeSimpleString( +// flag: F, +// chunk: Buffer +// ): ValueOrNext ? T : never> { +// const start = this.#cursor, +// crlfIndex = this.#findCRLF(chunk, start); +// if (crlfIndex === -1) { +// return this.#continueDecodeSimpleString.bind( +// this, +// [chunk.subarray(start)], +// flag +// ); +// } + +// const slice = chunk.subarray(start, crlfIndex); +// return (flag === Buffer ? +// slice : +// slice.toString()) as (F extends Flag ? T : never); +// } + +// #continueDecodeSimpleString( +// chunks: Array, +// flag: F, +// chunk: Buffer +// ): ValueOrNext ? T : never> { +// const start = this.#cursor, +// crlfIndex = this.#findCRLF(chunk, start); +// if (crlfIndex === -1) { +// chunks.push(chunk.subarray(start)); +// return this.#continueDecodeSimpleString.bind(this, chunks, flag) as Next ? T : never>; +// } + +// chunks.push(chunk.subarray(start, crlfIndex)); +// return (flag === Buffer ? +// Buffer.concat(chunks) : +// chunks.join('')) as ValueOrNext ? T : never>; +// } + +// #decodeBlobString(flag: Flags[RespTypes['BLOB_STRING']], chunk: Buffer) { +// // RESP 2 bulk string null +// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings +// if (chunk[this.#cursor] === ASCII['-']) { +// this.#cursor += 4; // skip -1\r\n +// return null; +// } + +// const length = this.#decodeUnsingedNumber(0, chunk); +// if (typeof length === 'function') { +// return this.#continueDecodeBlobStringLength.bind(this, length, flag); +// } else if (this.#cursor >= chunk.length) { +// return this.#decodeBlobStringWithLength.bind(this, length, flag); +// } + +// return this.#decodeBlobStringWithLength(length, flag, chunk); +// } + +// #continueDecodeBlobStringLength( +// lengthCb: Next, +// flag: Flags[RespTypes['BLOB_STRING']], +// chunk: Buffer +// ): ValueOrNext { +// const length = lengthCb(chunk); +// if (typeof length === 'function') { +// return this.#continueDecodeBlobStringLength.bind(this, length, flag); +// } else if (this.#cursor >= chunk.length) { +// return this.#decodeBlobStringWithLength.bind(this, length, flag); +// } + +// return this.#decodeBlobStringWithLength(length, flag, chunk); +// } + +// #decodeBlobStringWithLength( +// length: number, +// flag: Flags[RespTypes['BLOB_STRING']], +// chunk: Buffer +// ) { +// const end = this.#cursor + length; +// if (end >= chunk.length) { +// const slice = chunk.subarray(this.#cursor); +// this.#cursor = chunk.length; +// return this.#continueDecodeBlobStringWithLength.bind( +// this, +// length - slice.length, +// [slice], +// flag +// ); +// } + +// const slice = chunk.subarray(this.#cursor, end); +// this.#cursor = end + 2; // skip ${string}\r\n +// return flag === Buffer ? +// slice : +// slice.toString(); +// } + +// #continueDecodeBlobStringWithLength( +// length: number, +// chunks: Array, +// flag: Flags[RespTypes['BLOB_STRING']], +// chunk: Buffer +// ): ValueOrNext { +// const end = this.#cursor + length; +// if (end >= chunk.length) { +// const slice = chunk.subarray(this.#cursor); +// chunks.push(slice); +// this.#cursor = chunk.length; +// return this.#continueDecodeBlobStringWithLength.bind( +// this, +// length - slice.length, +// chunks, +// flag +// ); +// } + +// chunks.push(chunk.subarray(this.#cursor, end)); +// this.#cursor = end + 2; // skip ${string}\r\n +// return flag === Buffer ? +// Buffer.concat(chunks) : +// chunks.join(''); +// } + +// #decodeSimpleError(chunk: Buffer) { +// const string = this.#decodeSimpleString(String, chunk); +// return typeof string === 'function' ? +// this.#continueDecodeSimpleError.bind(this, string) : +// new Error(string); // TODO use custom error +// } + +// #continueDecodeSimpleError(stringCb, chunk) { +// const string = stringCb(chunk); +// return typeof string === 'function' ? +// this.#continueDecodeSimpleError.bind(this, string) : +// new Error(string); // TODO use custom error +// } + +// #decodeBlobError(chunk) { +// const string = this.#decodeBlobString(String, chunk); +// return typeof string === 'function' ? +// this.#continueDecodeBlobError.bind(this, string) : +// new Error(string); // TODO use custom error +// } + +// #continueDecodeBlobError(stringCb, chunk) { +// const string = stringCb(chunk); +// return typeof string === 'function' ? +// this.#continueDecodeBlobError.bind(this, string) : +// new Error(string); // TODO use custom error +// } + +// #decodeNestedType(flags, chunk) { +// const type = chunk[this.#cursor]; +// return ++this.#cursor === chunk.length ? +// this.#decodeReplyValue.bind(this, type, flags) : +// this.#decodeReplyValue(type, flags, chunk); +// } + +// #decodeArray(flags, chunk) { +// // RESP 2 null +// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays +// if (chunk[this.#cursor] === ASCII['-']) { +// this.#cursor += 4; // skip -1\r\n +// return null; +// } + +// return this.#decodeArrayWithLength( +// this.#decodeUnsingedNumber(0, chunk), +// flags, +// chunk +// ); +// } + +// #decodeArrayWithLength(length, flags, chunk) { +// return typeof length === 'function' ? +// this.#continueDecodeArrayLength.bind(this, length, flags) : +// this.#decodeArrayItems( +// new Array(length), +// 0, +// flags, +// chunk +// ); +// } + +// #continueDecodeArrayLength(lengthCb, flags, chunk) { +// return this.#decodeArrayWithLength( +// lengthCb(chunk), +// flags, +// chunk +// ); +// } + +// #decodeArrayItems(array, filled, flags, chunk) { +// for (let i = filled; i < array.length; i++) { +// if (this.#cursor >= chunk.length) { +// return this.#decodeArrayItems.bind( +// this, +// array, +// i, +// flags +// ); +// } + +// const item = this.#decodeNestedType(flags, chunk); +// if (typeof item === 'function') { +// return this.#continueDecodeArrayItems.bind( +// this, +// array, +// i, +// item, +// flags +// ); +// } + +// array[i] = item; +// } + +// return array; +// } + +// #continueDecodeArrayItems(array, filled, itemCb, flags, chunk) { +// const item = itemCb(chunk); +// if (typeof item === 'function') { +// return this.#continueDecodeArrayItems.bind( +// this, +// array, +// filled, +// item, +// flags +// ); +// } + +// array[filled++] = item; + +// return this.#decodeArrayItems(array, filled, flags, chunk); +// } + +// #decodeSet(flags, chunk) { +// const length = this.#decodeUnsingedNumber(0, chunk); +// if (typeof length === 'function') { +// return this.#continueDecodeSetLength.bind(this, length, flags); +// } + +// return this.#decodeSetItems( +// length, +// flags, +// chunk +// ); +// } + +// #continueDecodeSetLength(lengthCb, flags, chunk) { +// const length = lengthCb(chunk); +// return typeof length === 'function' ? +// this.#continueDecodeSetLength.bind(this, length, flags) : +// this.#decodeSetItems(length, flags, chunk); +// } + +// #decodeSetItems(length, flags, chunk) { +// return flags[TYPES.SET] === Set ? +// this.#decodeSetAsSet( +// new Set(), +// length, +// flags, +// chunk +// ) : +// this.#decodeArrayItems( +// new Array(length), +// 0, +// flags, +// chunk +// ); +// } + +// #decodeSetAsSet(set, remaining, flags, chunk) { +// // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates +// while (remaining > 0) { +// if (this.#cursor >= chunk.length) { +// return this.#decodeSetAsSet.bind( +// this, +// set, +// remaining, +// flags +// ); +// } + +// const item = this.#decodeNestedType(flags, chunk); +// if (typeof item === 'function') { +// return this.#continueDecodeSetAsSet.bind( +// this, +// set, +// remaining, +// item, +// flags +// ); +// } + +// set.add(item); +// --remaining; +// } + +// return set; +// } + +// #continueDecodeSetAsSet(set, remaining, itemCb, flags, chunk) { +// const item = itemCb(chunk); +// if (typeof item === 'function') { +// return this.#continueDecodeSetAsSet.bind( +// this, +// set, +// remaining, +// item, +// flags +// ); +// } + +// set.add(item); + +// return this.#decodeSetAsSet(set, remaining - 1, flags, chunk); +// } + +// #decodeMap(flags, chunk) { +// const length = this.#decodeUnsingedNumber(0, chunk); +// if (typeof length === 'function') { +// return this.#continueDecodeMapLength.bind(this, length, flags); +// } + +// return this.#decodeMapItems( +// length, +// flags, +// chunk +// ); +// } + +// #continueDecodeMapLength(lengthCb, flags, chunk) { +// const length = lengthCb(chunk); +// return typeof length === 'function' ? +// this.#continueDecodeMapLength.bind(this, length, flags) : +// this.#decodeMapItems(length, flags, chunk); +// } + +// #decodeMapItems(length, flags, chunk) { +// switch (flags[TYPES.MAP]) { +// case Map: +// return this.#decodeMapAsMap( +// new Map(), +// length, +// flags, +// chunk +// ); + +// case Array: +// return this.#decodeArrayItems( +// new Array(length * 2), +// 0, +// flags, +// chunk +// ); + +// default: +// return this.#decodeMapAsObject( +// Object.create(null), +// length, +// flags, +// chunk +// ); +// } +// } + +// #decodeMapAsMap(map, remaining, flags, chunk) { +// // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys +// while (remaining > 0) { +// if (this.#cursor >= chunk.length) { +// return this.#decodeMapAsMap.bind( +// this, +// map, +// remaining, +// flags +// ); +// } + +// const key = this.#decodeMapKey(flags, chunk); +// if (typeof key === 'function') { +// return this.#continueDecodeMapKey.bind( +// this, +// map, +// remaining, +// key, +// flags +// ); +// } + +// if (this.#cursor >= chunk.length) { +// return this.#continueDecodeMapValue.bind( +// this, +// map, +// remaining, +// key, +// this.#decodeNestedType.bind(this, flags), +// flags +// ); +// } + +// const value = this.#decodeNestedType(flags, chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapValue.bind( +// this, +// map, +// remaining, +// key, +// value, +// flags +// ); +// } + +// map.set(key, value); +// --remaining; +// } + +// return map; +// } + +// #decodeMapKey(flags, chunk) { +// const type = chunk[this.#cursor]; +// return ++this.#cursor === chunk.length ? +// this.#decodeMapKeyValue.bind(this, type, flags) : +// this.#decodeMapKeyValue(type, flags, chunk); +// } + +// #decodeMapKeyValue(type, flags, chunk) { +// switch (type) { +// // decode simple string map key as string (and not as buffer) +// case TYPES.SIMPLE_STRING: +// return this.#decodeSimpleString(String, chunk); + +// // decode blob string map key as string (and not as buffer) +// case TYPES.BLOB_STRING: +// return this.#decodeBlobString(String, chunk); + +// default: +// return this.#decodeReplyValue(type, flags, chunk); +// } +// } + +// #continueDecodeMapKey(map, remaining, keyCb, flags, chunk) { +// const key = keyCb(chunk); +// if (typeof key === 'function') { +// return this.#continueDecodeMapKey.bind( +// this, +// map, +// remaining, +// key, +// flags +// ); +// } + +// if (this.#cursor >= chunk.length) { +// return this.#continueDecodeMapValue.bind( +// this, +// map, +// remaining, +// key, +// this.#decodeNestedType.bind(this, flags), +// flags +// ); +// } + +// const value = this.#decodeNestedType(flags, chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapValue.bind( +// this, +// map, +// remaining, +// key, +// value, +// flags +// ); +// } + +// map.set(key, value); +// return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); +// } + +// #continueDecodeMapValue(map, remaining, key, valueCb, flags, chunk) { +// const value = valueCb(chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapValue.bind( +// this, +// map, +// remaining, +// key, +// value, +// flags +// ); +// } + +// map.set(key, value); + +// return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); +// } + +// #decodeMapAsObject(object, remaining, flags, chunk) { +// while (remaining > 0) { +// if (this.#cursor >= chunk.length) { +// return this.#decodeMapAsObject.bind( +// this, +// object, +// remaining, +// flags +// ); +// } + +// const key = this.#decodeMapKey(flags, chunk); +// if (typeof key === 'function') { +// return this.#continueDecodeMapAsObjectKey.bind( +// this, +// object, +// remaining, +// key, +// flags +// ); +// } + +// if (this.#cursor >= chunk.length) { +// return this.#continueDecodeMapAsObjectValue.bind( +// this, +// object, +// remaining, +// key, +// this.#decodeNestedType.bind(this, flags), +// flags +// ); +// } + +// const value = this.#decodeNestedType(flags, chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapAsObjectValue.bind( +// this, +// object, +// remaining, +// key, +// value, +// flags +// ); +// } + +// object[key] = value; +// --remaining; +// } + +// return object; +// } + +// #continueDecodeMapAsObjectKey(object, remaining, keyCb, flags, chunk) { +// const key = keyCb(chunk); +// if (typeof key === 'function') { +// return this.#continueDecodeMapAsObjectKey.bind( +// this, +// object, +// remaining, +// key, +// flags +// ); +// } + +// if (this.#cursor >= chunk.length) { +// return this.#continueDecodeMapAsObjectValue.bind( +// this, +// object, +// remaining, +// key, +// this.#decodeNestedType.bind(this, flags), +// flags +// ); +// } + +// const value = this.#decodeNestedType(flags, chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapAsObjectValue.bind( +// this, +// object, +// remaining, +// key, +// value, +// flags +// ); +// } + +// object[key] = value; + +// return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); +// } + +// #continueDecodeMapAsObjectValue(object, remaining, key, valueCb, flags, chunk) { +// const value = valueCb(chunk); +// if (typeof value === 'function') { +// return this.#continueDecodeMapAsObjectValue.bind( +// this, +// object, +// remaining, +// key, +// value, +// flags +// ); +// } + +// object[key] = value; + +// return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); +// } +// } + +// const a = new Decoder({ +// onReply(reply) { +// console.log('[REPLY]', reply); +// }, +// onErrorReply(err) { +// console.log('[ERROR REPLY]', err); +// }, +// onPush(push) { +// console.log('[PUSH]', push); +// }, +// getFlags() { +// return {}; +// } +// }); + +// a.write(Buffer.from('+PONG\r\n')); diff --git a/packages/client/lib/client/RESP2/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts similarity index 100% rename from packages/client/lib/client/RESP2/decoder.spec.ts rename to packages/client/lib/RESP/decoder.spec.ts diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts new file mode 100644 index 00000000000..950387966ee --- /dev/null +++ b/packages/client/lib/RESP/decoder.ts @@ -0,0 +1,1159 @@ +// @ts-nocheck +import { VerbatimString } from './verbatim-string'; +import { SimpleError, BlobError, ErrorReply } from '../errors'; +import { Flags } from './types'; + +// https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md +export const TYPES = { + NULL: 95, // _ + BOOLEAN: 35, // # + NUMBER: 58, // : + BIG_NUMBER: 40, // ( + DOUBLE: 44, // , + SIMPLE_STRING: 43, // + + BLOB_STRING: 36, // $ + VERBATIM_STRING: 61, // = + SIMPLE_ERROR: 45, // - + BLOB_ERROR: 33, // ! + ARRAY: 42, // * + SET: 126, // ~ + MAP: 37, // % + PUSH: 62 // > +} as const; + +const ASCII = { + '\r': 13, + 't': 116, + '+': 43, + '-': 45, + '0': 48, + '.': 46, + 'i': 105, + 'n': 110, + 'E': 69, + 'e': 101 +} as const; + +export const PUSH_FLAGS = { + [TYPES.BLOB_STRING]: Buffer +}; + +// this was written with performance in mind, so it's not very readable... sorry :( +// using `private _` instead of `#` to boost performance + +interface DecoderOptions { + onReply(reply: any): unknown; + onErrorReply(err: ErrorReply): unknown; + onPush(push: Array): unknown; + getFlags(): Flags; +} + +export class Decoder { + private _config; + + private _cursor = 0; + + private _next; + + constructor(config: DecoderOptions) { + this._config = config; + } + + reset() { + this._cursor = 0; + this._next = undefined; + } + + write(chunk) { + if (this._cursor >= chunk.length) { + this._cursor -= chunk.length; + return; + } + + if (this._next) { + if (this._next(chunk) || this._cursor >= chunk.length) { + this._cursor -= chunk.length; + return; + } + } + + do { + const type = chunk[this._cursor]; + if (++this._cursor === chunk.length) { + this._next = this._continueDecodeTypeValue.bind(this, type); + break; + } + + if (this._decodeTypeValue(type, chunk)) { + break; + } + } while (this._cursor < chunk.length); + this._cursor -= chunk.length; + } + + private _continueDecodeTypeValue(type, chunk) { + this._next = undefined; + return this._decodeTypeValue(type, chunk); + } + + private _decodeTypeValue(type, chunk) { + switch (type) { + case TYPES.NULL: + this._config.onReply(this._decodeNull()); + return false; + + case TYPES.BOOLEAN: + return this._handleDecodedValue( + this._config.onReply, + this._decodeBoolean(chunk) + ); + + case TYPES.NUMBER: + return this._handleDecodedValue( + this._config.onReply, + this._decodeNumber(chunk) + ); + + case TYPES.BIG_NUMBER: + return this._handleDecodedValue( + this._config.onReply, + this._decodeBigNumber( + this._config.getFlags()[TYPES.BIG_NUMBER], + chunk + ) + ); + + case TYPES.DOUBLE: + return this._handleDecodedValue( + this._config.onReply, + this._decodeDouble( + this._config.getFlags()[TYPES.DOUBLE], + chunk + ) + ); + + case TYPES.SIMPLE_STRING: + return this._handleDecodedValue( + this._config.onReply, + this._decodeSimpleString( + this._config.getFlags()[TYPES.SIMPLE_STRING], + chunk + ) + ); + + case TYPES.BLOB_STRING: + return this._handleDecodedValue( + this._config.onReply, + this._decodeBlobString( + this._config.getFlags()[TYPES.BLOB_STRING], + chunk + ) + ); + + case TYPES.VERBATIM_STRING: + return this._handleDecodedValue( + this._config.onReply, + this._decodeVerbatimString( + this._config.getFlags()[TYPES.VERBATIM_STRING], + chunk + ) + ); + + case TYPES.SIMPLE_ERROR: + return this._handleDecodedValue( + this._config.onErrorReply, + this._decodeSimpleError(chunk) + ); + + case TYPES.BLOB_ERROR: + return this._handleDecodedValue( + this._config.onErrorReply, + this._decodeBlobError(chunk) + ); + + case TYPES.ARRAY: + return this._handleDecodedValue( + this._config.onReply, + this._decodeArray(this._config.getFlags(), chunk) + ); + + case TYPES.SET: + return this._handleDecodedValue( + this._config.onReply, + this._decodeSet(this._config.getFlags(), chunk) + ); + + case TYPES.MAP: + return this._handleDecodedValue( + this._config.onReply, + this._decodeMap(this._config.getFlags(), chunk) + ); + + case TYPES.PUSH: + return this._handleDecodedValue( + this._config.onPush, + this._decodeArray(PUSH_FLAGS, chunk) + ); + } + } + + private _handleDecodedValue(cb, value) { + if (typeof value === 'function') { + this._next = this._continueDecodeValue.bind(this, cb, value); + return true; + } + + cb(value); + return false; + } + + private _continueDecodeValue(cb, next, chunk) { + this._next = undefined; + return this._handleDecodedValue(cb, next(chunk)); + } + + private _decodeNull() { + this._cursor += 2; // skip \r\n + return null; + } + + private _decodeBoolean(chunk) { + const boolean = chunk[this._cursor] === ASCII.t; + this._cursor += 3; // skip {t | f}\r\n + return boolean; + } + + private _decodeNumber(chunk) { + switch (chunk[this._cursor]) { + case ASCII['+']: + return this._maybeDecodeNumberValue(false, chunk); + + case ASCII['-']: + return this._maybeDecodeNumberValue(true, chunk); + + default: + return this._decodeNumberValue( + false, + this._decodeUnsingedNumber.bind(this, 0), + chunk + ); + } + } + + private _maybeDecodeNumberValue(isNegative, chunk) { + const cb = this._decodeUnsingedNumber.bind(this, 0); + return this._cursor === chunk.length ? + this._decodeNumberValue.bind(isNegative, cb) : + this._decodeNumberValue(isNegative, cb, chunk); + } + + private _decodeNumberValue(isNegative, numberCb, chunk) { + const number = numberCb(chunk); + return typeof number === 'function' ? + this._decodeNumberValue.bind(this, isNegative, number) : + isNegative ? -number : number; + } + + private _decodeUnsingedNumber(number, chunk) { + let cursor = this._cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this._cursor = cursor + 2; // skip \r\n + return number; + } + number = number * 10 + byte - ASCII['0']; + } while (++cursor < chunk.length); + + this._cursor = cursor; + return this._decodeUnsingedNumber.bind(this, number); + } + + private _decodeBigNumber(flag, chunk) { + if (flag === String) { + return this._decodeSimpleString(String, chunk); + } + + switch (chunk[this._cursor]) { + case ASCII['+']: + return this._maybeDecodeBigNumberValue(false, chunk); + + case ASCII['-']: + return this._maybeDecodeBigNumberValue(true, chunk); + + default: + return this._decodeBigNumberValue( + false, + this._decodeUnsingedBigNumber.bind(this, 0n), + chunk + ); + } + } + + private _maybeDecodeBigNumberValue(isNegative, chunk) { + const cb = this._decodeUnsingedBigNumber.bind(this, 0n); + return this._cursor === chunk.length ? + this._decodeBigNumberValue.bind(isNegative, cb) : + this._decodeBigNumberValue(isNegative, cb, chunk); + } + + private _decodeBigNumberValue(isNegative, bigNumberCb, chunk) { + const bigNumber = bigNumberCb(chunk); + return typeof bigNumber === 'function' ? + this._decodeBigNumberValue.bind(this, isNegative, bigNumber) : + isNegative ? -bigNumber : bigNumber; + } + + private _decodeUnsingedBigNumber(bigNumber, chunk) { + let cursor = this._cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this._cursor = cursor + 2; // skip \r\n + return bigNumber; + } + bigNumber = bigNumber * 10n + BigInt(byte - ASCII['0']); + } while (++cursor < chunk.length); + + this._cursor = cursor; + return this._decodeUnsingedBigNumber.bind(this, bigNumber); + } + + private _decodeDouble(flag, chunk) { + if (flag === String) { + return this._decodeSimpleString(String, chunk); + } + + switch (chunk[this._cursor]) { + case ASCII.n: + this._cursor += 5; // skip nan\r\n + return NaN; + + case ASCII['+']: + return this._maybeDecodeDoubleInteger(false, chunk); + + case ASCII['-']: + return this._maybeDecodeDoubleInteger(true, chunk); + + default: + return this._decodeDoubleInteger(false, 0, chunk); + } + } + + private _maybeDecodeDoubleInteger(isNegative, chunk) { + return ++this._cursor === chunk.length ? + this._decodeDoubleInteger.bind(this, isNegative, 0) : + this._decodeDoubleInteger(true, 0, chunk); + } + + private _decodeDoubleInteger(isNegative, integer, chunk) { + if (chunk[this._cursor] === ASCII.i) { + this._cursor += 5; // skip inf\r\n + return isNegative ? -Infinity : Infinity; + } + + return this._continueDecodeDoubleInteger(isNegative, integer, chunk); + } + + private _continueDecodeDoubleInteger(isNegative, integer, chunk) { + let cursor = this._cursor; + do { + const byte = chunk[cursor]; + switch (byte) { + case ASCII['.']: + this._cursor = cursor + 1; // skip . + return cursor < chunk.length ? + this._decodeDoubleDecimal(isNegative, 0, integer, chunk) : + this._decodeDoubleDecimal.bind(this, isNegative, 0, integer); + + case ASCII.E: + case ASCII.e: + this._cursor = cursor + 1; // skip e + return this._decodeDoubleExponent(isNegative ? -integer : integer, chunk); + + case ASCII['\r']: + this._cursor = cursor + 2; // skip \r\n + return isNegative ? -integer : integer; + + default: + integer = integer * 10 + byte - ASCII['0']; + } + } while (++cursor < chunk.length); + + this._cursor = cursor; + return this._continueDecodeDoubleInteger.bind(this, isNegative, integer); + } + + // Precalculated multipliers for decimal points to improve performance + // "A Number only keeps about 17 decimal places of precision" + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + static _DOUBLE_DECIMAL_MULTIPLIERS = [ + 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, + 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, + 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 + ]; + + private _decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { + let cursor = this._cursor; + do { + const byte = chunk[cursor]; + switch (byte) { + case ASCII.E: + case ASCII.e: + this._cursor = cursor + 1; // skip e + const d = isNegative ? -double : double; + return this._cursor === chunk.length ? + this._decodeDoubleExponent.bind(this, d, false, 0) : + this._decodeDoubleExponent(d, false, 0, chunk); + + case ASCII['\r']: + this._cursor = cursor + 2; // skip \r\n + return isNegative ? -double : double; + } + + if (decimalIndex < Decoder._DOUBLE_DECIMAL_MULTIPLIERS.length) { + double += (byte - ASCII['0']) * Decoder._DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; + } + } while (++cursor < chunk.length); + + this._cursor = cursor; + return this._decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); + } + + private _decodeDoubleExponent(double, chunk) { + switch (chunk[this._cursor]) { + case ASCII['+']: + return ++this._cursor === chunk.length ? + this._continueDecodeDoubleExponent.bind(this, false, double, 0) : + this._continueDecodeDoubleExponent(false, double, 0, chunk); + + case ASCII['-']: + return ++this._cursor === chunk.length ? + this._continueDecodeDoubleExponent.bind(this, true, double, 0) : + this._continueDecodeDoubleExponent(true, double, 0, chunk); + } + + return this._continueDecodeDoubleExponent(false, double, 0, chunk); + } + + private _continueDecodeDoubleExponent(isNegative, double, exponent, chunk) { + let cursor = this._cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this._cursor = cursor + 2; // skip \r\n + return double * 10 ** (isNegative ? -exponent : exponent); + } + + exponent = exponent * 10 + byte - ASCII['0']; + } while (++cursor < chunk.length); + + this._cursor = cursor; + return this._continueDecodeDoubleExponent.bind(this, isNegative, double, exponent); + } + + private _findCRLF(chunk, cursor) { + while (chunk[cursor] !== ASCII['\r']) { + if (++cursor === chunk.length) { + this._cursor = chunk.length; + return -1; + } + } + + this._cursor = cursor + 2; // skip \r\n + return cursor; + } + + private _decodeSimpleString(flag, chunk) { + const start = this._cursor, + crlfIndex = this._findCRLF(chunk, start); + if (crlfIndex === -1) { + return this._continueDecodeSimpleString.bind( + this, + [chunk.subarray(start)], + flag + ); + } + + const slice = chunk.subarray(start, crlfIndex); + return flag === Buffer ? + slice : + slice.toString(); + } + + private _continueDecodeSimpleString(chunks, flag, chunk) { + const start = this._cursor, + crlfIndex = this._findCRLF(chunk, start); + if (crlfIndex === -1) { + chunks.push(chunk.subarray(start)); + return this._continueDecodeSimpleString.bind(this, chunks, flag); + } + + chunks.push(chunk.subarray(start, crlfIndex)); + return flag === Buffer ? + Buffer.concat(chunks) : + chunks.join(''); + } + + private _decodeBlobString(flag, chunk) { + // RESP 2 bulk string null + // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings + if (chunk[this._cursor] === ASCII['-']) { + this._cursor += 4; // skip -1\r\n + return null; + } + + const length = this._decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this._continueDecodeBlobStringLength.bind(this, length, flag); + } else if (this._cursor >= chunk.length) { + return this._decodeBlobStringWithLength.bind(this, length, flag); + } + + return this._decodeBlobStringWithLength(length, flag, chunk); + } + + private _continueDecodeBlobStringLength(lengthCb, flag, chunk) { + const length = lengthCb(chunk); + if (typeof length === 'function') { + return this._continueDecodeBlobStringLength.bind(this, length, flag); + } else if (this._cursor >= chunk.length) { + return this._decodeBlobStringWithLength.bind(this, length, flag); + } + + return this._decodeBlobStringWithLength(length, flag, chunk); + } + + private _decodeStringWithLength(length, skip, flag, chunk) { + const end = this._cursor + length; + if (end >= chunk.length) { + const slice = chunk.subarray(this._cursor); + this._cursor = chunk.length; + return this._continueDecodeStringWithLength.bind( + this, + length - slice.length, + [slice], + skip, + flag + ); + } + + const slice = chunk.subarray(this._cursor, end); + this._cursor = end + skip; + return flag === Buffer ? + slice : + slice.toString(); + } + + private _continueDecodeStringWithLength(length, chunks, skip, flag, chunk) { + const end = this._cursor + length; + if (end >= chunk.length) { + const slice = chunk.subarray(this._cursor); + chunks.push(slice); + this._cursor = chunk.length; + return this._continueDecodeStringWithLength.bind( + this, + length - slice.length, + chunks, + flag + ); + } + + chunks.push(chunk.subarray(this._cursor, end)); + this._cursor = end + skip; + return flag === Buffer ? + Buffer.concat(chunks) : + chunks.join(''); + } + + private _decodeBlobStringWithLength(length, flag, chunk) { + return this._decodeStringWithLength(length, 2, flag, chunk); + } + + private _decodeVerbatimString(flag, chunk) { + return this._continueDecodeVerbatimStringLength( + this._decodeUnsingedNumber.bind(this, 0), + flag, + chunk + ); + } + + private _continueDecodeVerbatimStringLength(lengthCb, flag, chunk) { + const length = lengthCb(chunk); + return typeof length === 'function'? + this._continueDecodeVerbatimStringLength.bind(this, length, flag) : + this._decodeVerbatimStringWithLength(length, flag, chunk); + } + + private _decodeVerbatimStringWithLength(length, flag, chunk) { + const stringLength = length - 4; // skip : + if (flag === VerbatimString) { + return this._decodeVerbatimStringFormat(stringLength, chunk); + } + + this._cursor += 4; // skip : + return this._cursor >= chunk.length ? + this._decodeBlobStringWithLength.bind(this, stringLength, flag) : + this._decodeBlobStringWithLength(stringLength, flag, chunk); + } + + private _decodeVerbatimStringFormat(stringLength, chunk) { + return this._continueDecodeVerbatimStringFormat( + stringLength, + this._decodeStringWithLength.bind(this, 3, 1, String), + chunk + ); + } + + private _continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { + const format = formatCb(chunk); + return typeof format === 'function' ? + this._continueDecodeVerbatimStringFormat.bind(this, stringLength, format) : + this._decodeVerbatimStringWithFormat(stringLength, format, chunk); + } + + private _decodeVerbatimStringWithFormat(stringLength, format, chunk) { + return this._continueDecodeVerbatimStringWithFormat( + format, + this._decodeBlobStringWithLength.bind(this, stringLength, String), + chunk + ); + } + + private _continueDecodeVerbatimStringWithFormat(format, stringCb, chunk) { + const string = stringCb(chunk); + return typeof string === 'function' ? + this._continueDecodeVerbatimStringWithFormat.bind(this, format, string) : + new VerbatimString(format, string); + } + + private _decodeSimpleError(chunk) { + const string = this._decodeSimpleString(String, chunk); + return typeof string === 'function' ? + this._continueDecodeSimpleError.bind(this, string) : + new SimpleError(string); + } + + private _continueDecodeSimpleError(stringCb, chunk) { + const string = stringCb(chunk); + return typeof string === 'function' ? + this._continueDecodeSimpleError.bind(this, string) : + new SimpleError(string); + } + + private _decodeBlobError(chunk) { + const string = this._decodeBlobString(String, chunk); + return typeof string === 'function' ? + this._continueDecodeBlobError.bind(this, string) : + new BlobError(string); + } + + private _continueDecodeBlobError(stringCb, chunk) { + const string = stringCb(chunk); + return typeof string === 'function' ? + this._continueDecodeBlobError.bind(this, string) : + new BlobError(string); + } + + private _decodeNestedType(flags, chunk) { + const type = chunk[this._cursor]; + return ++this._cursor === chunk.length ? + this._decodeNestedTypeValue.bind(this, type, flags) : + this._decodeNestedTypeValue(type, flags, chunk); + } + + private _decodeNestedTypeValue(type, flags, chunk) { + switch (type) { + case TYPES.NULL: + return this._decodeNull(); + + case TYPES.BOOLEAN: + return this._decodeBoolean(chunk); + + case TYPES.NUMBER: + return this._decodeNumber(chunk); + + case TYPES.BIG_NUMBER: + return this._decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk); + + case TYPES.DOUBLE: + return this._decodeDouble(flags[TYPES.DOUBLE], chunk); + + case TYPES.SIMPLE_STRING: + return this._decodeSimpleString(flags[TYPES.SIMPLE_STRING], chunk); + + case TYPES.BLOB_STRING: + return this._decodeBlobString(flags[TYPES.BLOB_STRING], chunk); + + case TYPES.VERBATIM_STRING: + return this._decodeVerbatimString(flags[TYPES.VERBATIM_STRING], chunk); + + case TYPES.SIMPLE_ERROR: + return this._decodeSimpleError(chunk); + + case TYPES.BLOB_ERROR: + return this._decodeBlobError(chunk); + + case TYPES.ARRAY: + return this._decodeArray(flags, chunk); + + case TYPES.SET: + return this._decodeSet(flags, chunk); + + case TYPES.MAP: + return this._decodeMap(flags, chunk); + } + } + + private _decodeArray(flags, chunk) { + // RESP 2 null + // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays + if (chunk[this._cursor] === ASCII['-']) { + this._cursor += 4; // skip -1\r\n + return null; + } + + return this._decodeArrayWithLength( + this._decodeUnsingedNumber(0, chunk), + flags, + chunk + ); + } + + private _decodeArrayWithLength(length, flags, chunk) { + return typeof length === 'function' ? + this._continueDecodeArrayLength.bind(this, length, flags) : + this._decodeArrayItems( + new Array(length), + 0, + flags, + chunk + ); + } + + private _continueDecodeArrayLength(lengthCb, flags, chunk) { + return this._decodeArrayWithLength( + lengthCb(chunk), + flags, + chunk + ); + } + + private _decodeArrayItems(array, filled, flags, chunk) { + for (let i = filled; i < array.length; i++) { + if (this._cursor >= chunk.length) { + return this._decodeArrayItems.bind( + this, + array, + i, + flags + ); + } + + const item = this._decodeNestedType(flags, chunk); + if (typeof item === 'function') { + return this._continueDecodeArrayItems.bind( + this, + array, + i, + item, + flags + ); + } + + array[i] = item; + } + + return array; + } + + private _continueDecodeArrayItems(array, filled, itemCb, flags, chunk) { + const item = itemCb(chunk); + if (typeof item === 'function') { + return this._continueDecodeArrayItems.bind( + this, + array, + filled, + item, + flags + ); + } + + array[filled++] = item; + + return this._decodeArrayItems(array, filled, flags, chunk); + } + + private _decodeSet(flags, chunk) { + const length = this._decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this._continueDecodeSetLength.bind(this, length, flags); + } + + return this._decodeSetItems( + length, + flags, + chunk + ); + } + + private _continueDecodeSetLength(lengthCb, flags, chunk) { + const length = lengthCb(chunk); + return typeof length === 'function' ? + this._continueDecodeSetLength.bind(this, length, flags) : + this._decodeSetItems(length, flags, chunk); + } + + private _decodeSetItems(length, flags, chunk) { + return flags[TYPES.SET] === Set ? + this._decodeSetAsSet( + new Set(), + length, + flags, + chunk + ) : + this._decodeArrayItems( + new Array(length), + 0, + flags, + chunk + ); + } + + private _decodeSetAsSet(set, remaining, flags, chunk) { + // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates + while (remaining > 0) { + if (this._cursor >= chunk.length) { + return this._decodeSetAsSet.bind( + this, + set, + remaining, + flags + ); + } + + const item = this._decodeNestedType(flags, chunk); + if (typeof item === 'function') { + return this._continueDecodeSetAsSet.bind( + this, + set, + remaining, + item, + flags + ); + } + + set.add(item); + --remaining; + } + + return set; + } + + private _continueDecodeSetAsSet(set, remaining, itemCb, flags, chunk) { + const item = itemCb(chunk); + if (typeof item === 'function') { + return this._continueDecodeSetAsSet.bind( + this, + set, + remaining, + item, + flags + ); + } + + set.add(item); + + return this._decodeSetAsSet(set, remaining - 1, flags, chunk); + } + + private _decodeMap(flags, chunk) { + const length = this._decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this._continueDecodeMapLength.bind(this, length, flags); + } + + return this._decodeMapItems( + length, + flags, + chunk + ); + } + + private _continueDecodeMapLength(lengthCb, flags, chunk) { + const length = lengthCb(chunk); + return typeof length === 'function' ? + this._continueDecodeMapLength.bind(this, length, flags) : + this._decodeMapItems(length, flags, chunk); + } + + private _decodeMapItems(length, flags, chunk) { + switch (flags[TYPES.MAP]) { + case Map: + return this._decodeMapAsMap( + new Map(), + length, + flags, + chunk + ); + + case Array: + return this._decodeArrayItems( + new Array(length * 2), + 0, + flags, + chunk + ); + + default: + return this._decodeMapAsObject( + Object.create(null), + length, + flags, + chunk + ); + } + } + + private _decodeMapAsMap(map, remaining, flags, chunk) { + // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys + while (remaining > 0) { + if (this._cursor >= chunk.length) { + return this._decodeMapAsMap.bind( + this, + map, + remaining, + flags + ); + } + + const key = this._decodeMapKey(flags, chunk); + if (typeof key === 'function') { + return this._continueDecodeMapKey.bind( + this, + map, + remaining, + key, + flags + ); + } + + if (this._cursor >= chunk.length) { + return this._continueDecodeMapValue.bind( + this, + map, + remaining, + key, + this._decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this._decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this._continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + --remaining; + } + + return map; + } + + private _decodeMapKey(flags, chunk) { + const type = chunk[this._cursor]; + return ++this._cursor === chunk.length ? + this._decodeMapKeyValue.bind(this, type, flags) : + this._decodeMapKeyValue(type, flags, chunk); + } + + private _decodeMapKeyValue(type, flags, chunk) { + switch (type) { + // decode simple string map key as string (and not as buffer) + case TYPES.SIMPLE_STRING: + return this._decodeSimpleString(String, chunk); + + // decode blob string map key as string (and not as buffer) + case TYPES.BLOB_STRING: + return this._decodeBlobString(String, chunk); + + default: + return this._decodeNestedTypeValue(type, flags, chunk); + } + } + + private _continueDecodeMapKey(map, remaining, keyCb, flags, chunk) { + const key = keyCb(chunk); + if (typeof key === 'function') { + return this._continueDecodeMapKey.bind( + this, + map, + remaining, + key, + flags + ); + } + + if (this._cursor >= chunk.length) { + return this._continueDecodeMapValue.bind( + this, + map, + remaining, + key, + this._decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this._decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this._continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + return this._decodeMapAsMap(map, remaining - 1, flags, chunk); + } + + private _continueDecodeMapValue(map, remaining, key, valueCb, flags, chunk) { + const value = valueCb(chunk); + if (typeof value === 'function') { + return this._continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + + return this._decodeMapAsMap(map, remaining - 1, flags, chunk); + } + + private _decodeMapAsObject(object, remaining, flags, chunk) { + while (remaining > 0) { + if (this._cursor >= chunk.length) { + return this._decodeMapAsObject.bind( + this, + object, + remaining, + flags + ); + } + + const key = this._decodeMapKey(flags, chunk); + if (typeof key === 'function') { + return this._continueDecodeMapAsObjectKey.bind( + this, + object, + remaining, + key, + flags + ); + } + + if (this._cursor >= chunk.length) { + return this._continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + this._decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this._decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this._continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + --remaining; + } + + return object; + } + + private _continueDecodeMapAsObjectKey(object, remaining, keyCb, flags, chunk) { + const key = keyCb(chunk); + if (typeof key === 'function') { + return this._continueDecodeMapAsObjectKey.bind( + this, + object, + remaining, + key, + flags + ); + } + + if (this._cursor >= chunk.length) { + return this._continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + this._decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this._decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this._continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + + return this._decodeMapAsObject(object, remaining - 1, flags, chunk); + } + + private _continueDecodeMapAsObjectValue(object, remaining, key, valueCb, flags, chunk) { + const value = valueCb(chunk); + if (typeof value === 'function') { + return this._continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + + return this._decodeMapAsObject(object, remaining - 1, flags, chunk); + } +} diff --git a/packages/client/lib/RESP/encoder.spec.ts b/packages/client/lib/RESP/encoder.spec.ts new file mode 100644 index 00000000000..f8f20d783b3 --- /dev/null +++ b/packages/client/lib/RESP/encoder.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'assert'; +import { describe } from 'mocha'; +import encodeCommand from './encoder'; + +describe('RESP Encoder', () => { + it('1 byte', () => { + assert.deepEqual( + encodeCommand(['a', 'z']), + ['*2\r\n$1\r\na\r\n$1\r\nz\r\n'] + ); + }); + + it('2 bytes', () => { + assert.deepEqual( + encodeCommand(['א', 'ת']), + ['*2\r\n$2\r\nא\r\n$2\r\nת\r\n'] + ); + }); + + it('4 bytes', () => { + assert.deepEqual( + [...encodeCommand(['🐣', '🐤'])], + ['*2\r\n$4\r\n🐣\r\n$4\r\n🐤\r\n'] + ); + }); + + it('buffer', () => { + assert.deepEqual( + encodeCommand([Buffer.from('string')]), + ['*1\r\n$6\r\n', Buffer.from('string'), '\r\n'] + ); + }); +}); diff --git a/packages/client/lib/RESP/encoder.ts b/packages/client/lib/RESP/encoder.ts new file mode 100644 index 00000000000..b1db1c70237 --- /dev/null +++ b/packages/client/lib/RESP/encoder.ts @@ -0,0 +1,28 @@ +import { RedisArgument } from "./types"; + +const CRLF = '\r\n'; + +export default function encodeCommand(args: Array): Array { + const toWrite: Array = []; + + let strings = '*' + args.length + CRLF; + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (typeof arg === 'string') { + strings += '$' + Buffer.byteLength(arg) + CRLF + arg + CRLF; + } else if (arg instanceof Buffer) { + toWrite.push( + strings + '$' + arg.length.toString() + CRLF, + arg + ); + strings = CRLF; + } else { + throw new TypeError(`"arguments[${i}]" must be of type "string | Buffer", got ${typeof arg} instead.`); + } + } + + toWrite.push(strings); + + return toWrite; +} diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts new file mode 100644 index 00000000000..88ca88606d9 --- /dev/null +++ b/packages/client/lib/RESP/types.ts @@ -0,0 +1,417 @@ +import { RedisScriptConfig, SHA1 } from '../lua-script'; +import { TYPES } from './decoder'; +import { VerbatimString } from './verbatim-string'; + +export type RespTypes = typeof TYPES; + +export type RespTypesUnion = RespTypes[keyof RespTypes]; + +type RespType< + RESP_TYPE extends RespTypesUnion, + DEFAULT, + TYPES = never, + FLAG_TYPES = DEFAULT | TYPES +> = (DEFAULT | TYPES) & { + RESP_TYPE: RESP_TYPE; + DEFAULT: DEFAULT; + TYPES: TYPES; + FLAG: Flag; +}; + +export type NullReply = RespType< + RespTypes['NULL'], + null +>; +export type BooleanReply< + T extends boolean = boolean +> = RespType< + RespTypes['BOOLEAN'], + T +>; +export type NumberReply< + T extends number = number +> = RespType< + RespTypes['NUMBER'], + T, + `${T}`, + number | string +>; +export type BigNumberReply< + T extends bigint = bigint +> = RespType< + RespTypes['BIG_NUMBER'], + T, + number | `${T}`, + bigint | number | string +>; +export type DoubleReply< + T extends number = number +> = RespType< + RespTypes['DOUBLE'], + T, + `${T}`, + number | string +>; +export type SimpleStringReply< + T extends string = string +> = RespType< + RespTypes['SIMPLE_STRING'], + T, + Buffer, + string | Buffer +>; +export type BlobStringReply< + T extends string = string +> = RespType< + RespTypes['BLOB_STRING'], + T, + Buffer, + string | Buffer +>; +export type VerbatimStringReply< + T extends string = string +> = RespType< + RespTypes['VERBATIM_STRING'], + T, + Buffer | VerbatimString, + string | Buffer | VerbatimString +>; +export type SimpleErrorReply = RespType< + RespTypes['SIMPLE_ERROR'], + Buffer +>; +export type BlobErrorReply = RespType< + RespTypes['BLOB_ERROR'], + Buffer +>; +export type ArrayReply = RespType< + RespTypes['ARRAY'], + Array, + never, + Array +>; +export type TuplesReply]> = RespType< + RespTypes['ARRAY'], + T, + never, + Array +>; +export type SetReply = RespType< + RespTypes['SET'], + Array, + Set, + Array | Set +>; +export type MapReply = RespType< + RespTypes['MAP'], + { [key: string]: V }, + Map | Array, + Map | Array +>; + +type MapKeyValue = [key: BlobStringReply, value: unknown]; + +type MapTuples = Array; + +export type TuplesToMapReply = RespType< + RespTypes['MAP'], + { + [P in T[number] as P[0] extends BlobStringReply ? S : never]: P[1]; + }, + Map | FlattenTuples +>; + +type FlattenTuples = ( + T extends [] ? [] : + T extends [MapKeyValue] ? T[0] : + T extends [MapKeyValue, ...infer R] ? [ + ...T[0], + ...FlattenTuples + ] : + never +); + +export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply | + // cannot reuse ArrayReply, SetReply and MapReply because of circular reference + RespType< + RespTypes['ARRAY'], + Array + > | + RespType< + RespTypes['SET'], + Array, + Set + > | + RespType< + RespTypes['MAP'], + { [key: string]: ReplyUnion }, + Map | Array + >; + +export type Reply = ReplyWithFlags; + +export type Flag = ((...args: any) => T) | (new (...args: any) => T); + +type RespTypeUnion = T extends RespType ? FLAG_TYPES : never; + +export type Flags = { + [P in RespTypesUnion]?: Flag>>>; +}; + +type MapKey< + T, + FLAGS extends Flags +> = ReplyWithFlags; + +export type ReplyWithFlags< + REPLY, + FLAGS extends Flags +> = ( + // if REPLY is a type, extract the coresponding type from FLAGS or use the default type + REPLY extends RespType ? + FLAGS[RESP_TYPE] extends Flag ? + ReplyWithFlags, FLAGS> : + ReplyWithFlags + : ( + // if REPLY is a known generic type, convert its generic arguments + // TODO: tuples? + REPLY extends Array ? Array> : + REPLY extends Set ? Set> : + REPLY extends Map ? Map, ReplyWithFlags> : + // `Date` & `Buffer` are supersets of `Record`, so they need to be checked first + REPLY extends Date ? REPLY : + REPLY extends Buffer ? REPLY : + REPLY extends Record ? { + [P in keyof REPLY]: ReplyWithFlags; + } : + // otherwise, just return the REPLY as is + REPLY + ) +); + +export type TransformReply = (this: void, reply: any, preserve?: any) => any; // TODO; + +export type RedisArgument = string | Buffer; + +export type CommandArguments = Array & { preserve?: unknown }; + +export const REQUEST_POLICIES = { + /** + * TODO + */ + ALL_NODES: 'all_nodes', + /** + * TODO + */ + ALL_SHARDS: 'all_shards', + /** + * TODO + */ + SPECIAL: 'special' +} as const; + +export type REQUEST_POLICIES = typeof REQUEST_POLICIES; + +export type RequestPolicies = REQUEST_POLICIES[keyof REQUEST_POLICIES]; + +export const RESPONSE_POLICIES = { + /** + * TODO + */ + ONE_SUCCEEDED: 'one_succeeded', + /** + * TODO + */ + ALL_SUCCEEDED: 'all_succeeded', + /** + * TODO + */ + LOGICAL_AND: 'agg_logical_and', + /** + * TODO + */ + SPECIAL: 'special' +} as const; + +export type RESPONSE_POLICIES = typeof RESPONSE_POLICIES; + +export type ResponsePolicies = RESPONSE_POLICIES[keyof RESPONSE_POLICIES]; + +export type CommandPolicies = { + request?: RequestPolicies | null; + response?: ResponsePolicies | null; +}; + +export type Command = { + FIRST_KEY_INDEX?: number | ((this: void, ...args: Array) => RedisArgument | undefined); + IS_READ_ONLY?: boolean; + POLICIES?: CommandPolicies; + transformArguments(this: void, ...args: Array): CommandArguments; + TRANSFORM_LEGACY_REPLY?: boolean; + transformReply: TransformReply | Record; +}; + +export type RedisCommands = Record; + +export type RedisModules = Record; + +export interface RedisFunction extends Command { + NUMBER_OF_KEYS?: number; +} + +export type RedisFunctions = Record>; + +export type RedisScript = RedisScriptConfig & SHA1; + +export type RedisScripts = Record; + +// TODO: move to Commander? +export interface CommanderConfig< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> { + modules?: M; + functions?: F; + scripts?: S; + /** + * TODO + */ + RESP?: RESP; +} + +type Resp2Array = ( + T extends [] ? [] : + T extends [infer ITEM] ? [Resp2Reply] : + T extends [infer ITEM, ...infer REST] ? [ + Resp2Reply, + ...Resp2Array + ] : + T extends Array ? Array> : + never +); + +export type Resp2Reply = ( + RESP3REPLY extends RespType ? + // TODO: RESP3 only scalar types + RESP_TYPE extends RespTypes['DOUBLE'] ? BlobStringReply : + RESP_TYPE extends RespTypes['ARRAY'] | RespTypes['SET'] ? RespType< + RESP_TYPE, + Resp2Array + > : + RESP_TYPE extends RespTypes['MAP'] ? RespType< + RespTypes['ARRAY'], + Resp2Array>> + > : + RespType< + RESP_TYPE, + DEFAULT, + TYPES + > : + RESP3REPLY +); + +export type RespVersions = 2 | 3; + +export type CommandReply< + COMMAND extends Command, + RESP extends RespVersions +> = ( + // if transformReply is a function, use its return type + COMMAND['transformReply'] extends (...args: any) => infer T ? T : + // if transformReply[RESP] is a function, use its return type + COMMAND['transformReply'] extends Record infer T> ? T : + // otherwise use the generic reply type + Reply +); + +export type CommandSignature< + COMMAND extends Command, + RESP extends RespVersions, + FLAGS extends Flags +> = (...args: Parameters) => Promise, FLAGS>>; + +export type CommandWithPoliciesSignature< + COMMAND extends Command, + RESP extends RespVersions, + FLAGS extends Flags, + POLICIES extends CommandPolicies +> = (...args: Parameters) => Promise< + ReplyWithPolicy< + ReplyWithFlags, FLAGS>, + MergePolicies + > +>; + +export type MergePolicies< + COMMAND extends Command, + POLICIES extends CommandPolicies +> = Omit & POLICIES; + +type ReplyWithPolicy< + REPLY, + POLICIES extends CommandPolicies, +> = ( + POLICIES['request'] extends REQUEST_POLICIES['SPECIAL'] ? never : + POLICIES['request'] extends null | undefined ? REPLY : + unknown extends POLICIES['request'] ? REPLY : + POLICIES['response'] extends RESPONSE_POLICIES['SPECIAL'] ? never : + POLICIES['response'] extends RESPONSE_POLICIES['ALL_SUCCEEDED' | 'ONE_SUCCEEDED' | 'LOGICAL_AND'] ? REPLY : + // otherwise, return array of replies + Array +); + +const SAME = { + transformArguments(key: string): Array { + return ['GET', key]; + }, + transformReply: () => 'default' as const +} satisfies Command; + +type SAME_DEFAULT = CommandWithPoliciesSignature< + typeof SAME, + 2, + {}, + { + request: REQUEST_POLICIES['ALL_NODES']; + response: RESPONSE_POLICIES['SPECIAL']; + } +>; + +// type SAME_RESP2 = CommandReply; +// type SAME_COMMAND_RESP2 = CommandSignuture; +// type SAME_RESP3 = CommandReply; +// type SAME_COMMAND_RESP3 = CommandSignuture; + +// interface Test { +// /** +// * This is a test +// */ +// a: 'a'; +// } + +// const DIFFERENT = { +// transformArguments(key: string): Array { +// return ['GET', key]; +// }, +// transformReply: { +// 2: () => null as any as Test, +// 3: () => '3' as const +// } +// } satisfies Command; + +// type DIFFERENT_RESP2 = CommandReply; +// type DIFFERENT_COMMAND_RESP2 = CommandSignuture; +// type DIFFERENT_RESP3 = CommandReply; +// type DIFFERENT_COMMAND_RESP3 = CommandSignuture; + +// const a = null as any as DIFFERENT_COMMAND_RESP2; + +// const b = await a('a'); + +// b.a \ No newline at end of file diff --git a/packages/client/lib/RESP/verbatim-string.ts b/packages/client/lib/RESP/verbatim-string.ts new file mode 100644 index 00000000000..92ff4fe3fb1 --- /dev/null +++ b/packages/client/lib/RESP/verbatim-string.ts @@ -0,0 +1,8 @@ +export class VerbatimString extends String { + constructor( + public format: string, + value: string + ) { + super(value); + } +} diff --git a/packages/client/lib/client/RESP2/composers/buffer.spec.ts b/packages/client/lib/client/RESP2/composers/buffer.spec.ts deleted file mode 100644 index f57c369fecb..00000000000 --- a/packages/client/lib/client/RESP2/composers/buffer.spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { strict as assert } from 'assert'; -import BufferComposer from './buffer'; - -describe('Buffer Composer', () => { - const composer = new BufferComposer(); - - it('should compose two buffers', () => { - composer.write(Buffer.from([0])); - assert.deepEqual( - composer.end(Buffer.from([1])), - Buffer.from([0, 1]) - ); - }); -}); diff --git a/packages/client/lib/client/RESP2/composers/buffer.ts b/packages/client/lib/client/RESP2/composers/buffer.ts deleted file mode 100644 index 4affb4283e0..00000000000 --- a/packages/client/lib/client/RESP2/composers/buffer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Composer } from './interface'; - -export default class BufferComposer implements Composer { - private chunks: Array = []; - - write(buffer: Buffer): void { - this.chunks.push(buffer); - } - - end(buffer: Buffer): Buffer { - this.write(buffer); - return Buffer.concat(this.chunks.splice(0)); - } - - reset() { - this.chunks = []; - } -} diff --git a/packages/client/lib/client/RESP2/composers/interface.ts b/packages/client/lib/client/RESP2/composers/interface.ts deleted file mode 100644 index 0fc8f031414..00000000000 --- a/packages/client/lib/client/RESP2/composers/interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface Composer { - write(buffer: Buffer): void; - - end(buffer: Buffer): T; - - reset(): void; -} diff --git a/packages/client/lib/client/RESP2/composers/string.spec.ts b/packages/client/lib/client/RESP2/composers/string.spec.ts deleted file mode 100644 index 9dd26aae021..00000000000 --- a/packages/client/lib/client/RESP2/composers/string.spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { strict as assert } from 'assert'; -import StringComposer from './string'; - -describe('String Composer', () => { - const composer = new StringComposer(); - - it('should compose two strings', () => { - composer.write(Buffer.from([0])); - assert.deepEqual( - composer.end(Buffer.from([1])), - Buffer.from([0, 1]).toString() - ); - }); -}); diff --git a/packages/client/lib/client/RESP2/composers/string.ts b/packages/client/lib/client/RESP2/composers/string.ts deleted file mode 100644 index 0cd8f00e95c..00000000000 --- a/packages/client/lib/client/RESP2/composers/string.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { StringDecoder } from 'string_decoder'; -import { Composer } from './interface'; - -export default class StringComposer implements Composer { - private decoder = new StringDecoder(); - - private string = ''; - - write(buffer: Buffer): void { - this.string += this.decoder.write(buffer); - } - - end(buffer: Buffer): string { - const string = this.string + this.decoder.end(buffer); - this.string = ''; - return string; - } - - reset() { - this.string = ''; - } -} diff --git a/packages/client/lib/client/RESP2/decoder.ts b/packages/client/lib/client/RESP2/decoder.ts deleted file mode 100644 index 525f118bf30..00000000000 --- a/packages/client/lib/client/RESP2/decoder.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { ErrorReply } from '../../errors'; -import { Composer } from './composers/interface'; -import BufferComposer from './composers/buffer'; -import StringComposer from './composers/string'; - -// RESP2 specification -// https://redis.io/topics/protocol - -enum Types { - SIMPLE_STRING = 43, // + - ERROR = 45, // - - INTEGER = 58, // : - BULK_STRING = 36, // $ - ARRAY = 42 // * -} - -enum ASCII { - CR = 13, // \r - ZERO = 48, - MINUS = 45 -} - -export type Reply = string | Buffer | ErrorReply | number | null | Array; - -type ArrayReply = Array | null; - -export type ReturnStringsAsBuffers = () => boolean; - -interface RESP2Options { - returnStringsAsBuffers: ReturnStringsAsBuffers; - onReply(reply: Reply): unknown; -} - -interface ArrayInProcess { - array: Array; - pushCounter: number; -} - -// Using TypeScript `private` and not the build-in `#` to avoid __classPrivateFieldGet and __classPrivateFieldSet - -export default class RESP2Decoder { - constructor(private options: RESP2Options) {} - - private cursor = 0; - - private type?: Types; - - private bufferComposer = new BufferComposer(); - - private stringComposer = new StringComposer(); - - private currentStringComposer: BufferComposer | StringComposer = this.stringComposer; - - reset() { - this.cursor = 0; - this.type = undefined; - this.bufferComposer.reset(); - this.stringComposer.reset(); - this.currentStringComposer = this.stringComposer; - } - - write(chunk: Buffer): void { - while (this.cursor < chunk.length) { - if (!this.type) { - this.currentStringComposer = this.options.returnStringsAsBuffers() ? - this.bufferComposer : - this.stringComposer; - - this.type = chunk[this.cursor]; - if (++this.cursor >= chunk.length) break; - } - - const reply = this.parseType(chunk, this.type); - if (reply === undefined) break; - - this.type = undefined; - this.options.onReply(reply); - } - - this.cursor -= chunk.length; - } - - private parseType(chunk: Buffer, type: Types, arraysToKeep?: number): Reply | undefined { - switch (type) { - case Types.SIMPLE_STRING: - return this.parseSimpleString(chunk); - - case Types.ERROR: - return this.parseError(chunk); - - case Types.INTEGER: - return this.parseInteger(chunk); - - case Types.BULK_STRING: - return this.parseBulkString(chunk); - - case Types.ARRAY: - return this.parseArray(chunk, arraysToKeep); - } - } - - private compose< - C extends Composer, - T = C extends Composer ? TT : never - >( - chunk: Buffer, - composer: C - ): T | undefined { - for (let i = this.cursor; i < chunk.length; i++) { - if (chunk[i] === ASCII.CR) { - const reply = composer.end( - chunk.subarray(this.cursor, i) - ); - this.cursor = i + 2; - return reply; - } - } - - const toWrite = chunk.subarray(this.cursor); - composer.write(toWrite); - this.cursor = chunk.length; - } - - private parseSimpleString(chunk: Buffer): string | Buffer | undefined { - return this.compose(chunk, this.currentStringComposer); - } - - private parseError(chunk: Buffer): ErrorReply | undefined { - const message = this.compose(chunk, this.stringComposer); - if (message !== undefined) { - return new ErrorReply(message); - } - } - - private integer = 0; - - private isNegativeInteger?: boolean; - - private parseInteger(chunk: Buffer): number | undefined { - if (this.isNegativeInteger === undefined) { - this.isNegativeInteger = chunk[this.cursor] === ASCII.MINUS; - if (this.isNegativeInteger && ++this.cursor === chunk.length) return; - } - - do { - const byte = chunk[this.cursor]; - if (byte === ASCII.CR) { - const integer = this.isNegativeInteger ? -this.integer : this.integer; - this.integer = 0; - this.isNegativeInteger = undefined; - this.cursor += 2; - return integer; - } - - this.integer = this.integer * 10 + byte - ASCII.ZERO; - } while (++this.cursor < chunk.length); - } - - private bulkStringRemainingLength?: number; - - private parseBulkString(chunk: Buffer): string | Buffer | null | undefined { - if (this.bulkStringRemainingLength === undefined) { - const length = this.parseInteger(chunk); - if (length === undefined) return; - if (length === -1) return null; - - this.bulkStringRemainingLength = length; - - if (this.cursor >= chunk.length) return; - } - - const end = this.cursor + this.bulkStringRemainingLength; - if (chunk.length >= end) { - const reply = this.currentStringComposer.end( - chunk.subarray(this.cursor, end) - ); - this.bulkStringRemainingLength = undefined; - this.cursor = end + 2; - return reply; - } - - const toWrite = chunk.subarray(this.cursor); - this.currentStringComposer.write(toWrite); - this.bulkStringRemainingLength -= toWrite.length; - this.cursor = chunk.length; - } - - private arraysInProcess: Array = []; - - private initializeArray = false; - - private arrayItemType?: Types; - - private parseArray(chunk: Buffer, arraysToKeep = 0): ArrayReply | undefined { - if (this.initializeArray || this.arraysInProcess.length === arraysToKeep) { - const length = this.parseInteger(chunk); - if (length === undefined) { - this.initializeArray = true; - return undefined; - } - - this.initializeArray = false; - this.arrayItemType = undefined; - - if (length === -1) { - return this.returnArrayReply(null, arraysToKeep, chunk); - } else if (length === 0) { - return this.returnArrayReply([], arraysToKeep, chunk); - } - - this.arraysInProcess.push({ - array: new Array(length), - pushCounter: 0 - }); - } - - while (this.cursor < chunk.length) { - if (!this.arrayItemType) { - this.arrayItemType = chunk[this.cursor]; - - if (++this.cursor >= chunk.length) break; - } - - const item = this.parseType( - chunk, - this.arrayItemType, - arraysToKeep + 1 - ); - if (item === undefined) break; - - this.arrayItemType = undefined; - - const reply = this.pushArrayItem(item, arraysToKeep); - if (reply !== undefined) return reply; - } - } - - private returnArrayReply(reply: ArrayReply, arraysToKeep: number, chunk?: Buffer): ArrayReply | undefined { - if (this.arraysInProcess.length <= arraysToKeep) return reply; - - return this.pushArrayItem(reply, arraysToKeep, chunk); - } - - private pushArrayItem(item: Reply, arraysToKeep: number, chunk?: Buffer): ArrayReply | undefined { - const to = this.arraysInProcess[this.arraysInProcess.length - 1]!; - to.array[to.pushCounter] = item; - if (++to.pushCounter === to.array.length) { - return this.returnArrayReply( - this.arraysInProcess.pop()!.array, - arraysToKeep, - chunk - ); - } else if (chunk && chunk.length > this.cursor) { - return this.parseArray(chunk, arraysToKeep); - } - } -} diff --git a/packages/client/lib/client/RESP2/encoder.spec.ts b/packages/client/lib/client/RESP2/encoder.spec.ts deleted file mode 100644 index 486259472a4..00000000000 --- a/packages/client/lib/client/RESP2/encoder.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { strict as assert } from 'assert'; -import { describe } from 'mocha'; -import encodeCommand from './encoder'; - -describe('RESP2 Encoder', () => { - it('1 byte', () => { - assert.deepEqual( - encodeCommand(['a', 'z']), - ['*2\r\n$1\r\na\r\n$1\r\nz\r\n'] - ); - }); - - it('2 bytes', () => { - assert.deepEqual( - encodeCommand(['א', 'ת']), - ['*2\r\n$2\r\nא\r\n$2\r\nת\r\n'] - ); - }); - - it('4 bytes', () => { - assert.deepEqual( - [...encodeCommand(['🐣', '🐤'])], - ['*2\r\n$4\r\n🐣\r\n$4\r\n🐤\r\n'] - ); - }); - - it('buffer', () => { - assert.deepEqual( - encodeCommand([Buffer.from('string')]), - ['*1\r\n$6\r\n', Buffer.from('string'), '\r\n'] - ); - }); -}); diff --git a/packages/client/lib/client/RESP2/encoder.ts b/packages/client/lib/client/RESP2/encoder.ts deleted file mode 100644 index 217fbc714bb..00000000000 --- a/packages/client/lib/client/RESP2/encoder.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { RedisCommandArgument, RedisCommandArguments } from '../../commands'; - -const CRLF = '\r\n'; - -export default function encodeCommand(args: RedisCommandArguments): Array { - const toWrite: Array = []; - - let strings = '*' + args.length + CRLF; - - for (let i = 0; i < args.length; i++) { - const arg = args[i]; - if (typeof arg === 'string') { - strings += '$' + Buffer.byteLength(arg) + CRLF + arg + CRLF; - } else if (arg instanceof Buffer) { - toWrite.push( - strings + '$' + arg.length.toString() + CRLF, - arg - ); - strings = CRLF; - } else { - throw new TypeError('Invalid argument type'); - } - } - - toWrite.push(strings); - - return toWrite; -} diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 7fffed86580..9d215799e0a 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,263 +1,319 @@ import * as LinkedList from 'yallist'; -import { AbortError, ErrorReply } from '../errors'; -import { RedisCommandArguments, RedisCommandRawReply } from '../commands'; -import RESP2Decoder from './RESP2/decoder'; -import encodeCommand from './RESP2/encoder'; +import encodeCommand from '../RESP/encoder'; +import { Decoder, PUSH_FLAGS, TYPES } from '../RESP/decoder'; +import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; +import { AbortError, ErrorReply } from '../errors'; +import { EventEmitter } from 'stream'; export interface QueueCommandOptions { - asap?: boolean; - chainId?: symbol; - signal?: AbortSignal; - returnBuffers?: boolean; + asap?: boolean; + chainId?: symbol; + signal?: AbortSignal; + flags?: Flags; } export interface CommandWaitingToBeSent extends CommandWaitingForReply { - args: RedisCommandArguments; - chainId?: symbol; - abort?: { - signal: AbortSignal; - listener(): void; - }; + args: CommandArguments; + chainId?: symbol; + removeAbortListener?(): void; } interface CommandWaitingForReply { - resolve(reply?: unknown): void; - reject(err: unknown): void; - channelsCounter?: number; - returnBuffers?: boolean; + resolve(reply?: unknown): void; + reject(err: unknown): void; + channelsCounter?: number; + flags?: Flags; } +export type OnShardedChannelMoved = (channel: string, listeners: ChannelListeners) => void; + const PONG = Buffer.from('pong'); -export type OnShardedChannelMoved = (channel: string, listeners: ChannelListeners) => void; +const RESP2_PUSH_FLAGS = { + ...PUSH_FLAGS, + [TYPES.SIMPLE_STRING]: Buffer +}; export default class RedisCommandsQueue { - static #flushQueue(queue: LinkedList, err: Error): void { - while (queue.length) { - queue.shift()!.reject(err); - } + private readonly _maxLength: number | null | undefined; + private readonly _waitingToBeSent = new LinkedList(); + private readonly _waitingForReply = new LinkedList(); + private readonly _onShardedChannelMoved: OnShardedChannelMoved; + + private readonly _pubSub = new PubSub(); + + get isPubSubActive() { + return this._pubSub.isActive; + } + + private _chainInExecution: symbol | undefined; + + decoder: Decoder; + + constructor( + respVersion: RespVersions | null | undefined, + maxLength: number | null | undefined, + onShardedChannelMoved: EventEmitter['emit'] + ) { + this.decoder = this._initiateDecoder(respVersion); + this._maxLength = maxLength; + this._onShardedChannelMoved = onShardedChannelMoved; + } + + private _initiateDecoder(respVersion: RespVersions | null | undefined) { + return respVersion === 3 ? + this._initiateResp3Decoder() : + this._initiateResp2Decoder(); + } + + private _onReply(reply: ReplyUnion) { + this._waitingForReply.shift()!.resolve(reply); + } + + private _onErrorReply(err: ErrorReply) { + this._waitingForReply.shift()!.reject(err); + } + + private _onPush(push: Array) { + // TODO: type + if (this._pubSub.handleMessageReply(push)) return true; + + const isShardedUnsubscribe = PubSub.isShardedUnsubscribe(push); + if (isShardedUnsubscribe && !this._waitingForReply.length) { + const channel = push[1].toString(); + this._onShardedChannelMoved( + channel, + this._pubSub.removeShardedListeners(channel) + ); + return true; + } else if (isShardedUnsubscribe || PubSub.isStatusReply(push)) { + const head = this._waitingForReply.head!.value; + if ( + (Number.isNaN(head.channelsCounter!) && push[2] === 0) || + --head.channelsCounter! === 0 + ) { + this._waitingForReply.shift()!.resolve(); + } + return true; } + } - readonly #maxLength: number | null | undefined; - readonly #waitingToBeSent = new LinkedList(); - readonly #waitingForReply = new LinkedList(); - readonly #onShardedChannelMoved: OnShardedChannelMoved; - - readonly #pubSub = new PubSub(); - - get isPubSubActive() { - return this.#pubSub.isActive; - } + private _getFlags() { + return this._waitingForReply.head!.value.flags ?? {}; + } - #chainInExecution: symbol | undefined; + private _initiateResp3Decoder() { + return new Decoder({ + onReply: reply => this._onReply(reply), + onErrorReply: err => this._onErrorReply(err), + onPush: push => { + if (!this._onPush(push)) { - #decoder = new RESP2Decoder({ - returnStringsAsBuffers: () => { - return !!this.#waitingForReply.head?.value.returnBuffers || - this.#pubSub.isActive; - }, - onReply: reply => { - if (this.#pubSub.isActive && Array.isArray(reply)) { - if (this.#pubSub.handleMessageReply(reply as Array)) return; - - const isShardedUnsubscribe = PubSub.isShardedUnsubscribe(reply as Array); - if (isShardedUnsubscribe && !this.#waitingForReply.length) { - const channel = (reply[1] as Buffer).toString(); - this.#onShardedChannelMoved( - channel, - this.#pubSub.removeShardedListeners(channel) - ); - return; - } else if (isShardedUnsubscribe || PubSub.isStatusReply(reply as Array)) { - const head = this.#waitingForReply.head!.value; - if ( - (Number.isNaN(head.channelsCounter!) && reply[2] === 0) || - --head.channelsCounter! === 0 - ) { - this.#waitingForReply.shift()!.resolve(); - } - return; - } - if (PONG.equals(reply[0] as Buffer)) { - const { resolve, returnBuffers } = this.#waitingForReply.shift()!, - buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(returnBuffers ? buffer : buffer.toString()); - return; - } - } - - const { resolve, reject } = this.#waitingForReply.shift()!; - if (reply instanceof ErrorReply) { - reject(reply); - } else { - resolve(reply); - } } + }, + getFlags: () => this._getFlags() }); - - constructor( - maxLength: number | null | undefined, - onShardedChannelMoved: OnShardedChannelMoved - ) { - this.#maxLength = maxLength; - this.#onShardedChannelMoved = onShardedChannelMoved; - } - - addCommand(args: RedisCommandArguments, options?: QueueCommandOptions): Promise { - if (this.#maxLength && this.#waitingToBeSent.length + this.#waitingForReply.length >= this.#maxLength) { - return Promise.reject(new Error('The queue is full')); - } else if (options?.signal?.aborted) { - return Promise.reject(new AbortError()); + } + + private _initiateResp2Decoder() { + return new Decoder({ + onReply: reply => { + if (this._pubSub.isActive && Array.isArray(reply)) { + if (this._onPush(reply)) return; + + if (PONG.equals(reply[0] as Buffer)) { + const { resolve, flags } = this._waitingForReply.shift()!, + buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; + resolve(flags?.[TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + return; + } } - return new Promise((resolve, reject) => { - const node = new LinkedList.Node({ - args, - chainId: options?.chainId, - returnBuffers: options?.returnBuffers, - resolve, - reject - }); - - if (options?.signal) { - const listener = () => { - this.#waitingToBeSent.removeNode(node); - node.value.reject(new AbortError()); - }; - node.value.abort = { - signal: options.signal, - listener - }; - // AbortSignal type is incorrent - (options.signal as any).addEventListener('abort', listener, { - once: true - }); - } - - if (options?.asap) { - this.#waitingToBeSent.unshiftNode(node); - } else { - this.#waitingToBeSent.pushNode(node); - } - }); - } - - subscribe( - type: PubSubType, - channels: string | Array, - listener: PubSubListener, - returnBuffers?: T - ) { - return this.#pushPubSubCommand( - this.#pubSub.subscribe(type, channels, listener, returnBuffers) - ); - } - - unsubscribe( - type: PubSubType, - channels?: string | Array, - listener?: PubSubListener, - returnBuffers?: T - ) { - return this.#pushPubSubCommand( - this.#pubSub.unsubscribe(type, channels, listener, returnBuffers) - ); - } - - resubscribe(): Promise | undefined { - const commands = this.#pubSub.resubscribe(); - if (!commands.length) return; - - return Promise.all( - commands.map(command => this.#pushPubSubCommand(command)) - ); - } - - extendPubSubChannelListeners( - type: PubSubType, - channel: string, - listeners: ChannelListeners - ) { - return this.#pushPubSubCommand( - this.#pubSub.extendChannelListeners(type, channel, listeners) - ); - } + this._onReply(reply); + }, + onErrorReply: err => this._onErrorReply(err), + // PUSH type does not exist in RESP2 + // PubSub is handled in onReply + // @ts-expect-error + onPush: undefined, + getFlags: () => { + // PubSub push is an Array in RESP2 + return this._pubSub.isActive ? + RESP2_PUSH_FLAGS : + this._getFlags(); + } + }); + } - extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this.#pushPubSubCommand( - this.#pubSub.extendTypeListeners(type, listeners) - ); + addCommand(args: CommandArguments, options?: QueueCommandOptions): Promise { + if (this._maxLength && this._waitingToBeSent.length + this._waitingForReply.length >= this._maxLength) { + return Promise.reject(new Error('The queue is full')); + } else if (options?.signal?.aborted) { + return Promise.reject(new AbortError()); } - getPubSubListeners(type: PubSubType) { - return this.#pubSub.getTypeListeners(type); + return new Promise((resolve, reject) => { + const node = new LinkedList.Node({ + args, + chainId: options?.chainId, + flags: options?.flags, + resolve, + reject + }); + + if (options?.signal) { + const listener = () => { + this._waitingToBeSent.removeNode(node); + node.value.reject(new AbortError()); + }; + + node.value.removeAbortListener = () => options.signal?.removeEventListener('abort', listener); + + options.signal.addEventListener('abort', listener, { once: true }); + } + + if (options?.asap) { + this._waitingToBeSent.unshiftNode(node); + } else { + this._waitingToBeSent.pushNode(node); + } + }); + } + + subscribe( + type: PubSubType, + channels: string | Array, + listener: PubSubListener, + returnBuffers?: T + ) { + return this._pushPubSubCommand( + this._pubSub.subscribe(type, channels, listener, returnBuffers) + ); + } + + unsubscribe( + type: PubSubType, + channels?: string | Array, + listener?: PubSubListener, + returnBuffers?: T + ) { + return this._pushPubSubCommand( + this._pubSub.unsubscribe(type, channels, listener, returnBuffers) + ); + } + + resubscribe(): Promise | undefined { + const commands = this._pubSub.resubscribe(); + if (!commands.length) return; + + return Promise.all( + commands.map(command => this._pushPubSubCommand(command)) + ); + } + + extendPubSubChannelListeners( + type: PubSubType, + channel: string, + listeners: ChannelListeners + ) { + return this._pushPubSubCommand( + this._pubSub.extendChannelListeners(type, channel, listeners) + ); + } + + extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { + return this._pushPubSubCommand( + this._pubSub.extendTypeListeners(type, listeners) + ); + } + + getPubSubListeners(type: PubSubType) { + return this._pubSub.getTypeListeners(type); + } + + private _pushPubSubCommand(command: PubSubCommand) { + if (command === undefined) return; + + return new Promise((resolve, reject) => { + this._waitingToBeSent.push({ + args: command.args, + channelsCounter: command.channelsCounter, + flags: PUSH_FLAGS, + resolve: () => { + command.resolve(); + resolve(); + }, + reject: err => { + command.reject?.(); + reject(err); + } + }); + }); + } + + getCommandToSend(): CommandArguments | undefined { + const toSend = this._waitingToBeSent.shift(); + if (!toSend) return; + + let encoded: CommandArguments; + try { + encoded = encodeCommand(toSend.args); + } catch (err) { + toSend.reject(err); + return; } - #pushPubSubCommand(command: PubSubCommand) { - if (command === undefined) return; - - return new Promise((resolve, reject) => { - this.#waitingToBeSent.push({ - args: command.args, - channelsCounter: command.channelsCounter, - returnBuffers: true, - resolve: () => { - command.resolve(); - resolve(); - }, - reject: err => { - command.reject?.(); - reject(err); - } - }); - }); + // TODO + // reuse `toSend` + (toSend.args as any) = undefined; + if (toSend.removeAbortListener) { + toSend.removeAbortListener(); + (toSend.removeAbortListener as any) = undefined; } - - getCommandToSend(): RedisCommandArguments | undefined { - const toSend = this.#waitingToBeSent.shift(); - if (!toSend) return; - - let encoded: RedisCommandArguments; - try { - encoded = encodeCommand(toSend.args); - } catch (err) { - toSend.reject(err); - return; - } - - this.#waitingForReply.push({ - resolve: toSend.resolve, - reject: toSend.reject, - channelsCounter: toSend.channelsCounter, - returnBuffers: toSend.returnBuffers - }); - this.#chainInExecution = toSend.chainId; - return encoded; + this._waitingForReply.push(toSend); + this._chainInExecution = toSend.chainId; + return encoded; + } + + #flushWaitingForReply(err: Error): void { + while (this._waitingForReply.head) { + this._waitingForReply.shift()!.reject(err); } + } - onReplyChunk(chunk: Buffer): void { - this.#decoder.write(chunk); - } + static #flushWaitingToBeSent(command: CommandWaitingToBeSent, err: Error) { + command.removeAbortListener?.(); + command.reject(err); + } - flushWaitingForReply(err: Error): void { - this.#decoder.reset(); - this.#pubSub.reset(); - RedisCommandsQueue.#flushQueue(this.#waitingForReply, err); + flushWaitingForReply(err: Error): void { + this.decoder.reset(); + this._pubSub.reset(); - if (!this.#chainInExecution) return; + this.#flushWaitingForReply(err); - while (this.#waitingToBeSent.head?.value.chainId === this.#chainInExecution) { - this.#waitingToBeSent.shift(); - } + if (!this._chainInExecution) return; - this.#chainInExecution = undefined; + while (this._waitingToBeSent.head?.value.chainId === this._chainInExecution) { + RedisCommandsQueue.#flushWaitingToBeSent( + this._waitingToBeSent.shift()!, + err + ); } - flushAll(err: Error): void { - this.#decoder.reset(); - this.#pubSub.reset(); - RedisCommandsQueue.#flushQueue(this.#waitingForReply, err); - RedisCommandsQueue.#flushQueue(this.#waitingToBeSent, err); + this._chainInExecution = undefined; + } + + flushAll(err: Error): void { + this.decoder.reset(); + this._pubSub.reset(); + this.#flushWaitingForReply(err); + while (this._waitingToBeSent.head) { + RedisCommandsQueue.#flushWaitingToBeSent( + this._waitingToBeSent.shift()!, + err + ); } + } } diff --git a/packages/client/lib/client/commands.ts b/packages/client/lib/client/commands.ts deleted file mode 100644 index 2605962432a..00000000000 --- a/packages/client/lib/client/commands.ts +++ /dev/null @@ -1,359 +0,0 @@ -import CLUSTER_COMMANDS from '../cluster/commands'; -import * as ACL_CAT from '../commands/ACL_CAT'; -import * as ACL_DELUSER from '../commands/ACL_DELUSER'; -import * as ACL_DRYRUN from '../commands/ACL_DRYRUN'; -import * as ACL_GENPASS from '../commands/ACL_GENPASS'; -import * as ACL_GETUSER from '../commands/ACL_GETUSER'; -import * as ACL_LIST from '../commands/ACL_LIST'; -import * as ACL_LOAD from '../commands/ACL_LOAD'; -import * as ACL_LOG_RESET from '../commands/ACL_LOG_RESET'; -import * as ACL_LOG from '../commands/ACL_LOG'; -import * as ACL_SAVE from '../commands/ACL_SAVE'; -import * as ACL_SETUSER from '../commands/ACL_SETUSER'; -import * as ACL_USERS from '../commands/ACL_USERS'; -import * as ACL_WHOAMI from '../commands/ACL_WHOAMI'; -import * as ASKING from '../commands/ASKING'; -import * as AUTH from '../commands/AUTH'; -import * as BGREWRITEAOF from '../commands/BGREWRITEAOF'; -import * as BGSAVE from '../commands/BGSAVE'; -import * as CLIENT_CACHING from '../commands/CLIENT_CACHING'; -import * as CLIENT_GETNAME from '../commands/CLIENT_GETNAME'; -import * as CLIENT_GETREDIR from '../commands/CLIENT_GETREDIR'; -import * as CLIENT_ID from '../commands/CLIENT_ID'; -import * as CLIENT_KILL from '../commands/CLIENT_KILL'; -import * as CLIENT_LIST from '../commands/CLIENT_LIST'; -import * as CLIENT_NO_EVICT from '../commands/CLIENT_NO-EVICT'; -import * as CLIENT_PAUSE from '../commands/CLIENT_PAUSE'; -import * as CLIENT_SETNAME from '../commands/CLIENT_SETNAME'; -import * as CLIENT_TRACKING from '../commands/CLIENT_TRACKING'; -import * as CLIENT_TRACKINGINFO from '../commands/CLIENT_TRACKINGINFO'; -import * as CLIENT_UNPAUSE from '../commands/CLIENT_UNPAUSE'; -import * as CLIENT_INFO from '../commands/CLIENT_INFO'; -import * as CLUSTER_ADDSLOTS from '../commands/CLUSTER_ADDSLOTS'; -import * as CLUSTER_ADDSLOTSRANGE from '../commands/CLUSTER_ADDSLOTSRANGE'; -import * as CLUSTER_BUMPEPOCH from '../commands/CLUSTER_BUMPEPOCH'; -import * as CLUSTER_COUNT_FAILURE_REPORTS from '../commands/CLUSTER_COUNT-FAILURE-REPORTS'; -import * as CLUSTER_COUNTKEYSINSLOT from '../commands/CLUSTER_COUNTKEYSINSLOT'; -import * as CLUSTER_DELSLOTS from '../commands/CLUSTER_DELSLOTS'; -import * as CLUSTER_DELSLOTSRANGE from '../commands/CLUSTER_DELSLOTSRANGE'; -import * as CLUSTER_FAILOVER from '../commands/CLUSTER_FAILOVER'; -import * as CLUSTER_FLUSHSLOTS from '../commands/CLUSTER_FLUSHSLOTS'; -import * as CLUSTER_FORGET from '../commands/CLUSTER_FORGET'; -import * as CLUSTER_GETKEYSINSLOT from '../commands/CLUSTER_GETKEYSINSLOT'; -import * as CLUSTER_INFO from '../commands/CLUSTER_INFO'; -import * as CLUSTER_KEYSLOT from '../commands/CLUSTER_KEYSLOT'; -import * as CLUSTER_LINKS from '../commands/CLUSTER_LINKS'; -import * as CLUSTER_MEET from '../commands/CLUSTER_MEET'; -import * as CLUSTER_MYID from '../commands/CLUSTER_MYID'; -import * as CLUSTER_NODES from '../commands/CLUSTER_NODES'; -import * as CLUSTER_REPLICAS from '../commands/CLUSTER_REPLICAS'; -import * as CLUSTER_REPLICATE from '../commands/CLUSTER_REPLICATE'; -import * as CLUSTER_RESET from '../commands/CLUSTER_RESET'; -import * as CLUSTER_SAVECONFIG from '../commands/CLUSTER_SAVECONFIG'; -import * as CLUSTER_SET_CONFIG_EPOCH from '../commands/CLUSTER_SET-CONFIG-EPOCH'; -import * as CLUSTER_SETSLOT from '../commands/CLUSTER_SETSLOT'; -import * as CLUSTER_SLOTS from '../commands/CLUSTER_SLOTS'; -import * as COMMAND_COUNT from '../commands/COMMAND_COUNT'; -import * as COMMAND_GETKEYS from '../commands/COMMAND_GETKEYS'; -import * as COMMAND_GETKEYSANDFLAGS from '../commands/COMMAND_GETKEYSANDFLAGS'; -import * as COMMAND_INFO from '../commands/COMMAND_INFO'; -import * as COMMAND_LIST from '../commands/COMMAND_LIST'; -import * as COMMAND from '../commands/COMMAND'; -import * as CONFIG_GET from '../commands/CONFIG_GET'; -import * as CONFIG_RESETASTAT from '../commands/CONFIG_RESETSTAT'; -import * as CONFIG_REWRITE from '../commands/CONFIG_REWRITE'; -import * as CONFIG_SET from '../commands/CONFIG_SET'; -import * as DBSIZE from '../commands/DBSIZE'; -import * as DISCARD from '../commands/DISCARD'; -import * as ECHO from '../commands/ECHO'; -import * as FAILOVER from '../commands/FAILOVER'; -import * as FLUSHALL from '../commands/FLUSHALL'; -import * as FLUSHDB from '../commands/FLUSHDB'; -import * as FUNCTION_DELETE from '../commands/FUNCTION_DELETE'; -import * as FUNCTION_DUMP from '../commands/FUNCTION_DUMP'; -import * as FUNCTION_FLUSH from '../commands/FUNCTION_FLUSH'; -import * as FUNCTION_KILL from '../commands/FUNCTION_KILL'; -import * as FUNCTION_LIST_WITHCODE from '../commands/FUNCTION_LIST_WITHCODE'; -import * as FUNCTION_LIST from '../commands/FUNCTION_LIST'; -import * as FUNCTION_LOAD from '../commands/FUNCTION_LOAD'; -import * as FUNCTION_RESTORE from '../commands/FUNCTION_RESTORE'; -import * as FUNCTION_STATS from '../commands/FUNCTION_STATS'; -import * as HELLO from '../commands/HELLO'; -import * as INFO from '../commands/INFO'; -import * as KEYS from '../commands/KEYS'; -import * as LASTSAVE from '../commands/LASTSAVE'; -import * as LATENCY_DOCTOR from '../commands/LATENCY_DOCTOR'; -import * as LATENCY_GRAPH from '../commands/LATENCY_GRAPH'; -import * as LOLWUT from '../commands/LOLWUT'; -import * as MEMORY_DOCTOR from '../commands/MEMORY_DOCTOR'; -import * as MEMORY_MALLOC_STATS from '../commands/MEMORY_MALLOC-STATS'; -import * as MEMORY_PURGE from '../commands/MEMORY_PURGE'; -import * as MEMORY_STATS from '../commands/MEMORY_STATS'; -import * as MEMORY_USAGE from '../commands/MEMORY_USAGE'; -import * as MODULE_LIST from '../commands/MODULE_LIST'; -import * as MODULE_LOAD from '../commands/MODULE_LOAD'; -import * as MODULE_UNLOAD from '../commands/MODULE_UNLOAD'; -import * as MOVE from '../commands/MOVE'; -import * as PING from '../commands/PING'; -import * as PUBSUB_CHANNELS from '../commands/PUBSUB_CHANNELS'; -import * as PUBSUB_NUMPAT from '../commands/PUBSUB_NUMPAT'; -import * as PUBSUB_NUMSUB from '../commands/PUBSUB_NUMSUB'; -import * as PUBSUB_SHARDCHANNELS from '../commands/PUBSUB_SHARDCHANNELS'; -import * as RANDOMKEY from '../commands/RANDOMKEY'; -import * as READONLY from '../commands/READONLY'; -import * as READWRITE from '../commands/READWRITE'; -import * as REPLICAOF from '../commands/REPLICAOF'; -import * as RESTORE_ASKING from '../commands/RESTORE-ASKING'; -import * as ROLE from '../commands/ROLE'; -import * as SAVE from '../commands/SAVE'; -import * as SCAN from '../commands/SCAN'; -import * as SCRIPT_DEBUG from '../commands/SCRIPT_DEBUG'; -import * as SCRIPT_EXISTS from '../commands/SCRIPT_EXISTS'; -import * as SCRIPT_FLUSH from '../commands/SCRIPT_FLUSH'; -import * as SCRIPT_KILL from '../commands/SCRIPT_KILL'; -import * as SCRIPT_LOAD from '../commands/SCRIPT_LOAD'; -import * as SHUTDOWN from '../commands/SHUTDOWN'; -import * as SWAPDB from '../commands/SWAPDB'; -import * as TIME from '../commands/TIME'; -import * as UNWATCH from '../commands/UNWATCH'; -import * as WAIT from '../commands/WAIT'; - -export default { - ...CLUSTER_COMMANDS, - ACL_CAT, - aclCat: ACL_CAT, - ACL_DELUSER, - aclDelUser: ACL_DELUSER, - ACL_DRYRUN, - aclDryRun: ACL_DRYRUN, - ACL_GENPASS, - aclGenPass: ACL_GENPASS, - ACL_GETUSER, - aclGetUser: ACL_GETUSER, - ACL_LIST, - aclList: ACL_LIST, - ACL_LOAD, - aclLoad: ACL_LOAD, - ACL_LOG_RESET, - aclLogReset: ACL_LOG_RESET, - ACL_LOG, - aclLog: ACL_LOG, - ACL_SAVE, - aclSave: ACL_SAVE, - ACL_SETUSER, - aclSetUser: ACL_SETUSER, - ACL_USERS, - aclUsers: ACL_USERS, - ACL_WHOAMI, - aclWhoAmI: ACL_WHOAMI, - ASKING, - asking: ASKING, - AUTH, - auth: AUTH, - BGREWRITEAOF, - bgRewriteAof: BGREWRITEAOF, - BGSAVE, - bgSave: BGSAVE, - CLIENT_CACHING, - clientCaching: CLIENT_CACHING, - CLIENT_GETNAME, - clientGetName: CLIENT_GETNAME, - CLIENT_GETREDIR, - clientGetRedir: CLIENT_GETREDIR, - CLIENT_ID, - clientId: CLIENT_ID, - CLIENT_KILL, - clientKill: CLIENT_KILL, - 'CLIENT_NO-EVICT': CLIENT_NO_EVICT, - clientNoEvict: CLIENT_NO_EVICT, - CLIENT_LIST, - clientList: CLIENT_LIST, - CLIENT_PAUSE, - clientPause: CLIENT_PAUSE, - CLIENT_SETNAME, - clientSetName: CLIENT_SETNAME, - CLIENT_TRACKING, - clientTracking: CLIENT_TRACKING, - CLIENT_TRACKINGINFO, - clientTrackingInfo: CLIENT_TRACKINGINFO, - CLIENT_UNPAUSE, - clientUnpause: CLIENT_UNPAUSE, - CLIENT_INFO, - clientInfo: CLIENT_INFO, - CLUSTER_ADDSLOTS, - clusterAddSlots: CLUSTER_ADDSLOTS, - CLUSTER_ADDSLOTSRANGE, - clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE, - CLUSTER_BUMPEPOCH, - clusterBumpEpoch: CLUSTER_BUMPEPOCH, - CLUSTER_COUNT_FAILURE_REPORTS, - clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS, - CLUSTER_COUNTKEYSINSLOT, - clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT, - CLUSTER_DELSLOTS, - clusterDelSlots: CLUSTER_DELSLOTS, - CLUSTER_DELSLOTSRANGE, - clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE, - CLUSTER_FAILOVER, - clusterFailover: CLUSTER_FAILOVER, - CLUSTER_FLUSHSLOTS, - clusterFlushSlots: CLUSTER_FLUSHSLOTS, - CLUSTER_FORGET, - clusterForget: CLUSTER_FORGET, - CLUSTER_GETKEYSINSLOT, - clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT, - CLUSTER_INFO, - clusterInfo: CLUSTER_INFO, - CLUSTER_KEYSLOT, - clusterKeySlot: CLUSTER_KEYSLOT, - CLUSTER_LINKS, - clusterLinks: CLUSTER_LINKS, - CLUSTER_MEET, - clusterMeet: CLUSTER_MEET, - CLUSTER_MYID, - clusterMyId: CLUSTER_MYID, - CLUSTER_NODES, - clusterNodes: CLUSTER_NODES, - CLUSTER_REPLICAS, - clusterReplicas: CLUSTER_REPLICAS, - CLUSTER_REPLICATE, - clusterReplicate: CLUSTER_REPLICATE, - CLUSTER_RESET, - clusterReset: CLUSTER_RESET, - CLUSTER_SAVECONFIG, - clusterSaveConfig: CLUSTER_SAVECONFIG, - CLUSTER_SET_CONFIG_EPOCH, - clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH, - CLUSTER_SETSLOT, - clusterSetSlot: CLUSTER_SETSLOT, - CLUSTER_SLOTS, - clusterSlots: CLUSTER_SLOTS, - COMMAND_COUNT, - commandCount: COMMAND_COUNT, - COMMAND_GETKEYS, - commandGetKeys: COMMAND_GETKEYS, - COMMAND_GETKEYSANDFLAGS, - commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS, - COMMAND_INFO, - commandInfo: COMMAND_INFO, - COMMAND_LIST, - commandList: COMMAND_LIST, - COMMAND, - command: COMMAND, - CONFIG_GET, - configGet: CONFIG_GET, - CONFIG_RESETASTAT, - configResetStat: CONFIG_RESETASTAT, - CONFIG_REWRITE, - configRewrite: CONFIG_REWRITE, - CONFIG_SET, - configSet: CONFIG_SET, - DBSIZE, - dbSize: DBSIZE, - DISCARD, - discard: DISCARD, - ECHO, - echo: ECHO, - FAILOVER, - failover: FAILOVER, - FLUSHALL, - flushAll: FLUSHALL, - FLUSHDB, - flushDb: FLUSHDB, - FUNCTION_DELETE, - functionDelete: FUNCTION_DELETE, - FUNCTION_DUMP, - functionDump: FUNCTION_DUMP, - FUNCTION_FLUSH, - functionFlush: FUNCTION_FLUSH, - FUNCTION_KILL, - functionKill: FUNCTION_KILL, - FUNCTION_LIST_WITHCODE, - functionListWithCode: FUNCTION_LIST_WITHCODE, - FUNCTION_LIST, - functionList: FUNCTION_LIST, - FUNCTION_LOAD, - functionLoad: FUNCTION_LOAD, - FUNCTION_RESTORE, - functionRestore: FUNCTION_RESTORE, - FUNCTION_STATS, - functionStats: FUNCTION_STATS, - HELLO, - hello: HELLO, - INFO, - info: INFO, - KEYS, - keys: KEYS, - LASTSAVE, - lastSave: LASTSAVE, - LATENCY_DOCTOR, - latencyDoctor: LATENCY_DOCTOR, - LATENCY_GRAPH, - latencyGraph: LATENCY_GRAPH, - LOLWUT, - lolwut: LOLWUT, - MEMORY_DOCTOR, - memoryDoctor: MEMORY_DOCTOR, - 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS, - memoryMallocStats: MEMORY_MALLOC_STATS, - MEMORY_PURGE, - memoryPurge: MEMORY_PURGE, - MEMORY_STATS, - memoryStats: MEMORY_STATS, - MEMORY_USAGE, - memoryUsage: MEMORY_USAGE, - MODULE_LIST, - moduleList: MODULE_LIST, - MODULE_LOAD, - moduleLoad: MODULE_LOAD, - MODULE_UNLOAD, - moduleUnload: MODULE_UNLOAD, - MOVE, - move: MOVE, - PING, - ping: PING, - PUBSUB_CHANNELS, - pubSubChannels: PUBSUB_CHANNELS, - PUBSUB_NUMPAT, - pubSubNumPat: PUBSUB_NUMPAT, - PUBSUB_NUMSUB, - pubSubNumSub: PUBSUB_NUMSUB, - PUBSUB_SHARDCHANNELS, - pubSubShardChannels: PUBSUB_SHARDCHANNELS, - RANDOMKEY, - randomKey: RANDOMKEY, - READONLY, - readonly: READONLY, - READWRITE, - readwrite: READWRITE, - REPLICAOF, - replicaOf: REPLICAOF, - 'RESTORE-ASKING': RESTORE_ASKING, - restoreAsking: RESTORE_ASKING, - ROLE, - role: ROLE, - SAVE, - save: SAVE, - SCAN, - scan: SCAN, - SCRIPT_DEBUG, - scriptDebug: SCRIPT_DEBUG, - SCRIPT_EXISTS, - scriptExists: SCRIPT_EXISTS, - SCRIPT_FLUSH, - scriptFlush: SCRIPT_FLUSH, - SCRIPT_KILL, - scriptKill: SCRIPT_KILL, - SCRIPT_LOAD, - scriptLoad: SCRIPT_LOAD, - SHUTDOWN, - shutdown: SHUTDOWN, - SWAPDB, - swapDb: SWAPDB, - TIME, - time: TIME, - UNWATCH, - unwatch: UNWATCH, - WAIT, - wait: WAIT -}; diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 5dd386647ef..7d5e18a4c1b 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -1,823 +1,919 @@ -import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisCommandReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, RedisCommandSignature, ConvertArgumentType, RedisFunction, ExcludeMappedString, RedisCommands } from '../commands'; +import COMMANDS from '../commands'; import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket'; import RedisCommandsQueue, { QueueCommandOptions } from './commands-queue'; -import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; -import { RedisMultiQueuedCommand } from '../multi-command'; import { EventEmitter } from 'events'; -import { CommandOptions, commandOptions, isCommandOptions } from '../command-options'; -import { ScanOptions, ZMember } from '../commands/generic-transformers'; -import { ScanCommandOptions } from '../commands/SCAN'; -import { HScanTuple } from '../commands/HSCAN'; -import { attachCommands, attachExtensions, fCallArguments, transformCommandArguments, transformCommandReply, transformLegacyCommandArguments } from '../commander'; -import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; +import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import { ClientClosedError, ClientOfflineError, DisconnectsClientError } from '../errors'; import { URL } from 'url'; import { TcpSocketConnectOpts } from 'net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; -import { callbackify } from 'util'; +import { Command, CommandArguments, CommandSignature, Flags, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; +import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; +import { RedisMultiQueuedCommand } from '../multi-command'; +import HELLO, { HelloOptions } from '../commands/HELLO'; +import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; +import { ReplyWithFlags, BlobStringReply } from '../RESP/types'; +import { ScanCommandOptions } from '../commands/SCAN'; +import { HScanEntry } from '../commands/HSCAN'; +import { ScanOptions, ZMember } from '../commands/generic-transformers'; + + + export interface RedisClientOptions< - M extends RedisModules = RedisModules, - F extends RedisFunctions = RedisFunctions, - S extends RedisScripts = RedisScripts -> extends RedisExtensions { - /** - * `redis[s]://[[username][:password]@][host][:port][/db-number]` - * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details - */ - url?: string; - /** - * Socket connection properties - */ - socket?: RedisSocketOptions; - /** - * ACL username ([see ACL guide](https://redis.io/topics/acl)) - */ - username?: string; - /** - * ACL password or the old "--requirepass" password - */ - password?: string; - /** - * Client name ([see `CLIENT SETNAME`](https://redis.io/commands/client-setname)) - */ - name?: string; - /** - * Redis database number (see [`SELECT`](https://redis.io/commands/select) command) - */ - database?: number; - /** - * Maximum length of the client's internal command queue - */ - commandsQueueMaxLength?: number; - /** - * When `true`, commands are rejected when the client is reconnecting. - * When `false`, commands are queued for execution after reconnection. - */ - disableOfflineQueue?: boolean; - /** - * Connect in [`READONLY`](https://redis.io/commands/readonly) mode - */ - readonly?: boolean; - legacyMode?: boolean; - isolationPoolOptions?: PoolOptions; - /** - * Send `PING` command at interval (in ms). - * Useful with Redis deployments that do not use TCP Keep-Alive. - */ - pingInterval?: number; + M extends RedisModules = RedisModules, + F extends RedisFunctions = RedisFunctions, + S extends RedisScripts = RedisScripts, + RESP extends RespVersions = RespVersions +> extends CommanderConfig { + /** + * `redis[s]://[[username][:password]@][host][:port][/db-number]` + * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details + */ + url?: string; + /** + * Socket connection properties + */ + socket?: RedisSocketOptions; + /** + * ACL username ([see ACL guide](https://redis.io/topics/acl)) + */ + username?: string; + /** + * ACL password or the old "--requirepass" password + */ + password?: string; + /** + * Client name ([see `CLIENT SETNAME`](https://redis.io/commands/client-setname)) + */ + name?: string; + /** + * Redis database number (see [`SELECT`](https://redis.io/commands/select) command) + */ + database?: number; + /** + * Maximum length of the client's internal command queue + */ + commandsQueueMaxLength?: number; + /** + * When `true`, commands are rejected when the client is reconnecting. + * When `false`, commands are queued for execution after reconnection. + */ + disableOfflineQueue?: boolean; + /** + * Connect in [`READONLY`](https://redis.io/commands/readonly) mode + */ + readonly?: boolean; + /** + * TODO + */ + legacyMode?: boolean; + /** + * TODO + */ + isolationPoolOptions?: PoolOptions; + /** + * Send `PING` command at interval (in ms). + * Useful with Redis deployments that do not use TCP Keep-Alive. + */ + pingInterval?: number; } -type WithCommands = { - [P in keyof typeof COMMANDS]: RedisCommandSignature<(typeof COMMANDS)[P]>; +type WithCommands< + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, FLAGS>; }; -export type WithModules = { - [P in keyof M as ExcludeMappedString

]: { - [C in keyof M[P] as ExcludeMappedString]: RedisCommandSignature; - }; +type WithModules< + M extends RedisModules, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; }; -export type WithFunctions = { - [P in keyof F as ExcludeMappedString

]: { - [FF in keyof F[P] as ExcludeMappedString]: RedisCommandSignature; - }; +type WithFunctions< + F extends RedisFunctions, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; }; -export type WithScripts = { - [P in keyof S as ExcludeMappedString

]: RedisCommandSignature; +type WithScripts< + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof S]: CommandSignature; }; export type RedisClientType< - M extends RedisModules = Record, - F extends RedisFunctions = Record, - S extends RedisScripts = Record -> = RedisClient & WithCommands & WithModules & WithFunctions & WithScripts; - -export type InstantiableRedisClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = new (options?: RedisClientOptions) => RedisClientType; + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + FLAGS extends Flags = {} +> = ( + RedisClient & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); export interface ClientCommandOptions extends QueueCommandOptions { - isolated?: boolean; + isolated?: boolean; } -type ClientLegacyCallback = (err: Error | null, reply?: RedisCommandRawReply) => void; +// type ClientLegacyCallback = (err: Error | null, reply?: RedisCommandRawReply) => void; + +type ProxyClient = RedisClient<{}, {}, {}, RespVersions, Flags> & { commandOptions?: ClientCommandOptions }; + +type NamespaceProxyClient = { self: ProxyClient }; + +interface ScanIteratorOptions { + cursor?: number; +} export default class RedisClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags > extends EventEmitter { - static commandOptions(options: T): CommandOptions { - return commandOptions(options); - } - - commandOptions = RedisClient.commandOptions; - - static extend< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(extensions?: RedisExtensions): InstantiableRedisClient { - const Client = attachExtensions({ - BaseClass: RedisClient, - modulesExecutor: RedisClient.prototype.commandsExecutor, - modules: extensions?.modules, - functionsExecutor: RedisClient.prototype.functionsExecuter, - functions: extensions?.functions, - scriptsExecutor: RedisClient.prototype.scriptsExecuter, - scripts: extensions?.scripts + private static _createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: ProxyClient) { + const args = command.transformArguments.apply(undefined, arguments as any), + reply = await this._sendCommand(args, this.commandOptions); + return transformReply ? + transformReply(reply, args.preserve) : + reply; + }; + } + + private static _createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: NamespaceProxyClient) { + const args = command.transformArguments.apply(undefined, arguments as any), + reply = await this.self._sendCommand(args, this.self.commandOptions); + return transformReply ? + transformReply(reply, args.preserve) : + reply; + }; + } + + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return async function (this: NamespaceProxyClient) { + const fnArgs = fn.transformArguments.apply(undefined, arguments as any), + reply = await this.self._sendCommand( + prefix.concat(fnArgs), + this.self.commandOptions + ); + return transformReply ? + transformReply(reply, fnArgs.preserve) : + reply; + }; + } + + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + const prefix = scriptArgumentsPrefix(script), + transformReply = getTransformReply(script, resp); + return async function (this: ProxyClient) { + const scriptArgs = script.transformArguments.apply(undefined, arguments as any), + args = prefix.concat(scriptArgs), + reply = await this._sendCommand(args, this.commandOptions).catch((err: unknown) => { + if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; + + args[0] = 'EVAL'; + args[1] = script.SCRIPT; + return this._sendCommand(args, this.commandOptions); }); - - if (Client !== RedisClient) { - Client.prototype.Multi = RedisClientMultiCommand.extend(extensions); + return transformReply ? + transformReply(reply, scriptArgs.preserve) : + reply; + }; + } + + static factory< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 + >(config?: CommanderConfig) { + const Client = attachConfig({ + BaseClass: RedisClient, + commands: COMMANDS, + createCommand: RedisClient._createCommand, + createFunctionCommand: RedisClient._createFunctionCommand, + createModuleCommand: RedisClient._createModuleCommand, + createScriptCommand: RedisClient._createScriptCommand, + config + }); + + Client.prototype.Multi = RedisClientMultiCommand.extend(config); + + return (options?: Omit>) => { + // returning a proxy of the client to prevent the namespaces.self to leak between proxies + // namespaces will be bootstraped on first access per proxy + return Object.create(new Client(options)) as RedisClientType; + }; + } + + static create< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 + >(options?: RedisClientOptions) { + return RedisClient.factory(options)(options); + } + + static parseURL(url: string): RedisClientOptions { + // https://www.iana.org/assignments/uri-schemes/prov/redis + const { hostname, port, protocol, username, password, pathname } = new URL(url), + parsed: RedisClientOptions = { + socket: { + host: hostname } + }; - return Client; + if (protocol === 'rediss:') { + (parsed.socket as RedisTlsSocketOptions).tls = true; + } else if (protocol !== 'redis:') { + throw new TypeError('Invalid protocol'); } - static create< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(options?: RedisClientOptions): RedisClientType { - return new (RedisClient.extend(options))(options); - } - - static parseURL(url: string): RedisClientOptions { - // https://www.iana.org/assignments/uri-schemes/prov/redis - const { hostname, port, protocol, username, password, pathname } = new URL(url), - parsed: RedisClientOptions = { - socket: { - host: hostname - } - }; - - if (protocol === 'rediss:') { - (parsed.socket as RedisTlsSocketOptions).tls = true; - } else if (protocol !== 'redis:') { - throw new TypeError('Invalid protocol'); - } - - if (port) { - (parsed.socket as TcpSocketConnectOpts).port = Number(port); - } - - if (username) { - parsed.username = decodeURIComponent(username); - } - - if (password) { - parsed.password = decodeURIComponent(password); - } - - if (pathname.length > 1) { - const database = Number(pathname.substring(1)); - if (isNaN(database)) { - throw new TypeError('Invalid pathname'); - } - - parsed.database = database; - } - - return parsed; + if (port) { + (parsed.socket as TcpSocketConnectOpts).port = Number(port); } - readonly #options?: RedisClientOptions; - readonly #socket: RedisSocket; - readonly #queue: RedisCommandsQueue; - readonly #isolationPool: Pool>; - readonly #v4: Record = {}; - #selectedDB = 0; - - get options(): RedisClientOptions | undefined { - return this.#options; + if (username) { + parsed.username = decodeURIComponent(username); } - get isOpen(): boolean { - return this.#socket.isOpen; + if (password) { + parsed.password = decodeURIComponent(password); } - get isReady(): boolean { - return this.#socket.isReady; - } + if (pathname.length > 1) { + const database = Number(pathname.substring(1)); + if (isNaN(database)) { + throw new TypeError('Invalid pathname'); + } - get isPubSubActive() { - return this.#queue.isPubSubActive; + parsed.database = database; } - get v4(): Record { - if (!this.#options?.legacyMode) { - throw new Error('the client is not in "legacy mode"'); - } + return parsed; + } - return this.#v4; - } + self = this; - constructor(options?: RedisClientOptions) { - super(); - this.#options = this.#initiateOptions(options); - this.#queue = this.#initiateQueue(); - this.#socket = this.#initiateSocket(); - this.#isolationPool = createPool({ - create: async () => { - const duplicate = this.duplicate({ - isolationPoolOptions: undefined - }).on('error', err => this.emit('error', err)); - await duplicate.connect(); - return duplicate; - }, - destroy: client => client.disconnect() - }, options?.isolationPoolOptions); - this.#legacyMode(); - } + private readonly _options?: RedisClientOptions; + private readonly _socket: RedisSocket; + private readonly _queue: RedisCommandsQueue; + private _isolationPool?: Pool>; + // readonly #v4: Record = {}; + private _selectedDB = 0; - #initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { - if (options?.url) { - const parsed = RedisClient.parseURL(options.url); - if (options.socket) { - parsed.socket = Object.assign(options.socket, parsed.socket); - } + get options(): RedisClientOptions | undefined { + return this._options; + } - Object.assign(options, parsed); - } + get isOpen(): boolean { + return this._socket.isOpen; + } - if (options?.database) { - this.#selectedDB = options.database; - } + get isReady(): boolean { + return this._socket.isReady; + } - return options; - } + get isPubSubActive() { + return this._queue.isPubSubActive; + } - #initiateQueue(): RedisCommandsQueue { - return new RedisCommandsQueue( - this.#options?.commandsQueueMaxLength, - (channel, listeners) => this.emit('sharded-channel-moved', channel, listeners) - ); - } + // get v4(): Record { + // if (!this.client.#options?.legacyMode) { + // throw new Error('the client is not in "legacy mode"'); + // } - #initiateSocket(): RedisSocket { - const socketInitiator = async (): Promise => { - const promises = []; - - if (this.#selectedDB !== 0) { - promises.push( - this.#queue.addCommand( - ['SELECT', this.#selectedDB.toString()], - { asap: true } - ) - ); - } - - if (this.#options?.readonly) { - promises.push( - this.#queue.addCommand( - COMMANDS.READONLY.transformArguments(), - { asap: true } - ) - ); - } - - if (this.#options?.name) { - promises.push( - this.#queue.addCommand( - COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), - { asap: true } - ) - ); - } - - if (this.#options?.username || this.#options?.password) { - promises.push( - this.#queue.addCommand( - COMMANDS.AUTH.transformArguments({ - username: this.#options.username, - password: this.#options.password ?? '' - }), - { asap: true } - ) - ); - } - - const resubscribePromise = this.#queue.resubscribe(); - if (resubscribePromise) { - promises.push(resubscribePromise); - } - - if (promises.length) { - this.#tick(true); - await Promise.all(promises); - } - }; - - return new RedisSocket(socketInitiator, this.#options?.socket) - .on('data', chunk => this.#queue.onReplyChunk(chunk)) - .on('error', err => { - this.emit('error', err); - if (this.#socket.isOpen && !this.#options?.disableOfflineQueue) { - this.#queue.flushWaitingForReply(err); - } else { - this.#queue.flushAll(err); - } - }) - .on('connect', () => { - this.emit('connect'); - }) - .on('ready', () => { - this.emit('ready'); - this.#setPingTimer(); - this.#tick(); - }) - .on('reconnecting', () => this.emit('reconnecting')) - .on('drain', () => this.#tick()) - .on('end', () => this.emit('end')); - } + // return this.client.#v4; + // } - #legacyMode(): void { - if (!this.#options?.legacyMode) return; - - (this as any).#v4.sendCommand = this.#sendCommand.bind(this); - (this as any).sendCommand = (...args: Array): void => { - const result = this.#legacySendCommand(...args); - if (result) { - result.promise - .then(reply => result.callback(null, reply)) - .catch(err => result.callback(err)); - } - }; - - for (const [ name, command ] of Object.entries(COMMANDS as RedisCommands)) { - this.#defineLegacyCommand(name, command); - (this as any)[name.toLowerCase()] ??= (this as any)[name]; - } + constructor(options?: RedisClientOptions) { + super(); + this._options = this._initiateOptions(options); + this._queue = this._initiateQueue(); + this._socket = this._initiateSocket(); + // this.#legacyMode(); + } - // hard coded commands - this.#defineLegacyCommand('SELECT'); - this.#defineLegacyCommand('select'); - this.#defineLegacyCommand('SUBSCRIBE'); - this.#defineLegacyCommand('subscribe'); - this.#defineLegacyCommand('PSUBSCRIBE'); - this.#defineLegacyCommand('pSubscribe'); - this.#defineLegacyCommand('UNSUBSCRIBE'); - this.#defineLegacyCommand('unsubscribe'); - this.#defineLegacyCommand('PUNSUBSCRIBE'); - this.#defineLegacyCommand('pUnsubscribe'); - this.#defineLegacyCommand('QUIT'); - this.#defineLegacyCommand('quit'); - } + private _initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { + if (options?.url) { + const parsed = RedisClient.parseURL(options.url); + if (options.socket) { + parsed.socket = Object.assign(options.socket, parsed.socket); + } - #legacySendCommand(...args: Array) { - const callback = typeof args[args.length - 1] === 'function' ? - args.pop() as ClientLegacyCallback : - undefined; - - const promise = this.#sendCommand(transformLegacyCommandArguments(args)); - if (callback) return { - promise, - callback - }; - promise.catch(err => this.emit('error', err)); + Object.assign(options, parsed); } - #defineLegacyCommand(name: string, command?: RedisCommand): void { - this.#v4[name] = (this as any)[name].bind(this); - (this as any)[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? - (...args: Array) => { - const result = this.#legacySendCommand(name, ...args); - if (result) { - result.promise - .then(reply => result.callback(null, command.transformReply!(reply))) - .catch(err => result.callback(err)); - } - } : - (...args: Array) => (this as any).sendCommand(name, ...args); + if (options?.database) { + this._selectedDB = options.database; } - #pingTimer?: NodeJS.Timer; - - #setPingTimer(): void { - if (!this.#options?.pingInterval || !this.#socket.isReady) return; - clearTimeout(this.#pingTimer); - - this.#pingTimer = setTimeout(() => { - if (!this.#socket.isReady) return; + return options; + } - // using #sendCommand to support legacy mode - this.#sendCommand(['PING']) - .then(reply => this.emit('ping-interval', reply)) - .catch(err => this.emit('error', err)) - .finally(() => this.#setPingTimer()); - }, this.#options.pingInterval); - } + private _initiateQueue(): RedisCommandsQueue { + return new RedisCommandsQueue( + this._options?.RESP, + this._options?.commandsQueueMaxLength, + (channel, listeners) => this.emit('sharded-channel-moved', channel, listeners) + ); + } - duplicate(overrides?: Partial>): RedisClientType { - return new (Object.getPrototypeOf(this).constructor)({ - ...this.#options, - ...overrides - }); - } - - connect(): Promise { - return this.#socket.connect(); - } + private _initiateSocket(): RedisSocket { + const socketInitiator = async (): Promise => { + const promises = []; - async commandsExecutor( - command: C, - args: Array - ): Promise> { - const { args: redisArgs, options } = transformCommandArguments(command, args); - return transformCommandReply( - command, - await this.#sendCommand(redisArgs, options), - redisArgs.preserve + if (this._selectedDB !== 0) { + promises.push( + this._queue.addCommand( + ['SELECT', this._selectedDB.toString()], + { asap: true } + ) ); - } - - sendCommand( - args: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - return this.#sendCommand(args, options); - } - - // using `#sendCommand` cause `sendCommand` is overwritten in legacy mode - #sendCommand( - args: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - if (!this.#socket.isOpen) { - return Promise.reject(new ClientClosedError()); - } else if (options?.isolated) { - return this.executeIsolated(isolatedClient => - isolatedClient.sendCommand(args, { - ...options, - isolated: false - }) - ); - } else if (!this.#socket.isReady && this.#options?.disableOfflineQueue) { - return Promise.reject(new ClientOfflineError()); + } + + if (this._options?.readonly) { + // promises.push( + // this.#queue.addCommand( + // COMMANDS.READONLY.transformArguments(), + // { asap: true } + // ) + // ); + } + + if (this._options?.RESP) { + const hello: HelloOptions = {}; + + if (this._options.password) { + hello.AUTH = { + username: this._options.username ?? 'default', + password: this._options.password + }; } - const promise = this.#queue.addCommand(args, options); - this.#tick(); - return promise; - } - - async functionsExecuter( - fn: F, - args: Array, - name: string - ): Promise> { - const { args: redisArgs, options } = transformCommandArguments(fn, args); - return transformCommandReply( - fn, - await this.executeFunction(name, fn, redisArgs, options), - redisArgs.preserve - ); - } - - executeFunction( - name: string, - fn: RedisFunction, - args: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - return this.#sendCommand( - fCallArguments(name, fn, args), - options - ); - } - - async scriptsExecuter( - script: S, - args: Array - ): Promise> { - const { args: redisArgs, options } = transformCommandArguments(script, args); - return transformCommandReply( - script, - await this.executeScript(script, redisArgs, options), - redisArgs.preserve - ); - } - - async executeScript( - script: RedisScript, - args: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - const redisArgs: RedisCommandArguments = ['EVALSHA', script.SHA1]; - - if (script.NUMBER_OF_KEYS !== undefined) { - redisArgs.push(script.NUMBER_OF_KEYS.toString()); - } - - redisArgs.push(...args); - - try { - return await this.#sendCommand(redisArgs, options); - } catch (err: any) { - if (!err?.message?.startsWith?.('NOSCRIPT')) { - throw err; - } - - redisArgs[0] = 'EVAL'; - redisArgs[1] = script.SCRIPT; - return this.#sendCommand(redisArgs, options); + if (this._options.name) { + hello.SETNAME = this._options.name; } - } - - async SELECT(db: number): Promise; - async SELECT(options: CommandOptions, db: number): Promise; - async SELECT(options?: any, db?: any): Promise { - if (!isCommandOptions(options)) { - db = options; - options = null; - } - - await this.#sendCommand(['SELECT', db.toString()], options); - this.#selectedDB = db; - } - - select = this.SELECT; - - #pubSubCommand(promise: Promise | undefined) { - if (promise === undefined) return Promise.resolve(); - - this.#tick(); - return promise; - } - - SUBSCRIBE( - channels: string | Array, - listener: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.subscribe( - PubSubType.CHANNELS, - channels, - listener, - bufferMode - ) - ); - } - - subscribe = this.SUBSCRIBE; - - - UNSUBSCRIBE( - channels?: string | Array, - listener?: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.unsubscribe( - PubSubType.CHANNELS, - channels, - listener, - bufferMode - ) - ); - } - - unsubscribe = this.UNSUBSCRIBE; - - PSUBSCRIBE( - patterns: string | Array, - listener: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.subscribe( - PubSubType.PATTERNS, - patterns, - listener, - bufferMode - ) - ); - } - pSubscribe = this.PSUBSCRIBE; - - PUNSUBSCRIBE( - patterns?: string | Array, - listener?: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.unsubscribe( - PubSubType.PATTERNS, - patterns, - listener, - bufferMode - ) + promises.push( + this._queue.addCommand( + HELLO.transformArguments(this._options.RESP, hello), + { asap: true } + ) ); - } - - pUnsubscribe = this.PUNSUBSCRIBE; - - SSUBSCRIBE( - channels: string | Array, - listener: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.subscribe( - PubSubType.SHARDED, - channels, - listener, - bufferMode - ) - ); - } - - sSubscribe = this.SSUBSCRIBE; - - SUNSUBSCRIBE( - channels?: string | Array, - listener?: PubSubListener, - bufferMode?: T - ): Promise { - return this.#pubSubCommand( - this.#queue.unsubscribe( - PubSubType.SHARDED, - channels, - listener, - bufferMode - ) - ); - } - - sUnsubscribe = this.SUNSUBSCRIBE; - - getPubSubListeners(type: PubSubType) { - return this.#queue.getPubSubListeners(type); - } - - extendPubSubChannelListeners( - type: PubSubType, - channel: string, - listeners: ChannelListeners - ) { - return this.#pubSubCommand( - this.#queue.extendPubSubChannelListeners(type, channel, listeners) - ); - } - - extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this.#pubSubCommand( - this.#queue.extendPubSubListeners(type, listeners) - ); - } - - QUIT(): Promise { - return this.#socket.quit(async () => { - const quitPromise = this.#queue.addCommand(['QUIT']); - this.#tick(); - const [reply] = await Promise.all([ - quitPromise, - this.#destroyIsolationPool() - ]); - return reply; - }); - } - - quit = this.QUIT; - - #tick(force = false): void { - if (this.#socket.writableNeedDrain || (!force && !this.#socket.isReady)) { - return; + } else { + if (this._options?.name) { + // promises.push( + // this.#queue.addCommand( + // COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), + // { asap: true } + // ) + // ); } - this.#socket.cork(); - - while (!this.#socket.writableNeedDrain) { - const args = this.#queue.getCommandToSend(); - if (args === undefined) break; - - this.#socket.writeCommand(args); + if (this._options?.username || this._options?.password) { + // promises.push( + // this.#queue.addCommand( + // COMMANDS.AUTH.transformArguments({ + // username: this.#options.username, + // password: this.#options.password ?? '' + // }), + // { asap: true } + // ) + // ); } - } + } - executeIsolated(fn: (client: RedisClientType) => T | Promise): Promise { - return this.#isolationPool.use(fn); - } + const resubscribePromise = this._queue.resubscribe(); + if (resubscribePromise) { + promises.push(resubscribePromise); + } - MULTI(): RedisClientMultiCommandType { - return new (this as any).Multi( - this.multiExecutor.bind(this), - this.#options?.legacyMode - ); - } - - multi = this.MULTI; + if (promises.length) { + this._tick(true); + await Promise.all(promises); + } + }; - async multiExecutor( + return new RedisSocket(socketInitiator, this._options?.socket) + .on('data', chunk => this._queue.decoder.write(chunk)) + .on('error', err => { + this.emit('error', err); + if (this._socket.isOpen && !this._options?.disableOfflineQueue) { + this._queue.flushWaitingForReply(err); + } else { + this._queue.flushAll(err); + } + }) + .on('connect', () => this.emit('connect')) + .on('ready', () => { + this.emit('ready'); + this._setPingTimer(); + this._tick(); + }) + .on('reconnecting', () => this.emit('reconnecting')) + .on('drain', () => this._tick()) + .on('end', () => this.emit('end')); + } + + // #legacyMode(): void { + // if (!this.#options?.legacyMode) return; + + // (this as any).#v4.sendCommand = this.#sendCommand.bind(this); + // (this as any).sendCommand = (...args: Array): void => { + // const result = this.#legacySendCommand(...args); + // if (result) { + // result.promise + // .then(reply => result.callback(null, reply)) + // .catch(err => result.callback(err)); + // } + // }; + + // for (const [name, command] of Object.entries(COMMANDS)) { + // this.#defineLegacyCommand(name, command); + // (this as any)[name.toLowerCase()] ??= (this as any)[name]; + // } + + // // hard coded commands + // this.#defineLegacyCommand('SELECT'); + // this.#defineLegacyCommand('select'); + // this.#defineLegacyCommand('SUBSCRIBE'); + // this.#defineLegacyCommand('subscribe'); + // this.#defineLegacyCommand('PSUBSCRIBE'); + // this.#defineLegacyCommand('pSubscribe'); + // this.#defineLegacyCommand('UNSUBSCRIBE'); + // this.#defineLegacyCommand('unsubscribe'); + // this.#defineLegacyCommand('PUNSUBSCRIBE'); + // this.#defineLegacyCommand('pUnsubscribe'); + // this.#defineLegacyCommand('QUIT'); + // this.#defineLegacyCommand('quit'); + // } + + // #legacySendCommand(...args: Array) { + // const callback = typeof args[args.length - 1] === 'function' ? + // args.pop() as ClientLegacyCallback : + // undefined; + + // const promise = this.#sendCommand(transformLegacyCommandArguments(args)); + // if (callback) return { + // promise, + // callback + // }; + // promise.catch(err => this.emit('error', err)); + // } + + // #defineLegacyCommand(name: string, command?: RedisCommand): void { + // this.#v4[name] = (this as any)[name].bind(this); + // (this as any)[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? + // (...args: Array) => { + // const result = this.#legacySendCommand(name, ...args); + // if (result) { + // result.promise + // .then(reply => result.callback(null, command.transformReply!(reply))) + // .catch(err => result.callback(err)); + // } + // } : + // (...args: Array) => (this as any).sendCommand(name, ...args); + // } + + private _pingTimer?: NodeJS.Timer; + + private _setPingTimer(): void { + if (!this._options?.pingInterval || !this._socket.isReady) return; + clearTimeout(this._pingTimer); + + this._pingTimer = setTimeout(() => { + if (!this._socket.isReady) return; + + // using _sendCommand to support legacy mode + this._sendCommand(['PING']) + .then(reply => this.emit('ping-interval', reply)) + .catch(err => this.emit('error', err)) + .finally(() => this._setPingTimer()); + }, this._options.pingInterval); + } + + withCommandOptions(options: T) { + const proxy = Object.create(this.self); + proxy.commandOptions = options; + return proxy as RedisClientType< + M, + F, + S, + RESP, + T['flags'] extends Flags ? T['flags'] : {} + >; + } + + private _commandOptionsProxy< + K extends keyof ClientCommandOptions, + V extends ClientCommandOptions[K] + >( + key: K, + value: V + ) { + const proxy = Object.create(this.self); + proxy.commandOptions = Object.create((this as ProxyClient).commandOptions ?? null); + proxy.commandOptions[key] = value; + return proxy as RedisClientType< + M, + F, + S, + RESP, + K extends 'flags' ? V extends Flags ? V : {} : FLAGS + >; + } + + /** + * Override the `flags` command option + */ + withFlags(flags: FLAGS) { + return this._commandOptionsProxy('flags', flags); + } + + /** + * Override the `asap` command option to `true` + */ + asap() { + return this._commandOptionsProxy('asap', true); + } + + /** + * Override the `isolated` command option to `true` + */ + isolated() { + return this._commandOptionsProxy('isolated', true); + } + + duplicate(overrides?: Partial>) { + return new (Object.getPrototypeOf(this).constructor)({ + ...this._options, + ...overrides + }) as RedisClientType; + } + + async connect(): Promise { + await this._socket.connect(); + this.self._isolationPool = createPool({ + create: async () => { + const duplicate = this.duplicate({ + isolationPoolOptions: undefined + }).on('error', err => this.emit('error', err)); + await duplicate.connect(); + return duplicate; + }, + destroy: client => client.disconnect() + }, this._options?.isolationPoolOptions); + } + + sendCommand = this._sendCommand.bind(this); + + // using `_` to avoid conflicts with the legacy mode + _sendCommand( + args: CommandArguments, + options?: ClientCommandOptions + ): Promise { + if (!this._socket.isOpen) { + return Promise.reject(new ClientClosedError()); + } else if (options?.isolated) { + return this.executeIsolated(isolatedClient => + isolatedClient.sendCommand(args, { + ...options, + isolated: false + }) + ); + } else if (!this._socket.isReady && this._options?.disableOfflineQueue) { + return Promise.reject(new ClientOfflineError()); + } + + const promise = this._queue.addCommand(args, options); + this._tick(); + return promise; + } + + async SELECT(db: number): Promise { + await this._sendCommand(['SELECT', db.toString()]); + this._selectedDB = db; + } + + select = this.SELECT; + + private _pubSubCommand(promise: Promise | undefined) { + if (promise === undefined) return Promise.resolve(); + + this._tick(); + return promise; + } + + SUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ): Promise { + console.log('SUBSCRIBE', channels, listener, bufferMode, this._options?.RESP); + return this._pubSubCommand( + this._queue.subscribe( + PubSubType.CHANNELS, + channels, + listener, + bufferMode + ) + ); + } + + subscribe = this.SUBSCRIBE; + + UNSUBSCRIBE( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ): Promise { + return this._pubSubCommand( + this._queue.unsubscribe( + PubSubType.CHANNELS, + channels, + listener, + bufferMode + ) + ); + } + + unsubscribe = this.UNSUBSCRIBE; + + PSUBSCRIBE( + patterns: string | Array, + listener: PubSubListener, + bufferMode?: T + ): Promise { + return this._pubSubCommand( + this._queue.subscribe( + PubSubType.PATTERNS, + patterns, + listener, + bufferMode + ) + ); + } + + pSubscribe = this.PSUBSCRIBE; + + PUNSUBSCRIBE( + patterns?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ): Promise { + return this._pubSubCommand( + this._queue.unsubscribe( + PubSubType.PATTERNS, + patterns, + listener, + bufferMode + ) + ); + } + + pUnsubscribe = this.PUNSUBSCRIBE; + + SSUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ): Promise { + return this._pubSubCommand( + this._queue.subscribe( + PubSubType.SHARDED, + channels, + listener, + bufferMode + ) + ); + } + + sSubscribe = this.SSUBSCRIBE; + + SUNSUBSCRIBE( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ): Promise { + return this._pubSubCommand( + this._queue.unsubscribe( + PubSubType.SHARDED, + channels, + listener, + bufferMode + ) + ); + } + + sUnsubscribe = this.SUNSUBSCRIBE; + + getPubSubListeners(type: PubSubType) { + return this._queue.getPubSubListeners(type); + } + + extendPubSubChannelListeners( + type: PubSubType, + channel: string, + listeners: ChannelListeners + ) { + return this._pubSubCommand( + this._queue.extendPubSubChannelListeners(type, channel, listeners) + ); + } + + extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { + return this._pubSubCommand( + this._queue.extendPubSubListeners(type, listeners) + ); + } + + QUIT(): Promise { + return this._socket.quit(async () => { + const quitPromise = this._queue.addCommand(['QUIT']); + this._tick(); + const [reply] = await Promise.all([ + quitPromise, + this._destroyIsolationPool() + ]); + return reply; + }); + } + + quit = this.QUIT; + + _tick(force = false): void { + if (this._socket.writableNeedDrain || (!force && !this._socket.isReady)) { + return; + } + + this._socket.cork(); + + while (!this._socket.writableNeedDrain) { + const args = this._queue.getCommandToSend(); + if (args === undefined) break; + + this._socket.writeCommand(args); + } + } + + executeIsolated(fn: (client: RedisClientType) => T | Promise): Promise { + return this._isolationPool ? + this._isolationPool.use(fn) : + Promise.reject(new ClientClosedError()); + } + + private _addMultiCommands( + commands: Array, + chainId?: symbol, + flags?: Flags + ) { + return Promise.all( + commands.map(({ args }) => this._queue.addCommand(args, { + chainId, + flags + })) + ); + } + + MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, FLAGS> { + return new (this as any).Multi( + async ( commands: Array, selectedDB?: number, chainId?: symbol - ): Promise> { - if (!this.#socket.isOpen) { - return Promise.reject(new ClientClosedError()); + ) => { + if (!this._socket.isOpen) { + return Promise.reject(new ClientClosedError()); } - const promise = chainId ? + const flags = (this as ProxyClient).commandOptions?.flags, + promise = chainId ? // if `chainId` has a value, it's a `MULTI` (and not "pipeline") - need to add the `MULTI` and `EXEC` commands Promise.all([ - this.#queue.addCommand(['MULTI'], { chainId }), - this.#addMultiCommands(commands, chainId), - this.#queue.addCommand(['EXEC'], { chainId }) + this._queue.addCommand(['MULTI'], { chainId }), + this._addMultiCommands(commands, chainId), + this._queue.addCommand(['EXEC'], { chainId, flags }) ]) : - this.#addMultiCommands(commands); + this._addMultiCommands(commands, undefined, flags); - this.#tick(); + this._tick(); const results = await promise; if (selectedDB !== undefined) { - this.#selectedDB = selectedDB; + this._selectedDB = selectedDB; } return results; - } - - #addMultiCommands(commands: Array, chainId?: symbol) { - return Promise.all( - commands.map(({ args }) => this.#queue.addCommand(args, { chainId })) - ); - } - - async* scanIterator(options?: ScanCommandOptions): AsyncIterable { - let cursor = 0; - do { - const reply = await (this as any).scan(cursor, options); - cursor = reply.cursor; - for (const key of reply.keys) { - yield key; - } - } while (cursor !== 0); - } - - async* hScanIterator(key: string, options?: ScanOptions): AsyncIterable> { - let cursor = 0; - do { - const reply = await (this as any).hScan(key, cursor, options); - cursor = reply.cursor; - for (const tuple of reply.tuples) { - yield tuple; - } - } while (cursor !== 0); - } - - async* sScanIterator(key: string, options?: ScanOptions): AsyncIterable { - let cursor = 0; - do { - const reply = await (this as any).sScan(key, cursor, options); - cursor = reply.cursor; - for (const member of reply.members) { - yield member; - } - } while (cursor !== 0); - } - - async* zScanIterator(key: string, options?: ScanOptions): AsyncIterable> { - let cursor = 0; - do { - const reply = await (this as any).zScan(key, cursor, options); - cursor = reply.cursor; - for (const member of reply.members) { - yield member; - } - } while (cursor !== 0); - } - - async disconnect(): Promise { - this.#queue.flushAll(new DisconnectsClientError()); - this.#socket.disconnect(); - await this.#destroyIsolationPool(); - } - - async #destroyIsolationPool(): Promise { - await this.#isolationPool.drain(); - await this.#isolationPool.clear(); - } - - ref(): void { - this.#socket.ref(); - } - - unref(): void { - this.#socket.unref(); - } + } + // self.#options?.legacyMode + ); + } + + multi = this.MULTI; + + async* scanIterator( + this: RedisClientType, + options?: ScanCommandOptions & ScanIteratorOptions + ): AsyncIterable> { + let cursor = options?.cursor ?? 0; + do { + const reply = await this.scan(cursor, options); + cursor = reply.cursor; + for (const key of reply.keys) { + yield key; + } + } while (cursor !== 0); + } + + async* hScanIterator( + this: RedisClientType, + key: RedisArgument, + options?: ScanOptions & ScanIteratorOptions + ): AsyncIterable> { + let cursor = options?.cursor ?? 0; + do { + const reply = await this.hScan(key, cursor, options); + cursor = reply.cursor; + for (const entry of reply.entries) { + yield entry; + } + } while (cursor !== 0); + } + + async* sScanIterator( + this: RedisClientType, + key: RedisArgument, + options?: ScanOptions & ScanIteratorOptions + ): AsyncIterable> { + let cursor = options?.cursor ?? 0; + do { + const reply = await this.sScan(key, cursor, options); + cursor = reply.cursor; + for (const member of reply.members) { + yield member; + } + } while (cursor !== 0); + } + + async* zScanIterator( + this: RedisClientType, + key: RedisArgument, + options?: ScanOptions & ScanIteratorOptions + ): AsyncIterable> { + let cursor = options?.cursor ?? 0; + do { + const reply = await this.zScan(key, cursor, options); + cursor = reply.cursor; + for (const member of reply.members) { + yield member; + } + } while (cursor !== 0); + } + + async disconnect(): Promise { + this._queue.flushAll(new DisconnectsClientError()); + this._socket.disconnect(); + await this._destroyIsolationPool(); + } + + private async _destroyIsolationPool(): Promise { + await this._isolationPool!.drain(); + await this._isolationPool!.clear(); + this.self._isolationPool = undefined; + } + + ref(): void { + this._socket.ref(); + } + + unref(): void { + this._socket.unref(); + } } - -attachCommands({ - BaseClass: RedisClient, - commands: COMMANDS, - executor: RedisClient.prototype.commandsExecutor -}); -(RedisClient.prototype as any).Multi = RedisClientMultiCommand; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index e347667bf2c..d1842e8e61a 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,200 +1,243 @@ -import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, ExcludeMappedString, RedisFunction, RedisCommands } from '../commands'; +import COMMANDS from '../commands'; import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -import { attachCommands, attachExtensions, transformLegacyCommandArguments } from '../commander'; +import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags } from '../RESP/types'; +import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; type CommandSignature< - C extends RedisCommand, - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = (...args: Parameters) => RedisClientMultiCommandType; + REPLIES extends Array, + C extends Command, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = (...args: Parameters) => RedisClientMultiCommandType< + [...REPLIES, ReplyWithFlags, FLAGS>], + M, + F, + S, + RESP, + FLAGS +>; type WithCommands< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags > = { - [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], M, F, S>; + [P in keyof typeof COMMANDS]: CommandSignature; }; type WithModules< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags > = { - [P in keyof M as ExcludeMappedString

]: { - [C in keyof M[P] as ExcludeMappedString]: CommandSignature; - }; + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; }; type WithFunctions< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags > = { - [P in keyof F as ExcludeMappedString

]: { - [FF in keyof F[P] as ExcludeMappedString]: CommandSignature; - }; + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; }; type WithScripts< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags > = { - [P in keyof S as ExcludeMappedString

]: CommandSignature; + [P in keyof S]: CommandSignature; }; export type RedisClientMultiCommandType< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = RedisClientMultiCommand & WithCommands & WithModules & WithFunctions & WithScripts; - -type InstantiableRedisMultiCommand< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = new (...args: ConstructorParameters) => RedisClientMultiCommandType; + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = ( + RedisClientMultiCommand & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); export type RedisClientMultiExecutor = ( - queue: Array, - selectedDB?: number, - chainId?: symbol -) => Promise>; - -export default class RedisClientMultiCommand { - static extend< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(extensions?: RedisExtensions): InstantiableRedisMultiCommand { - return attachExtensions({ - BaseClass: RedisClientMultiCommand, - modulesExecutor: RedisClientMultiCommand.prototype.commandsExecutor, - modules: extensions?.modules, - functionsExecutor: RedisClientMultiCommand.prototype.functionsExecutor, - functions: extensions?.functions, - scriptsExecutor: RedisClientMultiCommand.prototype.scriptsExecutor, - scripts: extensions?.scripts - }); - } - - readonly #multi = new RedisMultiCommand(); - readonly #executor: RedisClientMultiExecutor; - readonly v4: Record = {}; - #selectedDB?: number; - - constructor(executor: RedisClientMultiExecutor, legacyMode = false) { - this.#executor = executor; - if (legacyMode) { - this.#legacyMode(); - } - } - - #legacyMode(): void { - this.v4.addCommand = this.addCommand.bind(this); - (this as any).addCommand = (...args: Array): this => { - this.#multi.addCommand(transformLegacyCommandArguments(args)); - return this; - }; - this.v4.exec = this.exec.bind(this); - (this as any).exec = (callback?: (err: Error | null, replies?: Array) => unknown): void => { - this.v4.exec() - .then((reply: Array) => { - if (!callback) return; - - callback(null, reply); - }) - .catch((err: Error) => { - if (!callback) { - // this.emit('error', err); - return; - } - - callback(err); - }); - }; - - for (const [ name, command ] of Object.entries(COMMANDS as RedisCommands)) { - this.#defineLegacyCommand(name, command); - (this as any)[name.toLowerCase()] ??= (this as any)[name]; - } - } - - #defineLegacyCommand(this: any, name: string, command?: RedisCommand): void { - this.v4[name] = this[name].bind(this.v4); - this[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? - (...args: Array) => { - this.#multi.addCommand( - [name, ...transformLegacyCommandArguments(args)], - command.transformReply - ); - return this; - } : - (...args: Array) => this.addCommand(name, ...args); - } - - commandsExecutor(command: RedisCommand, args: Array): this { - return this.addCommand( - command.transformArguments(...args), - command.transformReply - ); - } - - SELECT(db: number, transformReply?: RedisCommand['transformReply']): this { - this.#selectedDB = db; - return this.addCommand(['SELECT', db.toString()], transformReply); - } - - select = this.SELECT; - - addCommand(args: RedisCommandArguments, transformReply?: RedisCommand['transformReply']): this { - this.#multi.addCommand(args, transformReply); - return this; - } - - functionsExecutor(fn: RedisFunction, args: Array, name: string): this { - this.#multi.addFunction(name, fn, args); - return this; - } - - scriptsExecutor(script: RedisScript, args: Array): this { - this.#multi.addScript(script, args); - return this; - } - - async exec(execAsPipeline = false): Promise> { - if (execAsPipeline) { - return this.execAsPipeline(); - } - - return this.#multi.handleExecReplies( - await this.#executor( - this.#multi.queue, - this.#selectedDB, - RedisMultiCommand.generateChainId() - ) - ); - } - - EXEC = this.exec; - - async execAsPipeline(): Promise> { - if (this.#multi.queue.length === 0) return []; - - return this.#multi.transformReplies( - await this.#executor( - this.#multi.queue, - this.#selectedDB - ) - ); - } + queue: Array, + selectedDB?: number, + chainId?: symbol +) => Promise>; + +export default class RedisClientMultiCommand extends RedisMultiCommand { + static #createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: RedisClientMultiCommand) { + return this.addCommand( + command.transformArguments.apply(undefined, arguments as any), + transformReply + ); + }; + } + + static #createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: { self: RedisClientMultiCommand }) { + return this.self.addCommand( + command.transformArguments.apply(undefined, arguments as any), + transformReply + ); + }; + } + + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return function (this: { self: RedisClientMultiCommand }) { + const fnArgs = fn.transformArguments.apply(undefined, arguments as any), + args: CommandArguments = prefix.concat(fnArgs); + args.preserve = fnArgs.preserve; + return this.self.addCommand( + args, + transformReply + ); + }; + } + + static #createScriptCommand(script: RedisScript, resp: RespVersions) { + const transformReply = getTransformReply(script, resp); + return function (this: RedisClientMultiCommand) { + return this.addScript( + script, + script.transformArguments.apply(undefined, arguments as any), + transformReply + ); + }; + } + + static extend< + M extends RedisModules = Record, + F extends RedisFunctions = Record, + S extends RedisScripts = Record, + RESP extends RespVersions = 2, + FLAGS extends Flags = {} + >(config?: CommanderConfig) { + return attachConfig({ + BaseClass: RedisClientMultiCommand, + commands: COMMANDS, + createCommand: RedisClientMultiCommand.#createCommand, + createModuleCommand: RedisClientMultiCommand.#createModuleCommand, + createFunctionCommand: RedisClientMultiCommand.#createFunctionCommand, + createScriptCommand: RedisClientMultiCommand.#createScriptCommand, + config + }); + } + + // readonly #multi = new RedisMultiCommand(); + readonly #executor: RedisClientMultiExecutor; + // readonly v4: Record = {}; + #selectedDB?: number; + + constructor(executor: RedisClientMultiExecutor, legacyMode = false) { + super(); + this.#executor = executor; + // if (legacyMode) { + // this.#legacyMode(); + // } + } + + // #legacyMode(): void { + // this.v4.addCommand = this.addCommand.bind(this); + // (this as any).addCommand = (...args: Array): this => { + // this.#multi.addCommand(transformLegacyCommandArguments(args)); + // return this; + // }; + // this.v4.exec = this.exec.bind(this); + // (this as any).exec = (callback?: (err: Error | null, replies?: Array) => unknown): void => { + // this.v4.exec() + // .then((reply: Array) => { + // if (!callback) return; + + // callback(null, reply); + // }) + // .catch((err: Error) => { + // if (!callback) { + // // this.emit('error', err); + // return; + // } + + // callback(err); + // }); + // }; + + // for (const [name, command] of Object.entries(COMMANDS as RedisCommands)) { + // this.#defineLegacyCommand(name, command); + // (this as any)[name.toLowerCase()] ??= (this as any)[name]; + // } + // } + + // #defineLegacyCommand(this: any, name: string, command?: RedisCommand): void { + // this.v4[name] = this[name].bind(this.v4); + // this[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? + // (...args: Array) => { + // this.#multi.addCommand( + // [name, ...transformLegacyCommandArguments(args)], + // command.transformReply + // ); + // return this; + // } : + // (...args: Array) => this.addCommand(name, ...args); + // } + + SELECT(db: number, transformReply?: TransformReply): this { + this.#selectedDB = db; + return this.addCommand(['SELECT', db.toString()], transformReply); + } + + select = this.SELECT; + + async exec(execAsPipeline = false): Promise { + if (execAsPipeline) return this.execAsPipeline(); + + return this.handleExecReplies( + await this.#executor( + this.queue, + this.#selectedDB, + RedisMultiCommand.generateChainId() + ) + ) as REPLIES; + } + + EXEC = this.exec; + + async execAsPipeline(): Promise { + if (this.queue.length === 0) return [] as REPLIES; + + return this.transformReplies( + await this.#executor( + this.queue, + this.#selectedDB + ) + ) as REPLIES; + } } - -attachCommands({ - BaseClass: RedisClientMultiCommand, - commands: COMMANDS, - executor: RedisClientMultiCommand.prototype.commandsExecutor -}); diff --git a/packages/client/lib/client/pub-sub.ts b/packages/client/lib/client/pub-sub.ts index 8efc9d8a2e2..ec0639c7ee3 100644 --- a/packages/client/lib/client/pub-sub.ts +++ b/packages/client/lib/client/pub-sub.ts @@ -1,37 +1,37 @@ -import { RedisCommandArgument } from "../commands"; +import { RedisArgument } from "../RESP/types"; export enum PubSubType { - CHANNELS = 'CHANNELS', - PATTERNS = 'PATTERNS', - SHARDED = 'SHARDED' + CHANNELS = 'CHANNELS', + PATTERNS = 'PATTERNS', + SHARDED = 'SHARDED' } const COMMANDS = { - [PubSubType.CHANNELS]: { - subscribe: Buffer.from('subscribe'), - unsubscribe: Buffer.from('unsubscribe'), - message: Buffer.from('message') - }, - [PubSubType.PATTERNS]: { - subscribe: Buffer.from('psubscribe'), - unsubscribe: Buffer.from('punsubscribe'), - message: Buffer.from('pmessage') - }, - [PubSubType.SHARDED]: { - subscribe: Buffer.from('ssubscribe'), - unsubscribe: Buffer.from('sunsubscribe'), - message: Buffer.from('smessage') - } + [PubSubType.CHANNELS]: { + subscribe: Buffer.from('subscribe'), + unsubscribe: Buffer.from('unsubscribe'), + message: Buffer.from('message') + }, + [PubSubType.PATTERNS]: { + subscribe: Buffer.from('psubscribe'), + unsubscribe: Buffer.from('punsubscribe'), + message: Buffer.from('pmessage') + }, + [PubSubType.SHARDED]: { + subscribe: Buffer.from('ssubscribe'), + unsubscribe: Buffer.from('sunsubscribe'), + message: Buffer.from('smessage') + } }; export type PubSubListener< - RETURN_BUFFERS extends boolean = false + RETURN_BUFFERS extends boolean = false > = (message: T, channel: T) => unknown; export interface ChannelListeners { - unsubscribing: boolean; - buffers: Set>; - strings: Set>; + unsubscribing: boolean; + buffers: Set>; + strings: Set>; } export type PubSubTypeListeners = Map; @@ -39,370 +39,370 @@ export type PubSubTypeListeners = Map; type Listeners = Record; export type PubSubCommand = ReturnType< - typeof PubSub.prototype.subscribe | - typeof PubSub.prototype.unsubscribe | - typeof PubSub.prototype.extendTypeListeners + typeof PubSub.prototype.subscribe | + typeof PubSub.prototype.unsubscribe | + typeof PubSub.prototype.extendTypeListeners >; export class PubSub { - static isStatusReply(reply: Array): boolean { - return ( - COMMANDS[PubSubType.CHANNELS].subscribe.equals(reply[0]) || - COMMANDS[PubSubType.CHANNELS].unsubscribe.equals(reply[0]) || - COMMANDS[PubSubType.PATTERNS].subscribe.equals(reply[0]) || - COMMANDS[PubSubType.PATTERNS].unsubscribe.equals(reply[0]) || - COMMANDS[PubSubType.SHARDED].subscribe.equals(reply[0]) - ); - } - - static isShardedUnsubscribe(reply: Array): boolean { - return COMMANDS[PubSubType.SHARDED].unsubscribe.equals(reply[0]); - } - - static #channelsArray(channels: string | Array) { - return (Array.isArray(channels) ? channels : [channels]); + static isStatusReply(reply: Array): boolean { + return ( + COMMANDS[PubSubType.CHANNELS].subscribe.equals(reply[0]) || + COMMANDS[PubSubType.CHANNELS].unsubscribe.equals(reply[0]) || + COMMANDS[PubSubType.PATTERNS].subscribe.equals(reply[0]) || + COMMANDS[PubSubType.PATTERNS].unsubscribe.equals(reply[0]) || + COMMANDS[PubSubType.SHARDED].subscribe.equals(reply[0]) + ); + } + + static isShardedUnsubscribe(reply: Array): boolean { + return COMMANDS[PubSubType.SHARDED].unsubscribe.equals(reply[0]); + } + + static #channelsArray(channels: string | Array) { + return (Array.isArray(channels) ? channels : [channels]); + } + + static #listenersSet( + listeners: ChannelListeners, + returnBuffers?: T + ) { + return (returnBuffers ? listeners.buffers : listeners.strings); + } + + #subscribing = 0; + + #isActive = false; + + get isActive() { + return this.#isActive; + } + + #listeners: Listeners = { + [PubSubType.CHANNELS]: new Map(), + [PubSubType.PATTERNS]: new Map(), + [PubSubType.SHARDED]: new Map() + }; + + subscribe( + type: PubSubType, + channels: string | Array, + listener: PubSubListener, + returnBuffers?: T + ) { + const args: Array = [COMMANDS[type].subscribe], + channelsArray = PubSub.#channelsArray(channels); + for (const channel of channelsArray) { + let channelListeners = this.#listeners[type].get(channel); + if (!channelListeners || channelListeners.unsubscribing) { + args.push(channel); + } } - static #listenersSet( - listeners: ChannelListeners, - returnBuffers?: T - ) { - return (returnBuffers ? listeners.buffers : listeners.strings); + if (args.length === 1) { + // all channels are already subscribed, add listeners without issuing a command + for (const channel of channelsArray) { + PubSub.#listenersSet( + this.#listeners[type].get(channel)!, + returnBuffers + ).add(listener); + } + return; } - #subscribing = 0; - - #isActive = false; - - get isActive() { - return this.#isActive; - } - - #listeners: Listeners = { - [PubSubType.CHANNELS]: new Map(), - [PubSubType.PATTERNS]: new Map(), - [PubSubType.SHARDED]: new Map() - }; - - subscribe( - type: PubSubType, - channels: string | Array, - listener: PubSubListener, - returnBuffers?: T - ) { - const args: Array = [COMMANDS[type].subscribe], - channelsArray = PubSub.#channelsArray(channels); + this.#isActive = true; + this.#subscribing++; + return { + args, + channelsCounter: args.length - 1, + resolve: () => { + this.#subscribing--; for (const channel of channelsArray) { - let channelListeners = this.#listeners[type].get(channel); - if (!channelListeners || channelListeners.unsubscribing) { - args.push(channel); - } - } + let listeners = this.#listeners[type].get(channel); + if (!listeners) { + listeners = { + unsubscribing: false, + buffers: new Set(), + strings: new Set() + }; + this.#listeners[type].set(channel, listeners); + } - if (args.length === 1) { - // all channels are already subscribed, add listeners without issuing a command - for (const channel of channelsArray) { - PubSub.#listenersSet( - this.#listeners[type].get(channel)!, - returnBuffers - ).add(listener); - } - return; + PubSub.#listenersSet(listeners, returnBuffers).add(listener); } - - this.#isActive = true; - this.#subscribing++; - return { - args, - channelsCounter: args.length - 1, - resolve: () => { - this.#subscribing--; - for (const channel of channelsArray) { - let listeners = this.#listeners[type].get(channel); - if (!listeners) { - listeners = { - unsubscribing: false, - buffers: new Set(), - strings: new Set() - }; - this.#listeners[type].set(channel, listeners); - } - - PubSub.#listenersSet(listeners, returnBuffers).add(listener); - } - }, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; + }, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; + } + + extendChannelListeners( + type: PubSubType, + channel: string, + listeners: ChannelListeners + ) { + if (!this.#extendChannelListeners(type, channel, listeners)) return; + + this.#isActive = true; + this.#subscribing++; + return { + args: [ + COMMANDS[type].subscribe, + channel + ], + channelsCounter: 1, + resolve: () => this.#subscribing--, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; + } + + #extendChannelListeners( + type: PubSubType, + channel: string, + listeners: ChannelListeners + ) { + const existingListeners = this.#listeners[type].get(channel); + if (!existingListeners) { + this.#listeners[type].set(channel, listeners); + return true; } - extendChannelListeners( - type: PubSubType, - channel: string, - listeners: ChannelListeners - ) { - if (!this.#extendChannelListeners(type, channel, listeners)) return; - - this.#isActive = true; - this.#subscribing++; - return { - args: [ - COMMANDS[type].subscribe, - channel - ], - channelsCounter: 1, - resolve: () => this.#subscribing--, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; + for (const listener of listeners.buffers) { + existingListeners.buffers.add(listener); } - #extendChannelListeners( - type: PubSubType, - channel: string, - listeners: ChannelListeners - ) { - const existingListeners = this.#listeners[type].get(channel); - if (!existingListeners) { - this.#listeners[type].set(channel, listeners); - return true; - } - - for (const listener of listeners.buffers) { - existingListeners.buffers.add(listener); - } - - for (const listener of listeners.strings) { - existingListeners.strings.add(listener); - } - - return false; + for (const listener of listeners.strings) { + existingListeners.strings.add(listener); } - extendTypeListeners(type: PubSubType, listeners: PubSubTypeListeners) { - const args: Array = [COMMANDS[type].subscribe]; - for (const [channel, channelListeners] of listeners) { - if (this.#extendChannelListeners(type, channel, channelListeners)) { - args.push(channel); - } - } + return false; + } - if (args.length === 1) return; - - this.#isActive = true; - this.#subscribing++; - return { - args, - channelsCounter: args.length - 1, - resolve: () => this.#subscribing--, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; + extendTypeListeners(type: PubSubType, listeners: PubSubTypeListeners) { + const args: Array = [COMMANDS[type].subscribe]; + for (const [channel, channelListeners] of listeners) { + if (this.#extendChannelListeners(type, channel, channelListeners)) { + args.push(channel); + } } - unsubscribe( - type: PubSubType, - channels?: string | Array, - listener?: PubSubListener, - returnBuffers?: T - ) { - const listeners = this.#listeners[type]; - if (!channels) { - return this.#unsubscribeCommand( - [COMMANDS[type].unsubscribe], - // cannot use `this.#subscribed` because there might be some `SUBSCRIBE` commands in the queue - // cannot use `this.#subscribed + this.#subscribing` because some `SUBSCRIBE` commands might fail - NaN, - () => listeners.clear() - ); - } + if (args.length === 1) return; - const channelsArray = PubSub.#channelsArray(channels); - if (!listener) { - return this.#unsubscribeCommand( - [COMMANDS[type].unsubscribe, ...channelsArray], - channelsArray.length, - () => { - for (const channel of channelsArray) { - listeners.delete(channel); - } - } - ); - } + this.#isActive = true; + this.#subscribing++; + return { + args, + channelsCounter: args.length - 1, + resolve: () => this.#subscribing--, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; + } + + unsubscribe( + type: PubSubType, + channels?: string | Array, + listener?: PubSubListener, + returnBuffers?: T + ) { + const listeners = this.#listeners[type]; + if (!channels) { + return this.#unsubscribeCommand( + [COMMANDS[type].unsubscribe], + // cannot use `this.#subscribed` because there might be some `SUBSCRIBE` commands in the queue + // cannot use `this.#subscribed + this.#subscribing` because some `SUBSCRIBE` commands might fail + NaN, + () => listeners.clear() + ); + } - const args: Array = [COMMANDS[type].unsubscribe]; - for (const channel of channelsArray) { - const sets = listeners.get(channel); - if (sets) { - let current, - other; - if (returnBuffers) { - current = sets.buffers; - other = sets.strings; - } else { - current = sets.strings; - other = sets.buffers; - } - - const currentSize = current.has(listener) ? current.size - 1 : current.size; - if (currentSize !== 0 || other.size !== 0) continue; - sets.unsubscribing = true; - } - - args.push(channel); + const channelsArray = PubSub.#channelsArray(channels); + if (!listener) { + return this.#unsubscribeCommand( + [COMMANDS[type].unsubscribe, ...channelsArray], + channelsArray.length, + () => { + for (const channel of channelsArray) { + listeners.delete(channel); + } } + ); + } - if (args.length === 1) { - // all channels has other listeners, - // delete the listeners without issuing a command - for (const channel of channelsArray) { - PubSub.#listenersSet( - listeners.get(channel)!, - returnBuffers - ).delete(listener); - } - return; + const args: Array = [COMMANDS[type].unsubscribe]; + for (const channel of channelsArray) { + const sets = listeners.get(channel); + if (sets) { + let current, + other; + if (returnBuffers) { + current = sets.buffers; + other = sets.strings; + } else { + current = sets.strings; + other = sets.buffers; } - return this.#unsubscribeCommand( - args, - args.length - 1, - () => { - for (const channel of channelsArray) { - const sets = listeners.get(channel); - if (!sets) continue; - - (returnBuffers ? sets.buffers : sets.strings).delete(listener); - if (sets.buffers.size === 0 && sets.strings.size === 0) { - listeners.delete(channel); - } - } - } - ); - } + const currentSize = current.has(listener) ? current.size - 1 : current.size; + if (currentSize !== 0 || other.size !== 0) continue; + sets.unsubscribing = true; + } - #unsubscribeCommand( - args: Array, - channelsCounter: number, - removeListeners: () => void - ) { - return { - args, - channelsCounter, - resolve: () => { - removeListeners(); - this.#updateIsActive(); - }, - reject: undefined // use the same structure as `subscribe` - }; + args.push(channel); } - #updateIsActive() { - this.#isActive = ( - this.#listeners[PubSubType.CHANNELS].size !== 0 || - this.#listeners[PubSubType.PATTERNS].size !== 0 || - this.#listeners[PubSubType.CHANNELS].size !== 0 || - this.#subscribing !== 0 - ); + if (args.length === 1) { + // all channels has other listeners, + // delete the listeners without issuing a command + for (const channel of channelsArray) { + PubSub.#listenersSet( + listeners.get(channel)!, + returnBuffers + ).delete(listener); + } + return; } - reset() { - this.#isActive = false; - this.#subscribing = 0; - } + return this.#unsubscribeCommand( + args, + args.length - 1, + () => { + for (const channel of channelsArray) { + const sets = listeners.get(channel); + if (!sets) continue; - resubscribe(): Array { - const commands = []; - for (const [type, listeners] of Object.entries(this.#listeners)) { - if (!listeners.size) continue; - - this.#isActive = true; - this.#subscribing++; - const callback = () => this.#subscribing--; - commands.push({ - args: [ - COMMANDS[type as PubSubType].subscribe, - ...listeners.keys() - ], - channelsCounter: listeners.size, - resolve: callback, - reject: callback - }); + (returnBuffers ? sets.buffers : sets.strings).delete(listener); + if (sets.buffers.size === 0 && sets.strings.size === 0) { + listeners.delete(channel); + } } - - return commands; + } + ); + } + + #unsubscribeCommand( + args: Array, + channelsCounter: number, + removeListeners: () => void + ) { + return { + args, + channelsCounter, + resolve: () => { + removeListeners(); + this.#updateIsActive(); + }, + reject: undefined // use the same structure as `subscribe` + }; + } + + #updateIsActive() { + this.#isActive = ( + this.#listeners[PubSubType.CHANNELS].size !== 0 || + this.#listeners[PubSubType.PATTERNS].size !== 0 || + this.#listeners[PubSubType.CHANNELS].size !== 0 || + this.#subscribing !== 0 + ); + } + + reset() { + this.#isActive = false; + this.#subscribing = 0; + } + + resubscribe(): Array { + const commands = []; + for (const [type, listeners] of Object.entries(this.#listeners)) { + if (!listeners.size) continue; + + this.#isActive = true; + this.#subscribing++; + const callback = () => this.#subscribing--; + commands.push({ + args: [ + COMMANDS[type as PubSubType].subscribe, + ...listeners.keys() + ], + channelsCounter: listeners.size, + resolve: callback, + reject: callback + }); } - handleMessageReply(reply: Array): boolean { - if (COMMANDS[PubSubType.CHANNELS].message.equals(reply[0])) { - this.#emitPubSubMessage( - PubSubType.CHANNELS, - reply[2], - reply[1] - ); - return true; - } else if (COMMANDS[PubSubType.PATTERNS].message.equals(reply[0])) { - this.#emitPubSubMessage( - PubSubType.PATTERNS, - reply[3], - reply[2], - reply[1] - ); - return true; - } else if (COMMANDS[PubSubType.SHARDED].message.equals(reply[0])) { - this.#emitPubSubMessage( - PubSubType.SHARDED, - reply[2], - reply[1] - ); - return true; - } - - return false; + return commands; + } + + handleMessageReply(reply: Array): boolean { + if (COMMANDS[PubSubType.CHANNELS].message.equals(reply[0])) { + this.#emitPubSubMessage( + PubSubType.CHANNELS, + reply[2], + reply[1] + ); + return true; + } else if (COMMANDS[PubSubType.PATTERNS].message.equals(reply[0])) { + this.#emitPubSubMessage( + PubSubType.PATTERNS, + reply[3], + reply[2], + reply[1] + ); + return true; + } else if (COMMANDS[PubSubType.SHARDED].message.equals(reply[0])) { + this.#emitPubSubMessage( + PubSubType.SHARDED, + reply[2], + reply[1] + ); + return true; } - removeShardedListeners(channel: string): ChannelListeners { - const listeners = this.#listeners[PubSubType.SHARDED].get(channel)!; - this.#listeners[PubSubType.SHARDED].delete(channel); - this.#updateIsActive(); - return listeners; + return false; + } + + removeShardedListeners(channel: string): ChannelListeners { + const listeners = this.#listeners[PubSubType.SHARDED].get(channel)!; + this.#listeners[PubSubType.SHARDED].delete(channel); + this.#updateIsActive(); + return listeners; + } + + #emitPubSubMessage( + type: PubSubType, + message: Buffer, + channel: Buffer, + pattern?: Buffer + ): void { + const keyString = (pattern ?? channel).toString(), + listeners = this.#listeners[type].get(keyString); + + if (!listeners) return; + + for (const listener of listeners.buffers) { + listener(message, channel); } - - #emitPubSubMessage( - type: PubSubType, - message: Buffer, - channel: Buffer, - pattern?: Buffer - ): void { - const keyString = (pattern ?? channel).toString(), - listeners = this.#listeners[type].get(keyString); - - if (!listeners) return; - - for (const listener of listeners.buffers) { - listener(message, channel); - } - if (!listeners.strings.size) return; + if (!listeners.strings.size) return; - const channelString = pattern ? channel.toString() : keyString, - messageString = channelString === '__redis__:invalidate' ? - // https://github.com/redis/redis/pull/7469 - // https://github.com/redis/redis/issues/7463 - (message === null ? null : (message as any as Array).map(x => x.toString())) as any : - message.toString(); - for (const listener of listeners.strings) { - listener(messageString, channelString); - } + const channelString = pattern ? channel.toString() : keyString, + messageString = channelString === '__redis__:invalidate' ? + // https://github.com/redis/redis/pull/7469 + // https://github.com/redis/redis/issues/7463 + (message === null ? null : (message as any as Array).map(x => x.toString())) as any : + message.toString(); + for (const listener of listeners.strings) { + listener(messageString, channelString); } + } - getTypeListeners(type: PubSubType): PubSubTypeListeners { - return this.#listeners[type]; - } + getTypeListeners(type: PubSubType): PubSubTypeListeners { + return this.#listeners[type]; + } } diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index ac3b7f5bf3b..a88dc46d232 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -1,309 +1,309 @@ import { EventEmitter } from 'events'; import * as net from 'net'; import * as tls from 'tls'; -import { RedisCommandArguments } from '../commands'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError, ReconnectStrategyError } from '../errors'; import { promiseTimeout } from '../utils'; +import { RedisArgument } from '../RESP/types'; export interface RedisSocketCommonOptions { - /** - * Connection Timeout (in milliseconds) - */ - connectTimeout?: number; - /** - * Toggle [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) - */ - noDelay?: boolean; - /** - * Toggle [`keep-alive`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) - */ - keepAlive?: number | false; - /** - * When the socket closes unexpectedly (without calling `.quit()`/`.disconnect()`), the client uses `reconnectStrategy` to decide what to do. The following values are supported: - * 1. `false` -> do not reconnect, close the client and flush the command queue. - * 2. `number` -> wait for `X` milliseconds before reconnecting. - * 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. - * Defaults to `retries => Math.min(retries * 50, 500)` - */ - reconnectStrategy?: false | number | ((retries: number, cause: Error) => false | Error | number); + /** + * Connection Timeout (in milliseconds) + */ + connectTimeout?: number; + /** + * Toggle [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) + */ + noDelay?: boolean; + /** + * Toggle [`keep-alive`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) + */ + keepAlive?: number | false; + /** + * When the socket closes unexpectedly (without calling `.quit()`/`.disconnect()`), the client uses `reconnectStrategy` to decide what to do. The following values are supported: + * 1. `false` -> do not reconnect, close the client and flush the command queue. + * 2. `number` -> wait for `X` milliseconds before reconnecting. + * 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. + * Defaults to `retries => Math.min(retries * 50, 500)` + */ + reconnectStrategy?: false | number | ((retries: number, cause: Error) => false | Error | number); } type RedisNetSocketOptions = Partial & { - tls?: false; + tls?: false; }; export interface RedisTlsSocketOptions extends tls.ConnectionOptions { - tls: true; + tls: true; } export type RedisSocketOptions = RedisSocketCommonOptions & (RedisNetSocketOptions | RedisTlsSocketOptions); interface CreateSocketReturn { - connectEvent: string; - socket: T; + connectEvent: string; + socket: T; } export type RedisSocketInitiator = () => Promise; export default class RedisSocket extends EventEmitter { - static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { - options ??= {}; - if (!(options as net.IpcSocketConnectOpts).path) { - (options as net.TcpSocketConnectOpts).port ??= 6379; - (options as net.TcpSocketConnectOpts).host ??= 'localhost'; - } - - options.connectTimeout ??= 5000; - options.keepAlive ??= 5000; - options.noDelay ??= true; - - return options; + static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { + options ??= {}; + if (!(options as net.IpcSocketConnectOpts).path) { + (options as net.TcpSocketConnectOpts).port ??= 6379; + (options as net.TcpSocketConnectOpts).host ??= 'localhost'; } - static #isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { - return (options as RedisTlsSocketOptions).tls === true; - } + options.connectTimeout ??= 5000; + options.keepAlive ??= 5000; + options.noDelay ??= true; - readonly #initiator: RedisSocketInitiator; + return options; + } - readonly #options: RedisSocketOptions; + static #isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { + return (options as RedisTlsSocketOptions).tls === true; + } - #socket?: net.Socket | tls.TLSSocket; + readonly #initiator: RedisSocketInitiator; - #isOpen = false; + readonly #options: RedisSocketOptions; - get isOpen(): boolean { - return this.#isOpen; - } + #socket?: net.Socket | tls.TLSSocket; - #isReady = false; + #isOpen = false; - get isReady(): boolean { - return this.#isReady; - } + get isOpen(): boolean { + return this.#isOpen; + } - // `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used - // https://nodejs.org/api/stream.html#stream_writable_writableneeddrain - #writableNeedDrain = false; + #isReady = false; - get writableNeedDrain(): boolean { - return this.#writableNeedDrain; - } + get isReady(): boolean { + return this.#isReady; + } - #isSocketUnrefed = false; + // `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used + // https://nodejs.org/api/stream.html#stream_writable_writableneeddrain + #writableNeedDrain = false; - constructor(initiator: RedisSocketInitiator, options?: RedisSocketOptions) { - super(); + get writableNeedDrain(): boolean { + return this.#writableNeedDrain; + } - this.#initiator = initiator; - this.#options = RedisSocket.#initiateOptions(options); - } + #isSocketUnrefed = false; - #reconnectStrategy(retries: number, cause: Error) { - if (this.#options.reconnectStrategy === false) { - return false; - } else if (typeof this.#options.reconnectStrategy === 'number') { - return this.#options.reconnectStrategy; - } else if (this.#options.reconnectStrategy) { - try { - const retryIn = this.#options.reconnectStrategy(retries, cause); - if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { - throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); - } - - return retryIn; - } catch (err) { - this.emit('error', err); - } - } + constructor(initiator: RedisSocketInitiator, options?: RedisSocketOptions) { + super(); - return Math.min(retries * 50, 500); - } + this.#initiator = initiator; + this.#options = RedisSocket.#initiateOptions(options); + } - #shouldReconnect(retries: number, cause: Error) { - const retryIn = this.#reconnectStrategy(retries, cause); - if (retryIn === false) { - this.#isOpen = false; - this.emit('error', cause); - return cause; - } else if (retryIn instanceof Error) { - this.#isOpen = false; - this.emit('error', cause); - return new ReconnectStrategyError(retryIn, cause); + #reconnectStrategy(retries: number, cause: Error) { + if (this.#options.reconnectStrategy === false) { + return false; + } else if (typeof this.#options.reconnectStrategy === 'number') { + return this.#options.reconnectStrategy; + } else if (this.#options.reconnectStrategy) { + try { + const retryIn = this.#options.reconnectStrategy(retries, cause); + if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { + throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); } return retryIn; + } catch (err) { + this.emit('error', err); + } } - async connect(): Promise { - if (this.#isOpen) { - throw new Error('Socket already opened'); - } - - this.#isOpen = true; - return this.#connect(); - } - - async #connect(): Promise { - let retries = 0; - do { - try { - this.#socket = await this.#createSocket(); - this.#writableNeedDrain = false; - this.emit('connect'); - - try { - await this.#initiator(); - } catch (err) { - this.#socket.destroy(); - this.#socket = undefined; - throw err; - } - this.#isReady = true; - this.emit('ready'); - } catch (err) { - const retryIn = this.#shouldReconnect(retries++, err as Error); - if (typeof retryIn !== 'number') { - throw retryIn; - } - - this.emit('error', err); - await promiseTimeout(retryIn); - this.emit('reconnecting'); - } - } while (this.#isOpen && !this.#isReady); + return Math.min(retries * 50, 500); + } + + #shouldReconnect(retries: number, cause: Error) { + const retryIn = this.#reconnectStrategy(retries, cause); + if (retryIn === false) { + this.#isOpen = false; + this.emit('error', cause); + return cause; + } else if (retryIn instanceof Error) { + this.#isOpen = false; + this.emit('error', cause); + return new ReconnectStrategyError(retryIn, cause); } - #createSocket(): Promise { - return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? - this.#createTlsSocket() : - this.#createNetSocket(); - - if (this.#options.connectTimeout) { - socket.setTimeout(this.#options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); - } - - if (this.#isSocketUnrefed) { - socket.unref(); - } - - socket - .setNoDelay(this.#options.noDelay) - .once('error', reject) - .once(connectEvent, () => { - socket - .setTimeout(0) - // https://github.com/nodejs/node/issues/31663 - .setKeepAlive(this.#options.keepAlive !== false, this.#options.keepAlive || 0) - .off('error', reject) - .once('error', (err: Error) => this.#onSocketError(err)) - .once('close', hadError => { - if (!hadError && this.#isOpen && this.#socket === socket) { - this.#onSocketError(new SocketClosedUnexpectedlyError()); - } - }) - .on('drain', () => { - this.#writableNeedDrain = false; - this.emit('drain'); - }) - .on('data', data => this.emit('data', data)); - - resolve(socket); - }); - }); - } + return retryIn; + } - #createNetSocket(): CreateSocketReturn { - return { - connectEvent: 'connect', - socket: net.connect(this.#options as net.NetConnectOpts) // TODO - }; + async connect(): Promise { + if (this.#isOpen) { + throw new Error('Socket already opened'); } - #createTlsSocket(): CreateSocketReturn { - return { - connectEvent: 'secureConnect', - socket: tls.connect(this.#options as tls.ConnectionOptions) // TODO - }; - } + this.#isOpen = true; + return this.#connect(); + } + + async #connect(): Promise { + let retries = 0; + do { + try { + this.#socket = await this.#createSocket(); + this.#writableNeedDrain = false; + this.emit('connect'); + + try { + await this.#initiator(); + } catch (err) { + this.#socket.destroy(); + this.#socket = undefined; + throw err; + } + this.#isReady = true; + this.emit('ready'); + } catch (err) { + const retryIn = this.#shouldReconnect(retries++, err as Error); + if (typeof retryIn !== 'number') { + throw retryIn; + } - #onSocketError(err: Error): void { - this.#isReady = false; this.emit('error', err); - - if (!this.#isOpen || typeof this.#shouldReconnect(0, err) !== 'number') return; - + await promiseTimeout(retryIn); this.emit('reconnecting'); - this.#connect().catch(() => { - // the error was already emitted, silently ignore it + } + } while (this.#isOpen && !this.#isReady); + } + + #createSocket(): Promise { + return new Promise((resolve, reject) => { + const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? + this.#createTlsSocket() : + this.#createNetSocket(); + + if (this.#options.connectTimeout) { + socket.setTimeout(this.#options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); + } + + if (this.#isSocketUnrefed) { + socket.unref(); + } + + socket + .setNoDelay(this.#options.noDelay) + .once('error', reject) + .once(connectEvent, () => { + socket + .setTimeout(0) + // https://github.com/nodejs/node/issues/31663 + .setKeepAlive(this.#options.keepAlive !== false, this.#options.keepAlive || 0) + .off('error', reject) + .once('error', (err: Error) => this.#onSocketError(err)) + .once('close', hadError => { + if (!hadError && this.#isReady && this.#socket === socket) { + this.#onSocketError(new SocketClosedUnexpectedlyError()); + } + }) + .on('drain', () => { + this.#writableNeedDrain = false; + this.emit('drain'); + }) + .on('data', data => this.emit('data', data)); + + resolve(socket); }); + }); + } + + #createNetSocket(): CreateSocketReturn { + return { + connectEvent: 'connect', + socket: net.connect(this.#options as net.NetConnectOpts) // TODO + }; + } + + #createTlsSocket(): CreateSocketReturn { + return { + connectEvent: 'secureConnect', + socket: tls.connect(this.#options as tls.ConnectionOptions) // TODO + }; + } + + #onSocketError(err: Error): void { + this.#isReady = false; + this.emit('error', err); + + if (!this.#isOpen || typeof this.#shouldReconnect(0, err) !== 'number') return; + + this.emit('reconnecting'); + this.#connect().catch(() => { + // the error was already emitted, silently ignore it + }); + } + + writeCommand(args: Array): void { + if (!this.#socket) { + throw new ClientClosedError(); } - writeCommand(args: RedisCommandArguments): void { - if (!this.#socket) { - throw new ClientClosedError(); - } - - for (const toWrite of args) { - this.#writableNeedDrain = !this.#socket.write(toWrite); - } + for (const toWrite of args) { + this.#writableNeedDrain = !this.#socket.write(toWrite); } + } - disconnect(): void { - if (!this.#isOpen) { - throw new ClientClosedError(); - } - - this.#isOpen = false; - this.#disconnect(); + disconnect(): void { + if (!this.#isOpen) { + throw new ClientClosedError(); } - #disconnect(): void { - this.#isReady = false; + this.#isOpen = false; + this.#disconnect(); + } - if (this.#socket) { - this.#socket.destroy(); - this.#socket = undefined; - } - - this.emit('end'); + #disconnect(): void { + this.#isReady = false; + + if (this.#socket) { + this.#socket.destroy(); + this.#socket = undefined; } - async quit(fn: () => Promise): Promise { - if (!this.#isOpen) { - throw new ClientClosedError(); - } + this.emit('end'); + } - this.#isOpen = false; - const reply = await fn(); - this.#disconnect(); - return reply; + async quit(fn: () => Promise): Promise { + if (!this.#isOpen) { + throw new ClientClosedError(); } - #isCorked = false; + this.#isOpen = false; + const reply = await fn(); + this.#disconnect(); + return reply; + } - cork(): void { - if (!this.#socket || this.#isCorked) { - return; - } + #isCorked = false; - this.#socket.cork(); - this.#isCorked = true; - - queueMicrotask(() => { - this.#socket?.uncork(); - this.#isCorked = false; - }); + cork(): void { + if (!this.#socket || this.#isCorked) { + return; } - ref(): void { - this.#isSocketUnrefed = false; - this.#socket?.ref(); - } + this.#socket.cork(); + this.#isCorked = true; - unref(): void { - this.#isSocketUnrefed = true; - this.#socket?.unref(); - } + queueMicrotask(() => { + this.#socket?.uncork(); + this.#isCorked = false; + }); + } + + ref(): void { + this.#isSocketUnrefed = false; + this.#socket?.ref(); + } + + unref(): void { + this.#isSocketUnrefed = true; + this.#socket?.unref(); + } } diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index b540c2fa85f..e94ad52002d 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -1,621 +1,618 @@ -import RedisClient, { InstantiableRedisClient, RedisClientType } from '../client'; import { RedisClusterClientOptions, RedisClusterOptions } from '.'; -import { RedisCommandArgument, RedisFunctions, RedisModules, RedisScripts } from '../commands'; import { RootNodesUnavailableError } from '../errors'; -import { ClusterSlotsNode } from '../commands/CLUSTER_SLOTS'; +import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; import { types } from 'util'; -import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; import { EventEmitter } from 'stream'; +import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; +import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; +// TODO: ?! // We need to use 'require', because it's not possible with Typescript to import // function that are exported as 'module.exports = function`, without esModuleInterop // set to true. const calculateSlot = require('cluster-key-slot'); interface NodeAddress { - host: string; - port: number; + host: string; + port: number; } export type NodeAddressMap = { - [address: string]: NodeAddress; + [address: string]: NodeAddress; } | ((address: string) => NodeAddress | undefined); type ValueOrPromise = T | Promise; type ClientOrPromise< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = ValueOrPromise>; + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions = 2 +> = ValueOrPromise>; export interface Node< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions > { - address: string; - client?: ClientOrPromise; + address: string; + client?: ClientOrPromise; } export interface ShardNode< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> extends Node { - id: string; - host: string; - port: number; - readonly: boolean; + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> extends Node { + host: string; + port: number; + readonly: boolean; } export interface MasterNode< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> extends ShardNode { - pubSubClient?: ClientOrPromise; + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> extends ShardNode { + pubSubClient?: ClientOrPromise; } export interface Shard< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions > { - master: MasterNode; - replicas?: Array>; - nodesIterator?: IterableIterator>; + master: MasterNode; + replicas?: Array>; + nodesIterator?: IterableIterator>; } type ShardWithReplicas< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = Shard & Required, 'replicas'>>; + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> = Shard & Required, 'replicas'>>; export type PubSubNode< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = Required>; + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> = Required>; type PubSubToResubscribe = Record< - PubSubType.CHANNELS | PubSubType.PATTERNS, - PubSubTypeListeners + PubSubType.CHANNELS | PubSubType.PATTERNS, + PubSubTypeListeners >; export type OnShardedChannelMovedError = ( - err: unknown, - channel: string, - listeners?: ChannelListeners + err: unknown, + channel: string, + listeners?: ChannelListeners ) => void; export default class RedisClusterSlots< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions > { - static #SLOTS = 16384; - - readonly #options: RedisClusterOptions; - readonly #Client: InstantiableRedisClient; - readonly #emit: EventEmitter['emit']; - slots = new Array>(RedisClusterSlots.#SLOTS); - shards = new Array>(); - masters = new Array>(); - replicas = new Array>(); - readonly nodeByAddress = new Map | ShardNode>(); - pubSubNode?: PubSubNode; - - #isOpen = false; - - get isOpen() { - return this.#isOpen; - } - - constructor( - options: RedisClusterOptions, - emit: EventEmitter['emit'] - ) { - this.#options = options; - this.#Client = RedisClient.extend(options); - this.#emit = emit; - } - - async connect() { - if (this.#isOpen) { - throw new Error('Cluster already open'); - } - - this.#isOpen = true; - try { - await this.#discoverWithRootNodes(); - } catch (err) { - this.#isOpen = false; - throw err; - } + private static _SLOTS = 16384; + + private readonly _options: RedisClusterOptions; + private readonly _clientFactory: ReturnType>; + private readonly _emit: EventEmitter['emit']; + slots = new Array>(RedisClusterSlots._SLOTS); + shards = new Array>(); + masters = new Array>(); + replicas = new Array>(); + readonly nodeByAddress = new Map | ShardNode>(); + pubSubNode?: PubSubNode; + + private _isOpen = false; + + get isOpen() { + return this._isOpen; + } + + constructor( + options: RedisClusterOptions, + emit: EventEmitter['emit'] + ) { + this._options = options; + this._clientFactory = RedisClient.factory(options); + this._emit = emit; + } + + async connect() { + if (this._isOpen) { + throw new Error('Cluster already open'); } - async #discoverWithRootNodes() { - let start = Math.floor(Math.random() * this.#options.rootNodes.length); - for (let i = start; i < this.#options.rootNodes.length; i++) { - if (await this.#discover(this.#options.rootNodes[i])) return; - } - - for (let i = 0; i < start; i++) { - if (await this.#discover(this.#options.rootNodes[i])) return; - } - - throw new RootNodesUnavailableError(); + this._isOpen = true; + try { + await this._discoverWithRootNodes(); + } catch (err) { + this._isOpen = false; + throw err; } + } - #resetSlots() { - this.slots = new Array(RedisClusterSlots.#SLOTS); - this.shards = []; - this.masters = []; - this.replicas = []; - this.#randomNodeIterator = undefined; + private async _discoverWithRootNodes() { + let start = Math.floor(Math.random() * this._options.rootNodes.length); + for (let i = start; i < this._options.rootNodes.length; i++) { + if (await this._discover(this._options.rootNodes[i])) return; } - async #discover(rootNode?: RedisClusterClientOptions) { - this.#resetSlots(); - const addressesInUse = new Set(); - - try { - const shards = await this.#getShards(rootNode), - promises: Array> = [], - eagerConnect = this.#options.minimizeConnections !== true; - for (const { from, to, master, replicas } of shards) { - const shard: Shard = { - master: this.#initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) - }; - - if (this.#options.useReplicas) { - shard.replicas = replicas.map(replica => - this.#initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises) - ); - } - - this.shards.push(shard); - - for (let i = from; i <= to; i++) { - this.slots[i] = shard; - } - } - - if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { - if (types.isPromise(this.pubSubNode.client)) { - promises.push( - this.pubSubNode.client.then(client => client.disconnect()) - ); - this.pubSubNode = undefined; - } else { - promises.push(this.pubSubNode.client.disconnect()); - - const channelsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.CHANNELS), - patternsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.PATTERNS); - - if (channelsListeners.size || patternsListeners.size) { - promises.push( - this.#initiatePubSubClient({ - [PubSubType.CHANNELS]: channelsListeners, - [PubSubType.PATTERNS]: patternsListeners - }) - ); - } - } - } - - for (const [address, node] of this.nodeByAddress.entries()) { - if (addressesInUse.has(address)) continue; - - if (node.client) { - promises.push( - this.#execOnNodeClient(node.client, client => client.disconnect()) - ); - } - - const { pubSubClient } = node as MasterNode; - if (pubSubClient) { - promises.push( - this.#execOnNodeClient(pubSubClient, client => client.disconnect()) - ); - } - - this.nodeByAddress.delete(address); - } - - await Promise.all(promises); - - return true; - } catch (err) { - this.#emit('error', err); - return false; - } + for (let i = 0; i < start; i++) { + if (await this._discover(this._options.rootNodes[i])) return; } - async #getShards(rootNode?: RedisClusterClientOptions) { - const client = new this.#Client( - this.#clientOptionsDefaults(rootNode, true) - ); - - client.on('error', err => this.#emit('error', err)); - - await client.connect(); + throw new RootNodesUnavailableError(); + } + + private _resetSlots() { + this.slots = new Array(RedisClusterSlots._SLOTS); + this.shards = []; + this.masters = []; + this.replicas = []; + this._randomNodeIterator = undefined; + } + + private async _discover(rootNode: RedisClusterClientOptions) { + this._resetSlots(); + const addressesInUse = new Set(); + + try { + const shards = await this._getShards(rootNode), + promises: Array> = [], + eagerConnect = this._options.minimizeConnections !== true; + + type a = typeof shards; + for (const { from, to, master, replicas } of shards) { + const shard: Shard = { + master: this._initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) + }; - try { - // using `CLUSTER SLOTS` and not `CLUSTER SHARDS` to support older versions - return await client.clusterSlots(); - } finally { - await client.disconnect(); + if (this._options.useReplicas) { + shard.replicas = replicas.map(replica => + this._initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises) + ); } - } - #getNodeAddress(address: string): NodeAddress | undefined { - switch (typeof this.#options.nodeAddressMap) { - case 'object': - return this.#options.nodeAddressMap[address]; + this.shards.push(shard); - case 'function': - return this.#options.nodeAddressMap(address); + for (let i = from; i <= to; i++) { + this.slots[i] = shard; } - } - - #clientOptionsDefaults( - options?: RedisClusterClientOptions, - disableReconnect?: boolean - ): RedisClusterClientOptions | undefined { - let result: RedisClusterClientOptions | undefined; - if (this.#options.defaults) { - let socket; - if (this.#options.defaults.socket) { - socket = options?.socket ? { - ...this.#options.defaults.socket, - ...options.socket - } : this.#options.defaults.socket; - } else { - socket = options?.socket; - } - - result = { - ...this.#options.defaults, - ...options, - socket - }; + } + + if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { + if (types.isPromise(this.pubSubNode.client)) { + promises.push( + this.pubSubNode.client.then(client => client.disconnect()) + ); + this.pubSubNode = undefined; } else { - result = options; - } - - if (disableReconnect) { - result ??= {}; - result.socket ??= {}; - result.socket.reconnectStrategy = false; + promises.push(this.pubSubNode.client.disconnect()); + + const channelsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.CHANNELS), + patternsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.PATTERNS); + + if (channelsListeners.size || patternsListeners.size) { + promises.push( + this._initiatePubSubClient({ + [PubSubType.CHANNELS]: channelsListeners, + [PubSubType.PATTERNS]: patternsListeners + }) + ); + } } + } - return result; - } + for (const [address, node] of this.nodeByAddress.entries()) { + if (addressesInUse.has(address)) continue; - #initiateSlotNode( - { id, ip, port }: ClusterSlotsNode, - readonly: boolean, - eagerConnent: boolean, - addressesInUse: Set, - promises: Array> - ) { - const address = `${ip}:${port}`; - addressesInUse.add(address); - - let node = this.nodeByAddress.get(address); - if (!node) { - node = { - id, - host: ip, - port, - address, - readonly, - client: undefined - }; - - if (eagerConnent) { - promises.push(this.#createNodeClient(node)); - } - - this.nodeByAddress.set(address, node); + if (node.client) { + promises.push( + this._execOnNodeClient(node.client, client => client.disconnect()) + ); } - (readonly ? this.replicas : this.masters).push(node); - - return node; - } + const { pubSubClient } = node as MasterNode; + if (pubSubClient) { + promises.push( + this._execOnNodeClient(pubSubClient, client => client.disconnect()) + ); + } - async #createClient( - node: ShardNode, - readonly = node.readonly - ) { - const client = new this.#Client( - this.#clientOptionsDefaults({ - socket: this.#getNodeAddress(node.address) ?? { - host: node.host, - port: node.port - }, - readonly - }) - ); - client.on('error', err => this.#emit('error', err)); + this.nodeByAddress.delete(address); + } - await client.connect(); + await Promise.all(promises); - return client; + return true; + } catch (err) { + this._emit('error', err); + return false; } + } - #createNodeClient(node: ShardNode) { - const promise = this.#createClient(node) - .then(client => { - node.client = client; - return client; - }) - .catch(err => { - node.client = undefined; - throw err; - }); - node.client = promise; - return promise; - } + private async _getShards(rootNode: RedisClusterClientOptions) { + const options = this._clientOptionsDefaults(rootNode)!; + options.socket ??= {}; + options.socket.reconnectStrategy = false; + options.RESP = this._options.RESP; - nodeClient(node: ShardNode) { - return node.client ?? this.#createNodeClient(node); - } + const client = RedisClient.factory(this._options)(options); + + client.on('error', err => this._emit('error', err)); - #runningRediscoverPromise?: Promise; + await client.connect(); - async rediscover(startWith: RedisClientType): Promise { - this.#runningRediscoverPromise ??= this.#rediscover(startWith) - .finally(() => this.#runningRediscoverPromise = undefined); - return this.#runningRediscoverPromise; + try { + // switch to `CLUSTER SHARDS` when Redis 7.0 will be the minimum supported version + return await client.clusterSlots(); + } finally { + await client.disconnect(); } + } - async #rediscover(startWith: RedisClientType): Promise { - if (await this.#discover(startWith.options)) return; + private _getNodeAddress(address: string): NodeAddress | undefined { + switch (typeof this._options.nodeAddressMap) { + case 'object': + return this._options.nodeAddressMap[address]; - return this.#discoverWithRootNodes(); + case 'function': + return this._options.nodeAddressMap(address); } - - quit(): Promise { - return this.#destroy(client => client.quit()); + } + + private _clientOptionsDefaults(options?: RedisClientOptions): RedisClientOptions | undefined { + if (!this._options.defaults) return options; + + let socket; + if (this._options.defaults.socket) { + socket = options?.socket ? { + ...this._options.defaults.socket, + ...options.socket + } : this._options.defaults.socket; + } else { + socket = options?.socket; } - disconnect(): Promise { - return this.#destroy(client => client.disconnect()); + return { + ...this._options.defaults, + ...options, + socket + }; + } + + private _initiateSlotNode( + slotAddress: NodeAddress, + readonly: boolean, + eagerConnent: boolean, + addressesInUse: Set, + promises: Array> + ) { + const address = `${slotAddress.host}:${slotAddress.port}`; + addressesInUse.add(address); + + let node = this.nodeByAddress.get(address); + if (!node) { + node = { + ...slotAddress, + address, + readonly, + client: undefined + }; + + if (eagerConnent) { + promises.push(this._createNodeClient(node)); + } + + this.nodeByAddress.set(address, node); } - async #destroy(fn: (client: RedisClientType) => Promise): Promise { - this.#isOpen = false; - - const promises = []; - for (const { master, replicas } of this.shards) { - if (master.client) { - promises.push( - this.#execOnNodeClient(master.client, fn) - ); - } - - if (master.pubSubClient) { - promises.push( - this.#execOnNodeClient(master.pubSubClient, fn) - ); - } - - if (replicas) { - for (const { client } of replicas) { - if (client) { - promises.push( - this.#execOnNodeClient(client, fn) - ); - } - } - } - } + (readonly ? this.replicas : this.masters).push(node); + + return node; + } + + private async _createClient( + node: ShardNode, + readonly = node.readonly + ) { + const client = this._clientFactory( + this._clientOptionsDefaults({ + socket: this._getNodeAddress(node.address) ?? { + host: node.host, + port: node.port + }, + readonly, + RESP: this._options.RESP + }) + ); + client.on('error', err => this._emit('error', err)); + + await client.connect(); + + return client; + } + + private _createNodeClient(node: ShardNode) { + const promise = this._createClient(node) + .then(client => { + node.client = client; + return client; + }) + .catch(err => { + node.client = undefined; + throw err; + }); + node.client = promise; + return promise; + } + + nodeClient(node: ShardNode) { + return node.client ?? this._createNodeClient(node); + } + + #runningRediscoverPromise?: Promise; + + async rediscover(startWith: RedisClientType): Promise { + this.#runningRediscoverPromise ??= this._rediscover(startWith) + .finally(() => this.#runningRediscoverPromise = undefined); + return this.#runningRediscoverPromise; + } + + private async _rediscover(startWith: RedisClientType): Promise { + if (await this._discover(startWith.options!)) return; + + return this._discoverWithRootNodes(); + } + + quit(): Promise { + return this._destroy(client => client.quit()); + } + + disconnect(): Promise { + return this._destroy(client => client.disconnect()); + } + + private async _destroy(fn: (client: RedisClientType) => Promise): Promise { + this._isOpen = false; + + const promises = []; + for (const { master, replicas } of this.shards) { + if (master.client) { + promises.push( + this._execOnNodeClient(master.client, fn) + ); + } - if (this.pubSubNode) { - promises.push(this.#execOnNodeClient(this.pubSubNode.client, fn)); - this.pubSubNode = undefined; + if (master.pubSubClient) { + promises.push( + this._execOnNodeClient(master.pubSubClient, fn) + ); + } + + if (replicas) { + for (const { client } of replicas) { + if (client) { + promises.push( + this._execOnNodeClient(client, fn) + ); + } } - - this.#resetSlots(); - this.nodeByAddress.clear(); - - await Promise.allSettled(promises); + } } - #execOnNodeClient( - client: ClientOrPromise, - fn: (client: RedisClientType) => Promise - ) { - return types.isPromise(client) ? - client.then(fn) : - fn(client); + if (this.pubSubNode) { + promises.push(this._execOnNodeClient(this.pubSubNode.client, fn)); + this.pubSubNode = undefined; } - getClient( - firstKey: RedisCommandArgument | undefined, - isReadonly: boolean | undefined - ): ClientOrPromise { - if (!firstKey) { - return this.nodeClient(this.getRandomNode()); - } - - const slotNumber = calculateSlot(firstKey); - if (!isReadonly) { - return this.nodeClient(this.slots[slotNumber].master); - } - - return this.nodeClient(this.getSlotRandomNode(slotNumber)); + this._resetSlots(); + this.nodeByAddress.clear(); + + await Promise.allSettled(promises); + } + + private _execOnNodeClient( + client: ClientOrPromise, + fn: (client: RedisClientType) => Promise + ) { + return types.isPromise(client) ? + client.then(fn) : + fn(client); + } + + getClient( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined + ): ClientOrPromise { + if (!firstKey) { + return this.nodeClient(this.getRandomNode()); } - *#iterateAllNodes() { - let i = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); - if (i < this.masters.length) { - do { - yield this.masters[i]; - } while (++i < this.masters.length); - - for (const replica of this.replicas) { - yield replica; - } - } else { - i -= this.masters.length; - do { - yield this.replicas[i]; - } while (++i < this.replicas.length); - } - - while (true) { - for (const master of this.masters) { - yield master; - } - - for (const replica of this.replicas) { - yield replica; - } - } + const slotNumber = calculateSlot(firstKey); + if (!isReadonly) { + return this.nodeClient(this.slots[slotNumber].master); } - #randomNodeIterator?: IterableIterator>; - - getRandomNode() { - this.#randomNodeIterator ??= this.#iterateAllNodes(); - return this.#randomNodeIterator.next().value as ShardNode; + return this.nodeClient(this.getSlotRandomNode(slotNumber)); + } + + private *_iterateAllNodes() { + let i = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); + if (i < this.masters.length) { + do { + yield this.masters[i]; + } while (++i < this.masters.length); + + for (const replica of this.replicas) { + yield replica; + } + } else { + i -= this.masters.length; + do { + yield this.replicas[i]; + } while (++i < this.replicas.length); } - *#slotNodesIterator(slot: ShardWithReplicas) { - let i = Math.floor(Math.random() * (1 + slot.replicas.length)); - if (i < slot.replicas.length) { - do { - yield slot.replicas[i]; - } while (++i < slot.replicas.length); - } + while (true) { + for (const master of this.masters) { + yield master; + } - while (true) { - yield slot.master; - - for (const replica of slot.replicas) { - yield replica; - } - } + for (const replica of this.replicas) { + yield replica; + } } + } - getSlotRandomNode(slotNumber: number) { - const slot = this.slots[slotNumber]; - if (!slot.replicas?.length) { - return slot.master; - } - - slot.nodesIterator ??= this.#slotNodesIterator(slot as ShardWithReplicas); - return slot.nodesIterator.next().value as ShardNode; - } + _randomNodeIterator?: IterableIterator>; - getMasterByAddress(address: string) { - const master = this.nodeByAddress.get(address); - if (!master) return; + getRandomNode() { + this._randomNodeIterator ??= this._iterateAllNodes(); + return this._randomNodeIterator.next().value as ShardNode; + } - return this.nodeClient(master); + private *_slotNodesIterator(slot: ShardWithReplicas) { + let i = Math.floor(Math.random() * (1 + slot.replicas.length)); + if (i < slot.replicas.length) { + do { + yield slot.replicas[i]; + } while (++i < slot.replicas.length); } - getPubSubClient() { - return this.pubSubNode ? - this.pubSubNode.client : - this.#initiatePubSubClient(); - } + while (true) { + yield slot.master; - async #initiatePubSubClient(toResubscribe?: PubSubToResubscribe) { - const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), - node = index < this.masters.length ? - this.masters[index] : - this.replicas[index - this.masters.length]; - - this.pubSubNode = { - address: node.address, - client: this.#createClient(node, true) - .then(async client => { - if (toResubscribe) { - await Promise.all([ - client.extendPubSubListeners(PubSubType.CHANNELS, toResubscribe[PubSubType.CHANNELS]), - client.extendPubSubListeners(PubSubType.PATTERNS, toResubscribe[PubSubType.PATTERNS]) - ]); - } - - this.pubSubNode!.client = client; - return client; - }) - .catch(err => { - this.pubSubNode = undefined; - throw err; - }) - }; - - return this.pubSubNode.client as Promise>; + for (const replica of slot.replicas) { + yield replica; + } } + } - async executeUnsubscribeCommand( - unsubscribe: (client: RedisClientType) => Promise - ): Promise { - const client = await this.getPubSubClient(); - await unsubscribe(client); - - if (!client.isPubSubActive) { - await client.disconnect(); - this.pubSubNode = undefined; - } + getSlotRandomNode(slotNumber: number) { + const slot = this.slots[slotNumber]; + if (!slot.replicas?.length) { + return slot.master; } - getShardedPubSubClient(channel: string) { - const { master } = this.slots[calculateSlot(channel)]; - return master.pubSubClient ?? this.#initiateShardedPubSubClient(master); + slot.nodesIterator ??= this._slotNodesIterator(slot as ShardWithReplicas); + return slot.nodesIterator.next().value as ShardNode; + } + + getMasterByAddress(address: string) { + const master = this.nodeByAddress.get(address); + if (!master) return; + + return this.nodeClient(master); + } + + getPubSubClient() { + return this.pubSubNode ? + this.pubSubNode.client : + this._initiatePubSubClient(); + } + + private async _initiatePubSubClient(toResubscribe?: PubSubToResubscribe) { + const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), + node = index < this.masters.length ? + this.masters[index] : + this.replicas[index - this.masters.length]; + + this.pubSubNode = { + address: node.address, + client: this._createClient(node, true) + .then(async client => { + if (toResubscribe) { + await Promise.all([ + client.extendPubSubListeners(PubSubType.CHANNELS, toResubscribe[PubSubType.CHANNELS]), + client.extendPubSubListeners(PubSubType.PATTERNS, toResubscribe[PubSubType.PATTERNS]) + ]); + } + + this.pubSubNode!.client = client; + return client; + }) + .catch(err => { + this.pubSubNode = undefined; + throw err; + }) + }; + + return this.pubSubNode.client as Promise>; + } + + async executeUnsubscribeCommand( + unsubscribe: (client: RedisClientType) => Promise + ): Promise { + const client = await this.getPubSubClient(); + await unsubscribe(client); + + if (!client.isPubSubActive) { + await client.disconnect(); + this.pubSubNode = undefined; } + } + + getShardedPubSubClient(channel: string) { + const { master } = this.slots[calculateSlot(channel)]; + return master.pubSubClient ?? this.#initiateShardedPubSubClient(master); + } + + #initiateShardedPubSubClient(master: MasterNode) { + const promise = this._createClient(master, true) + .then(client => { + client.on('server-sunsubscribe', async (channel, listeners) => { + try { + await this.rediscover(client); + const redirectTo = await this.getShardedPubSubClient(channel); + redirectTo.extendPubSubChannelListeners( + PubSubType.SHARDED, + channel, + listeners + ); + } catch (err) { + this._emit('sharded-shannel-moved-error', err, channel, listeners); + } + }); + + master.pubSubClient = client; + return client; + }) + .catch(err => { + master.pubSubClient = undefined; + throw err; + }); - #initiateShardedPubSubClient(master: MasterNode) { - const promise = this.#createClient(master, true) - .then(client => { - client.on('server-sunsubscribe', async (channel, listeners) => { - try { - await this.rediscover(client); - const redirectTo = await this.getShardedPubSubClient(channel); - redirectTo.extendPubSubChannelListeners( - PubSubType.SHARDED, - channel, - listeners - ); - } catch (err) { - this.#emit('sharded-shannel-moved-error', err, channel, listeners); - } - }); - - master.pubSubClient = client; - return client; - }) - .catch(err => { - master.pubSubClient = undefined; - throw err; - }); - - master.pubSubClient = promise; - - return promise; - } + master.pubSubClient = promise; + + return promise; + } - async executeShardedUnsubscribeCommand( - channel: string, - unsubscribe: (client: RedisClientType) => Promise - ): Promise { - const { master } = this.slots[calculateSlot(channel)]; - if (!master.pubSubClient) return Promise.resolve(); + async executeShardedUnsubscribeCommand( + channel: string, + unsubscribe: (client: RedisClientType) => Promise + ): Promise { + const { master } = this.slots[calculateSlot(channel)]; + if (!master.pubSubClient) return Promise.resolve(); - const client = await master.pubSubClient; - await unsubscribe(client); + const client = await master.pubSubClient; + await unsubscribe(client); - if (!client.isPubSubActive) { - await client.disconnect(); - master.pubSubClient = undefined; - } + if (!client.isPubSubActive) { + await client.disconnect(); + master.pubSubClient = undefined; } + } } diff --git a/packages/client/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts deleted file mode 100644 index 58fa651be1b..00000000000 --- a/packages/client/lib/cluster/commands.ts +++ /dev/null @@ -1,637 +0,0 @@ - -import * as APPEND from '../commands/APPEND'; -import * as BITCOUNT from '../commands/BITCOUNT'; -import * as BITFIELD_RO from '../commands/BITFIELD_RO'; -import * as BITFIELD from '../commands/BITFIELD'; -import * as BITOP from '../commands/BITOP'; -import * as BITPOS from '../commands/BITPOS'; -import * as BLMOVE from '../commands/BLMOVE'; -import * as BLMPOP from '../commands/BLMPOP'; -import * as BLPOP from '../commands/BLPOP'; -import * as BRPOP from '../commands/BRPOP'; -import * as BRPOPLPUSH from '../commands/BRPOPLPUSH'; -import * as BZMPOP from '../commands/BZMPOP'; -import * as BZPOPMAX from '../commands/BZPOPMAX'; -import * as BZPOPMIN from '../commands/BZPOPMIN'; -import * as COPY from '../commands/COPY'; -import * as DECR from '../commands/DECR'; -import * as DECRBY from '../commands/DECRBY'; -import * as DEL from '../commands/DEL'; -import * as DUMP from '../commands/DUMP'; -import * as EVAL_RO from '../commands/EVAL_RO'; -import * as EVAL from '../commands/EVAL'; -import * as EVALSHA_RO from '../commands/EVALSHA_RO'; -import * as EVALSHA from '../commands/EVALSHA'; -import * as EXISTS from '../commands/EXISTS'; -import * as EXPIRE from '../commands/EXPIRE'; -import * as EXPIREAT from '../commands/EXPIREAT'; -import * as EXPIRETIME from '../commands/EXPIRETIME'; -import * as FCALL_RO from '../commands/FCALL_RO'; -import * as FCALL from '../commands/FCALL'; -import * as GEOADD from '../commands/GEOADD'; -import * as GEODIST from '../commands/GEODIST'; -import * as GEOHASH from '../commands/GEOHASH'; -import * as GEOPOS from '../commands/GEOPOS'; -import * as GEORADIUS_RO_WITH from '../commands/GEORADIUS_RO_WITH'; -import * as GEORADIUS_RO from '../commands/GEORADIUS_RO'; -import * as GEORADIUS_WITH from '../commands/GEORADIUS_WITH'; -import * as GEORADIUS from '../commands/GEORADIUS'; -import * as GEORADIUSBYMEMBER_RO_WITH from '../commands/GEORADIUSBYMEMBER_RO_WITH'; -import * as GEORADIUSBYMEMBER_RO from '../commands/GEORADIUSBYMEMBER_RO'; -import * as GEORADIUSBYMEMBER_WITH from '../commands/GEORADIUSBYMEMBER_WITH'; -import * as GEORADIUSBYMEMBER from '../commands/GEORADIUSBYMEMBER'; -import * as GEORADIUSBYMEMBERSTORE from '../commands/GEORADIUSBYMEMBERSTORE'; -import * as GEORADIUSSTORE from '../commands/GEORADIUSSTORE'; -import * as GEOSEARCH_WITH from '../commands/GEOSEARCH_WITH'; -import * as GEOSEARCH from '../commands/GEOSEARCH'; -import * as GEOSEARCHSTORE from '../commands/GEOSEARCHSTORE'; -import * as GET from '../commands/GET'; -import * as GETBIT from '../commands/GETBIT'; -import * as GETDEL from '../commands/GETDEL'; -import * as GETEX from '../commands/GETEX'; -import * as GETRANGE from '../commands/GETRANGE'; -import * as GETSET from '../commands/GETSET'; -import * as HDEL from '../commands/HDEL'; -import * as HEXISTS from '../commands/HEXISTS'; -import * as HGET from '../commands/HGET'; -import * as HGETALL from '../commands/HGETALL'; -import * as HINCRBY from '../commands/HINCRBY'; -import * as HINCRBYFLOAT from '../commands/HINCRBYFLOAT'; -import * as HKEYS from '../commands/HKEYS'; -import * as HLEN from '../commands/HLEN'; -import * as HMGET from '../commands/HMGET'; -import * as HRANDFIELD_COUNT_WITHVALUES from '../commands/HRANDFIELD_COUNT_WITHVALUES'; -import * as HRANDFIELD_COUNT from '../commands/HRANDFIELD_COUNT'; -import * as HRANDFIELD from '../commands/HRANDFIELD'; -import * as HSCAN from '../commands/HSCAN'; -import * as HSET from '../commands/HSET'; -import * as HSETNX from '../commands/HSETNX'; -import * as HSTRLEN from '../commands/HSTRLEN'; -import * as HVALS from '../commands/HVALS'; -import * as INCR from '../commands/INCR'; -import * as INCRBY from '../commands/INCRBY'; -import * as INCRBYFLOAT from '../commands/INCRBYFLOAT'; -import * as LCS_IDX_WITHMATCHLEN from '../commands/LCS_IDX_WITHMATCHLEN'; -import * as LCS_IDX from '../commands/LCS_IDX'; -import * as LCS_LEN from '../commands/LCS_LEN'; -import * as LCS from '../commands/LCS'; -import * as LINDEX from '../commands/LINDEX'; -import * as LINSERT from '../commands/LINSERT'; -import * as LLEN from '../commands/LLEN'; -import * as LMOVE from '../commands/LMOVE'; -import * as LMPOP from '../commands/LMPOP'; -import * as LPOP_COUNT from '../commands/LPOP_COUNT'; -import * as LPOP from '../commands/LPOP'; -import * as LPOS_COUNT from '../commands/LPOS_COUNT'; -import * as LPOS from '../commands/LPOS'; -import * as LPUSH from '../commands/LPUSH'; -import * as LPUSHX from '../commands/LPUSHX'; -import * as LRANGE from '../commands/LRANGE'; -import * as LREM from '../commands/LREM'; -import * as LSET from '../commands/LSET'; -import * as LTRIM from '../commands/LTRIM'; -import * as MGET from '../commands/MGET'; -import * as MIGRATE from '../commands/MIGRATE'; -import * as MSET from '../commands/MSET'; -import * as MSETNX from '../commands/MSETNX'; -import * as OBJECT_ENCODING from '../commands/OBJECT_ENCODING'; -import * as OBJECT_FREQ from '../commands/OBJECT_FREQ'; -import * as OBJECT_IDLETIME from '../commands/OBJECT_IDLETIME'; -import * as OBJECT_REFCOUNT from '../commands/OBJECT_REFCOUNT'; -import * as PERSIST from '../commands/PERSIST'; -import * as PEXPIRE from '../commands/PEXPIRE'; -import * as PEXPIREAT from '../commands/PEXPIREAT'; -import * as PEXPIRETIME from '../commands/PEXPIRETIME'; -import * as PFADD from '../commands/PFADD'; -import * as PFCOUNT from '../commands/PFCOUNT'; -import * as PFMERGE from '../commands/PFMERGE'; -import * as PSETEX from '../commands/PSETEX'; -import * as PTTL from '../commands/PTTL'; -import * as PUBLISH from '../commands/PUBLISH'; -import * as RENAME from '../commands/RENAME'; -import * as RENAMENX from '../commands/RENAMENX'; -import * as RPOP_COUNT from '../commands/RPOP_COUNT'; -import * as RPOP from '../commands/RPOP'; -import * as RPOPLPUSH from '../commands/RPOPLPUSH'; -import * as RPUSH from '../commands/RPUSH'; -import * as RPUSHX from '../commands/RPUSHX'; -import * as SADD from '../commands/SADD'; -import * as SCARD from '../commands/SCARD'; -import * as SDIFF from '../commands/SDIFF'; -import * as SDIFFSTORE from '../commands/SDIFFSTORE'; -import * as SET from '../commands/SET'; -import * as SETBIT from '../commands/SETBIT'; -import * as SETEX from '../commands/SETEX'; -import * as SETNX from '../commands/SETNX'; -import * as SETRANGE from '../commands/SETRANGE'; -import * as SINTER from '../commands/SINTER'; -import * as SINTERCARD from '../commands/SINTERCARD'; -import * as SINTERSTORE from '../commands/SINTERSTORE'; -import * as SISMEMBER from '../commands/SISMEMBER'; -import * as SMEMBERS from '../commands/SMEMBERS'; -import * as SMISMEMBER from '../commands/SMISMEMBER'; -import * as SMOVE from '../commands/SMOVE'; -import * as SORT_RO from '../commands/SORT_RO'; -import * as SORT_STORE from '../commands/SORT_STORE'; -import * as SORT from '../commands/SORT'; -import * as SPOP from '../commands/SPOP'; -import * as SPUBLISH from '../commands/SPUBLISH'; -import * as SRANDMEMBER_COUNT from '../commands/SRANDMEMBER_COUNT'; -import * as SRANDMEMBER from '../commands/SRANDMEMBER'; -import * as SREM from '../commands/SREM'; -import * as SSCAN from '../commands/SSCAN'; -import * as STRLEN from '../commands/STRLEN'; -import * as SUNION from '../commands/SUNION'; -import * as SUNIONSTORE from '../commands/SUNIONSTORE'; -import * as TOUCH from '../commands/TOUCH'; -import * as TTL from '../commands/TTL'; -import * as TYPE from '../commands/TYPE'; -import * as UNLINK from '../commands/UNLINK'; -import * as WATCH from '../commands/WATCH'; -import * as XACK from '../commands/XACK'; -import * as XADD from '../commands/XADD'; -import * as XAUTOCLAIM_JUSTID from '../commands/XAUTOCLAIM_JUSTID'; -import * as XAUTOCLAIM from '../commands/XAUTOCLAIM'; -import * as XCLAIM_JUSTID from '../commands/XCLAIM_JUSTID'; -import * as XCLAIM from '../commands/XCLAIM'; -import * as XDEL from '../commands/XDEL'; -import * as XGROUP_CREATE from '../commands/XGROUP_CREATE'; -import * as XGROUP_CREATECONSUMER from '../commands/XGROUP_CREATECONSUMER'; -import * as XGROUP_DELCONSUMER from '../commands/XGROUP_DELCONSUMER'; -import * as XGROUP_DESTROY from '../commands/XGROUP_DESTROY'; -import * as XGROUP_SETID from '../commands/XGROUP_SETID'; -import * as XINFO_CONSUMERS from '../commands/XINFO_CONSUMERS'; -import * as XINFO_GROUPS from '../commands/XINFO_GROUPS'; -import * as XINFO_STREAM from '../commands/XINFO_STREAM'; -import * as XLEN from '../commands/XLEN'; -import * as XPENDING_RANGE from '../commands/XPENDING_RANGE'; -import * as XPENDING from '../commands/XPENDING'; -import * as XRANGE from '../commands/XRANGE'; -import * as XREAD from '../commands/XREAD'; -import * as XREADGROUP from '../commands/XREADGROUP'; -import * as XREVRANGE from '../commands/XREVRANGE'; -import * as XSETID from '../commands/XSETID'; -import * as XTRIM from '../commands/XTRIM'; -import * as ZADD from '../commands/ZADD'; -import * as ZCARD from '../commands/ZCARD'; -import * as ZCOUNT from '../commands/ZCOUNT'; -import * as ZDIFF_WITHSCORES from '../commands/ZDIFF_WITHSCORES'; -import * as ZDIFF from '../commands/ZDIFF'; -import * as ZDIFFSTORE from '../commands/ZDIFFSTORE'; -import * as ZINCRBY from '../commands/ZINCRBY'; -import * as ZINTER_WITHSCORES from '../commands/ZINTER_WITHSCORES'; -import * as ZINTER from '../commands/ZINTER'; -import * as ZINTERCARD from '../commands/ZINTERCARD'; -import * as ZINTERSTORE from '../commands/ZINTERSTORE'; -import * as ZLEXCOUNT from '../commands/ZLEXCOUNT'; -import * as ZMPOP from '../commands/ZMPOP'; -import * as ZMSCORE from '../commands/ZMSCORE'; -import * as ZPOPMAX_COUNT from '../commands/ZPOPMAX_COUNT'; -import * as ZPOPMAX from '../commands/ZPOPMAX'; -import * as ZPOPMIN_COUNT from '../commands/ZPOPMIN_COUNT'; -import * as ZPOPMIN from '../commands/ZPOPMIN'; -import * as ZRANDMEMBER_COUNT_WITHSCORES from '../commands/ZRANDMEMBER_COUNT_WITHSCORES'; -import * as ZRANDMEMBER_COUNT from '../commands/ZRANDMEMBER_COUNT'; -import * as ZRANDMEMBER from '../commands/ZRANDMEMBER'; -import * as ZRANGE_WITHSCORES from '../commands/ZRANGE_WITHSCORES'; -import * as ZRANGE from '../commands/ZRANGE'; -import * as ZRANGEBYLEX from '../commands/ZRANGEBYLEX'; -import * as ZRANGEBYSCORE_WITHSCORES from '../commands/ZRANGEBYSCORE_WITHSCORES'; -import * as ZRANGEBYSCORE from '../commands/ZRANGEBYSCORE'; -import * as ZRANGESTORE from '../commands/ZRANGESTORE'; -import * as ZRANK from '../commands/ZRANK'; -import * as ZREM from '../commands/ZREM'; -import * as ZREMRANGEBYLEX from '../commands/ZREMRANGEBYLEX'; -import * as ZREMRANGEBYRANK from '../commands/ZREMRANGEBYRANK'; -import * as ZREMRANGEBYSCORE from '../commands/ZREMRANGEBYSCORE'; -import * as ZREVRANK from '../commands/ZREVRANK'; -import * as ZSCAN from '../commands/ZSCAN'; -import * as ZSCORE from '../commands/ZSCORE'; -import * as ZUNION_WITHSCORES from '../commands/ZUNION_WITHSCORES'; -import * as ZUNION from '../commands/ZUNION'; -import * as ZUNIONSTORE from '../commands/ZUNIONSTORE'; - -export default { - APPEND, - append: APPEND, - BITCOUNT, - bitCount: BITCOUNT, - BITFIELD_RO, - bitFieldRo: BITFIELD_RO, - BITFIELD, - bitField: BITFIELD, - BITOP, - bitOp: BITOP, - BITPOS, - bitPos: BITPOS, - BLMOVE, - blMove: BLMOVE, - BLMPOP, - blmPop: BLMPOP, - BLPOP, - blPop: BLPOP, - BRPOP, - brPop: BRPOP, - BRPOPLPUSH, - brPopLPush: BRPOPLPUSH, - BZMPOP, - bzmPop: BZMPOP, - BZPOPMAX, - bzPopMax: BZPOPMAX, - BZPOPMIN, - bzPopMin: BZPOPMIN, - COPY, - copy: COPY, - DECR, - decr: DECR, - DECRBY, - decrBy: DECRBY, - DEL, - del: DEL, - DUMP, - dump: DUMP, - EVAL_RO, - evalRo: EVAL_RO, - EVAL, - eval: EVAL, - EVALSHA, - evalSha: EVALSHA, - EVALSHA_RO, - evalShaRo: EVALSHA_RO, - EXISTS, - exists: EXISTS, - EXPIRE, - expire: EXPIRE, - EXPIREAT, - expireAt: EXPIREAT, - EXPIRETIME, - expireTime: EXPIRETIME, - FCALL_RO, - fCallRo: FCALL_RO, - FCALL, - fCall: FCALL, - GEOADD, - geoAdd: GEOADD, - GEODIST, - geoDist: GEODIST, - GEOHASH, - geoHash: GEOHASH, - GEOPOS, - geoPos: GEOPOS, - GEORADIUS_RO_WITH, - geoRadiusRoWith: GEORADIUS_RO_WITH, - GEORADIUS_RO, - geoRadiusRo: GEORADIUS_RO, - GEORADIUS_WITH, - geoRadiusWith: GEORADIUS_WITH, - GEORADIUS, - geoRadius: GEORADIUS, - GEORADIUSBYMEMBER_RO_WITH, - geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH, - GEORADIUSBYMEMBER_RO, - geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO, - GEORADIUSBYMEMBER_WITH, - geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH, - GEORADIUSBYMEMBER, - geoRadiusByMember: GEORADIUSBYMEMBER, - GEORADIUSBYMEMBERSTORE, - geoRadiusByMemberStore: GEORADIUSBYMEMBERSTORE, - GEORADIUSSTORE, - geoRadiusStore: GEORADIUSSTORE, - GEOSEARCH_WITH, - geoSearchWith: GEOSEARCH_WITH, - GEOSEARCH, - geoSearch: GEOSEARCH, - GEOSEARCHSTORE, - geoSearchStore: GEOSEARCHSTORE, - GET, - get: GET, - GETBIT, - getBit: GETBIT, - GETDEL, - getDel: GETDEL, - GETEX, - getEx: GETEX, - GETRANGE, - getRange: GETRANGE, - GETSET, - getSet: GETSET, - HDEL, - hDel: HDEL, - HEXISTS, - hExists: HEXISTS, - HGET, - hGet: HGET, - HGETALL, - hGetAll: HGETALL, - HINCRBY, - hIncrBy: HINCRBY, - HINCRBYFLOAT, - hIncrByFloat: HINCRBYFLOAT, - HKEYS, - hKeys: HKEYS, - HLEN, - hLen: HLEN, - HMGET, - hmGet: HMGET, - HRANDFIELD_COUNT_WITHVALUES, - hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, - HRANDFIELD_COUNT, - hRandFieldCount: HRANDFIELD_COUNT, - HRANDFIELD, - hRandField: HRANDFIELD, - HSCAN, - hScan: HSCAN, - HSET, - hSet: HSET, - HSETNX, - hSetNX: HSETNX, - HSTRLEN, - hStrLen: HSTRLEN, - HVALS, - hVals: HVALS, - INCR, - incr: INCR, - INCRBY, - incrBy: INCRBY, - INCRBYFLOAT, - incrByFloat: INCRBYFLOAT, - LCS_IDX_WITHMATCHLEN, - lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN, - LCS_IDX, - lcsIdx: LCS_IDX, - LCS_LEN, - lcsLen: LCS_LEN, - LCS, - lcs: LCS, - LINDEX, - lIndex: LINDEX, - LINSERT, - lInsert: LINSERT, - LLEN, - lLen: LLEN, - LMOVE, - lMove: LMOVE, - LMPOP, - lmPop: LMPOP, - LPOP_COUNT, - lPopCount: LPOP_COUNT, - LPOP, - lPop: LPOP, - LPOS_COUNT, - lPosCount: LPOS_COUNT, - LPOS, - lPos: LPOS, - LPUSH, - lPush: LPUSH, - LPUSHX, - lPushX: LPUSHX, - LRANGE, - lRange: LRANGE, - LREM, - lRem: LREM, - LSET, - lSet: LSET, - LTRIM, - lTrim: LTRIM, - MGET, - mGet: MGET, - MIGRATE, - migrate: MIGRATE, - MSET, - mSet: MSET, - MSETNX, - mSetNX: MSETNX, - OBJECT_ENCODING, - objectEncoding: OBJECT_ENCODING, - OBJECT_FREQ, - objectFreq: OBJECT_FREQ, - OBJECT_IDLETIME, - objectIdleTime: OBJECT_IDLETIME, - OBJECT_REFCOUNT, - objectRefCount: OBJECT_REFCOUNT, - PERSIST, - persist: PERSIST, - PEXPIRE, - pExpire: PEXPIRE, - PEXPIREAT, - pExpireAt: PEXPIREAT, - PEXPIRETIME, - pExpireTime: PEXPIRETIME, - PFADD, - pfAdd: PFADD, - PFCOUNT, - pfCount: PFCOUNT, - PFMERGE, - pfMerge: PFMERGE, - PSETEX, - pSetEx: PSETEX, - PTTL, - pTTL: PTTL, - PUBLISH, - publish: PUBLISH, - RENAME, - rename: RENAME, - RENAMENX, - renameNX: RENAMENX, - RPOP_COUNT, - rPopCount: RPOP_COUNT, - RPOP, - rPop: RPOP, - RPOPLPUSH, - rPopLPush: RPOPLPUSH, - RPUSH, - rPush: RPUSH, - RPUSHX, - rPushX: RPUSHX, - SADD, - sAdd: SADD, - SCARD, - sCard: SCARD, - SDIFF, - sDiff: SDIFF, - SDIFFSTORE, - sDiffStore: SDIFFSTORE, - SINTER, - sInter: SINTER, - SINTERCARD, - sInterCard: SINTERCARD, - SINTERSTORE, - sInterStore: SINTERSTORE, - SET, - set: SET, - SETBIT, - setBit: SETBIT, - SETEX, - setEx: SETEX, - SETNX, - setNX: SETNX, - SETRANGE, - setRange: SETRANGE, - SISMEMBER, - sIsMember: SISMEMBER, - SMEMBERS, - sMembers: SMEMBERS, - SMISMEMBER, - smIsMember: SMISMEMBER, - SMOVE, - sMove: SMOVE, - SORT_RO, - sortRo: SORT_RO, - SORT_STORE, - sortStore: SORT_STORE, - SORT, - sort: SORT, - SPOP, - sPop: SPOP, - SPUBLISH, - sPublish: SPUBLISH, - SRANDMEMBER_COUNT, - sRandMemberCount: SRANDMEMBER_COUNT, - SRANDMEMBER, - sRandMember: SRANDMEMBER, - SREM, - sRem: SREM, - SSCAN, - sScan: SSCAN, - STRLEN, - strLen: STRLEN, - SUNION, - sUnion: SUNION, - SUNIONSTORE, - sUnionStore: SUNIONSTORE, - TOUCH, - touch: TOUCH, - TTL, - ttl: TTL, - TYPE, - type: TYPE, - UNLINK, - unlink: UNLINK, - WATCH, - watch: WATCH, - XACK, - xAck: XACK, - XADD, - xAdd: XADD, - XAUTOCLAIM_JUSTID, - xAutoClaimJustId: XAUTOCLAIM_JUSTID, - XAUTOCLAIM, - xAutoClaim: XAUTOCLAIM, - XCLAIM, - xClaim: XCLAIM, - XCLAIM_JUSTID, - xClaimJustId: XCLAIM_JUSTID, - XDEL, - xDel: XDEL, - XGROUP_CREATE, - xGroupCreate: XGROUP_CREATE, - XGROUP_CREATECONSUMER, - xGroupCreateConsumer: XGROUP_CREATECONSUMER, - XGROUP_DELCONSUMER, - xGroupDelConsumer: XGROUP_DELCONSUMER, - XGROUP_DESTROY, - xGroupDestroy: XGROUP_DESTROY, - XGROUP_SETID, - xGroupSetId: XGROUP_SETID, - XINFO_CONSUMERS, - xInfoConsumers: XINFO_CONSUMERS, - XINFO_GROUPS, - xInfoGroups: XINFO_GROUPS, - XINFO_STREAM, - xInfoStream: XINFO_STREAM, - XLEN, - xLen: XLEN, - XPENDING_RANGE, - xPendingRange: XPENDING_RANGE, - XPENDING, - xPending: XPENDING, - XRANGE, - xRange: XRANGE, - XREAD, - xRead: XREAD, - XREADGROUP, - xReadGroup: XREADGROUP, - XREVRANGE, - xRevRange: XREVRANGE, - XSETID, - xSetId: XSETID, - XTRIM, - xTrim: XTRIM, - ZADD, - zAdd: ZADD, - ZCARD, - zCard: ZCARD, - ZCOUNT, - zCount: ZCOUNT, - ZDIFF_WITHSCORES, - zDiffWithScores: ZDIFF_WITHSCORES, - ZDIFF, - zDiff: ZDIFF, - ZDIFFSTORE, - zDiffStore: ZDIFFSTORE, - ZINCRBY, - zIncrBy: ZINCRBY, - ZINTER_WITHSCORES, - zInterWithScores: ZINTER_WITHSCORES, - ZINTER, - zInter: ZINTER, - ZINTERCARD, - zInterCard: ZINTERCARD, - ZINTERSTORE, - zInterStore: ZINTERSTORE, - ZLEXCOUNT, - zLexCount: ZLEXCOUNT, - ZMPOP, - zmPop: ZMPOP, - ZMSCORE, - zmScore: ZMSCORE, - ZPOPMAX_COUNT, - zPopMaxCount: ZPOPMAX_COUNT, - ZPOPMAX, - zPopMax: ZPOPMAX, - ZPOPMIN_COUNT, - zPopMinCount: ZPOPMIN_COUNT, - ZPOPMIN, - zPopMin: ZPOPMIN, - ZRANDMEMBER_COUNT_WITHSCORES, - zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES, - ZRANDMEMBER_COUNT, - zRandMemberCount: ZRANDMEMBER_COUNT, - ZRANDMEMBER, - zRandMember: ZRANDMEMBER, - ZRANGE_WITHSCORES, - zRangeWithScores: ZRANGE_WITHSCORES, - ZRANGE, - zRange: ZRANGE, - ZRANGEBYLEX, - zRangeByLex: ZRANGEBYLEX, - ZRANGEBYSCORE_WITHSCORES, - zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, - ZRANGEBYSCORE, - zRangeByScore: ZRANGEBYSCORE, - ZRANGESTORE, - zRangeStore: ZRANGESTORE, - ZRANK, - zRank: ZRANK, - ZREM, - zRem: ZREM, - ZREMRANGEBYLEX, - zRemRangeByLex: ZREMRANGEBYLEX, - ZREMRANGEBYRANK, - zRemRangeByRank: ZREMRANGEBYRANK, - ZREMRANGEBYSCORE, - zRemRangeByScore: ZREMRANGEBYSCORE, - ZREVRANK, - zRevRank: ZREVRANK, - ZSCAN, - zScan: ZSCAN, - ZSCORE, - zScore: ZSCORE, - ZUNION_WITHSCORES, - zUnionWithScores: ZUNION_WITHSCORES, - ZUNION, - zUnion: ZUNION, - ZUNIONSTORE, - zUnionStore: ZUNIONSTORE -}; diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 818930c8c82..4e69452f7cd 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,424 +1,549 @@ -import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply, RedisCommandReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, RedisCommandSignature, RedisFunction } from '../commands'; -import { ClientCommandOptions, RedisClientOptions, RedisClientType, WithFunctions, WithModules, WithScripts } from '../client'; -import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; -import { attachExtensions, transformCommandReply, attachCommands, transformCommandArguments } from '../commander'; +import { ClientCommandOptions, RedisClientOptions, RedisClientType } from '../client'; +import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandSignature, CommandWithPoliciesSignature, Flags, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, TransformReply } from '../RESP/types'; +import COMMANDS from '../commands'; import { EventEmitter } from 'events'; -import RedisClusterMultiCommand, { InstantiableRedisClusterMultiCommandType, RedisClusterMultiCommandType } from './multi-command'; -import { RedisMultiQueuedCommand } from '../multi-command'; +import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; +import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; +// import RedisClusterMultiCommand, { InstantiableRedisClusterMultiCommandType, RedisClusterMultiCommandType } from './multi-command'; +// import { RedisMultiQueuedCommand } from '../multi-command'; import { PubSubListener } from '../client/pub-sub'; import { ErrorReply } from '../errors'; export type RedisClusterClientOptions = Omit< - RedisClientOptions, - 'modules' | 'functions' | 'scripts' | 'database' + RedisClientOptions, + 'modules' | 'functions' | 'scripts' | 'database' | 'RESP' >; export interface RedisClusterOptions< - M extends RedisModules = Record, - F extends RedisFunctions = Record, - S extends RedisScripts = Record -> extends RedisExtensions { - /** - * Should contain details for some of the cluster nodes that the client will use to discover - * the "cluster topology". We recommend including details for at least 3 nodes here. - */ - rootNodes: Array; - /** - * Default values used for every client in the cluster. Use this to specify global values, - * for example: ACL credentials, timeouts, TLS configuration etc. - */ - defaults?: Partial; - /** - * When `true`, `.connect()` will only discover the cluster topology, without actually connecting to all the nodes. - * Useful for short-term or PubSub-only connections. - */ - minimizeConnections?: boolean; - /** - * When `true`, distribute load by executing readonly commands (such as `GET`, `GEOSEARCH`, etc.) across all cluster nodes. When `false`, only use master nodes. - */ - useReplicas?: boolean; - /** - * The maximum number of times a command will be redirected due to `MOVED` or `ASK` errors. - */ - maxCommandRedirections?: number; - /** - * Mapping between the addresses in the cluster (see `CLUSTER SHARDS`) and the addresses the client should connect to - * Useful when the cluster is running on another network - * - */ - nodeAddressMap?: NodeAddressMap; + M extends RedisModules = RedisModules, + F extends RedisFunctions = RedisFunctions, + S extends RedisScripts = RedisScripts, + RESP extends RespVersions = RespVersions +> extends CommanderConfig { + /** + * Should contain details for some of the cluster nodes that the client will use to discover + * the "cluster topology". We recommend including details for at least 3 nodes here. + */ + rootNodes: Array; + /** + * Default values used for every client in the cluster. Use this to specify global values, + * for example: ACL credentials, timeouts, TLS configuration etc. + */ + defaults?: Partial; + /** + * When `true`, `.connect()` will only discover the cluster topology, without actually connecting to all the nodes. + * Useful for short-term or PubSub-only connections. + */ + minimizeConnections?: boolean; + /** + * When `true`, distribute load by executing readonly commands (such as `GET`, `GEOSEARCH`, etc.) across all cluster nodes. When `false`, only use master nodes. + */ + // TODO: replicas only mode? + useReplicas?: boolean; + /** + * The maximum number of times a command will be redirected due to `MOVED` or `ASK` errors. + */ + maxCommandRedirections?: number; + /** + * Mapping between the addresses in the cluster (see `CLUSTER SHARDS`) and the addresses the client should connect to + * Useful when the cluster is running on another network + */ + nodeAddressMap?: NodeAddressMap; } -type WithCommands = { - [P in keyof typeof COMMANDS]: RedisCommandSignature<(typeof COMMANDS)[P]>; +type WithCommands< + RESP extends RespVersions, + FLAGS extends Flags, + POLICIES extends CommandPolicies +> = { + [P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, FLAGS, POLICIES>; }; export type RedisClusterType< - M extends RedisModules = Record, - F extends RedisFunctions = Record, - S extends RedisScripts = Record -> = RedisCluster & WithCommands & WithModules & WithFunctions & WithScripts; - -export default class RedisCluster< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> extends EventEmitter { - static extractFirstKey( - command: RedisCommand, - originalArgs: Array, - redisArgs: RedisCommandArguments - ): RedisCommandArgument | undefined { - if (command.FIRST_KEY_INDEX === undefined) { - return undefined; - } else if (typeof command.FIRST_KEY_INDEX === 'number') { - return redisArgs[command.FIRST_KEY_INDEX]; - } - - return command.FIRST_KEY_INDEX(...originalArgs); - } - - static create< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(options?: RedisClusterOptions): RedisClusterType { - return new (attachExtensions({ - BaseClass: RedisCluster, - modulesExecutor: RedisCluster.prototype.commandsExecutor, - modules: options?.modules, - functionsExecutor: RedisCluster.prototype.functionsExecutor, - functions: options?.functions, - scriptsExecutor: RedisCluster.prototype.scriptsExecutor, - scripts: options?.scripts - }))(options); - } - - readonly #options: RedisClusterOptions; - - readonly #slots: RedisClusterSlots; - - get slots() { - return this.#slots.slots; - } - - get shards() { - return this.#slots.shards; - } - - get masters() { - return this.#slots.masters; - } - - get replicas() { - return this.#slots.replicas; - } - - get nodeByAddress() { - return this.#slots.nodeByAddress; - } - - get pubSubNode() { - return this.#slots.pubSubNode; - } - - readonly #Multi: InstantiableRedisClusterMultiCommandType; - - get isOpen() { - return this.#slots.isOpen; - } - - constructor(options: RedisClusterOptions) { - super(); - - this.#options = options; - this.#slots = new RedisClusterSlots(options, this.emit.bind(this)); - this.#Multi = RedisClusterMultiCommand.extend(options); - } - - duplicate(overrides?: Partial>): RedisClusterType { - return new (Object.getPrototypeOf(this).constructor)({ - ...this.#options, - ...overrides - }); - } - - connect() { - return this.#slots.connect(); - } + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + FLAGS extends Flags = {}, + POLICIES extends CommandPolicies = {} +> = RedisCluster & WithCommands; +// & WithModules & WithFunctions & WithScripts + +export interface ClusterCommandOptions extends ClientCommandOptions { + policies?: CommandPolicies; +} - async commandsExecutor( - command: C, - args: Array - ): Promise> { - const { args: redisArgs, options } = transformCommandArguments(command, args); - return transformCommandReply( - command, - await this.sendCommand( - RedisCluster.extractFirstKey(command, args, redisArgs), - command.IS_READ_ONLY, - redisArgs, - options - ), - redisArgs.preserve - ); - } +type ProxyCluster = RedisCluster & { commandOptions?: ClusterCommandOptions }; - async sendCommand( - firstKey: RedisCommandArgument | undefined, - isReadonly: boolean | undefined, - args: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - return this.#execute( - firstKey, - isReadonly, - client => client.sendCommand(args, options) - ); - } +type NamespaceProxyCluster = { self: ProxyCluster }; - async functionsExecutor( - fn: F, - args: Array, - name: string, - ): Promise> { - const { args: redisArgs, options } = transformCommandArguments(fn, args); - return transformCommandReply( - fn, - await this.executeFunction( - name, - fn, - args, - redisArgs, - options - ), - redisArgs.preserve +export default class RedisCluster< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags, + POLICIES extends CommandPolicies +> extends EventEmitter { + private static _extractFirstKey( + command: C, + args: Parameters, + redisArgs: Array + ): RedisArgument | undefined { + if (command.FIRST_KEY_INDEX === undefined) { + return undefined; + } else if (typeof command.FIRST_KEY_INDEX === 'number') { + return redisArgs[command.FIRST_KEY_INDEX]; + } + + return command.FIRST_KEY_INDEX(...args); + } + + private static _createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: ProxyCluster) { + const args = command.transformArguments.apply(undefined, arguments as any), + firstKey = RedisCluster._extractFirstKey( + command, + arguments as any, + args + ), + reply = await this.sendCommand( + firstKey, + command.IS_READ_ONLY, + args, + this.commandOptions, + command.POLICIES ); - } - async executeFunction( - name: string, - fn: RedisFunction, - originalArgs: Array, - redisArgs: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - return this.#execute( - RedisCluster.extractFirstKey(fn, originalArgs, redisArgs), - fn.IS_READ_ONLY, - client => client.executeFunction(name, fn, redisArgs, options) + return transformReply ? + transformReply(reply, args.preserve) : + reply; + }; + } + + private static _createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: NamespaceProxyCluster) { + const args = command.transformArguments.apply(undefined, arguments as any), + firstKey = RedisCluster._extractFirstKey( + command, + arguments as any, + args + ), + reply = await this.self.sendCommand( + firstKey, + command.IS_READ_ONLY, + args, + this.self.commandOptions, + command.POLICIES ); - } - async scriptsExecutor(script: S, args: Array): Promise> { - const { args: redisArgs, options } = transformCommandArguments(script, args); - return transformCommandReply( - script, - await this.executeScript( - script, - args, - redisArgs, - options - ), - redisArgs.preserve + return transformReply ? + transformReply(reply, args.preserve) : + reply; + }; + } + + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return async function (this: NamespaceProxyCluster) { + const fnArgs = fn.transformArguments.apply(undefined, arguments as any), + args = prefix.concat(fnArgs), + firstKey = RedisCluster._extractFirstKey( + fn, + arguments as any, + args + ), + reply = await this.self.sendCommand( + firstKey, + fn.IS_READ_ONLY, + args, + this.self.commandOptions, + fn.POLICIES ); - } - async executeScript( - script: RedisScript, - originalArgs: Array, - redisArgs: RedisCommandArguments, - options?: ClientCommandOptions - ): Promise { - return this.#execute( - RedisCluster.extractFirstKey(script, originalArgs, redisArgs), - script.IS_READ_ONLY, - client => client.executeScript(script, redisArgs, options) + return transformReply ? + transformReply(reply, fnArgs.preserve) : + reply; + }; + } + + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + const prefix = scriptArgumentsPrefix(script), + transformReply = getTransformReply(script, resp); + return async function (this: ProxyCluster) { + const scriptArgs = script.transformArguments.apply(undefined, arguments as any), + args = prefix.concat(scriptArgs), + firstKey = RedisCluster._extractFirstKey( + script, + arguments as any, + args + ), + reply = await this.sendCommand( + firstKey, + script.IS_READ_ONLY, + args, + this.commandOptions, + script.POLICIES ); - } - async #execute( - firstKey: RedisCommandArgument | undefined, - isReadonly: boolean | undefined, - executor: (client: RedisClientType) => Promise - ): Promise { - const maxCommandRedirections = this.#options.maxCommandRedirections ?? 16; - let client = await this.#slots.getClient(firstKey, isReadonly); - for (let i = 0;; i++) { - try { - return await executor(client); - } catch (err) { - if (++i > maxCommandRedirections || !(err instanceof ErrorReply)) { - throw err; - } - - if (err.message.startsWith('ASK')) { - const address = err.message.substring(err.message.lastIndexOf(' ') + 1); - let redirectTo = await this.#slots.getMasterByAddress(address); - if (!redirectTo) { - await this.#slots.rediscover(client); - redirectTo = await this.#slots.getMasterByAddress(address); - } - - if (!redirectTo) { - throw new Error(`Cannot find node ${address}`); - } - - await redirectTo.asking(); - client = redirectTo; - continue; - } else if (err.message.startsWith('MOVED')) { - await this.#slots.rediscover(client); - client = await this.#slots.getClient(firstKey, isReadonly); - continue; - } - - throw err; - } + return transformReply ? + transformReply(reply, scriptArgs.preserve) : + reply; + }; + } + + static factory< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 + >(config?: CommanderConfig) { + const Cluster = attachConfig({ + BaseClass: RedisCluster, + commands: COMMANDS, + createCommand: RedisCluster._createCommand, + createFunctionCommand: RedisCluster._createFunctionCommand, + createModuleCommand: RedisCluster._createModuleCommand, + createScriptCommand: RedisCluster._createScriptCommand, + config + }); + + // Client.prototype.Multi = RedisClientMultiCommand.extend(config); + + return (options?: Omit>) => { + // returning a proxy of the client to prevent the namespaces.self to leak between proxies + // namespaces will be bootstraped on first access per proxy + return Object.create(new Cluster(options)) as RedisClusterType; + }; + } + + static create< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 + >(options?: RedisClusterOptions) { + return RedisCluster.factory(options)(options); + } + + private readonly _options: RedisClusterOptions; + + private readonly _slots: RedisClusterSlots; + + /** + * An array of the cluster slots, each slot contain its `master` and `replicas`. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). + */ + get slots() { + return this._slots.slots; + } + + /** + * An array of cluster shards, each shard contain its `master` and `replicas`. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). + */ + get shards() { + return this._slots.shards; + } + + /** + * An array of the cluster masters. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific master node. + */ + get masters() { + return this._slots.masters; + } + + /** + * An array of the cluster replicas. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific replica node. + */ + get replicas() { + return this._slots.replicas; + } + + /** + * A map form a node address (`:`) to its shard, each shard contain its `master` and `replicas`. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). + */ + get nodeByAddress() { + return this._slots.nodeByAddress; + } + + /** + * The current pub/sub node. + */ + get pubSubNode() { + return this._slots.pubSubNode; + } + + // readonly #Multi: InstantiableRedisClusterMultiCommandType; + + get isOpen() { + return this._slots.isOpen; + } + + constructor(options: RedisClusterOptions) { + super(); + + this._options = options; + this._slots = new RedisClusterSlots(options, this.emit.bind(this)); + // this.#Multi = RedisClusterMultiCommand.extend(options); + } + + duplicate(overrides?: Partial>): RedisClusterType { + return new (Object.getPrototypeOf(this).constructor)({ + ...this._options, + ...overrides + }); + } + + connect() { + return this._slots.connect(); + } + + withCommandOptions(options: T) { + const proxy = Object.create(this); + proxy.commandOptions = options; + return proxy as RedisClusterType< + M, + F, + S, + RESP, + T['flags'] extends Flags ? T['flags'] : {}, + T['policies'] extends CommandPolicies ? T['policies'] : {} + >; + } + + private _commandOptionsProxy< + K extends keyof ClusterCommandOptions, + V extends ClusterCommandOptions[K] + >( + key: K, + value: V + ) { + const proxy = Object.create(this); + proxy.commandOptions = Object.create((this as ProxyCluster).commandOptions ?? null); + proxy.commandOptions[key] = value; + return proxy as RedisClusterType< + M, + F, + S, + RESP, + K extends 'flags' ? V extends Flags ? V : {} : FLAGS, + K extends 'policies' ? V extends CommandPolicies ? V : {} : POLICIES + >; + } + + /** + * Override the `flags` command option + */ + withFlags(flags: FLAGS) { + return this._commandOptionsProxy('flags', flags); + } + + /** + * Override the `policies` command option + * TODO + */ + withPolicies (policies: POLICIES) { + return this._commandOptionsProxy('policies', policies); + } + + async sendCommand( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + args: CommandArguments, + options?: ClusterCommandOptions, + deafultPolicies?: CommandPolicies + ): Promise { + // const requestPolicy = options?.policies?.request ?? deafultPolicies?.request, + // responsePolicy = options?.policies?.response ?? deafultPolicies?.response; + + const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; + let client = await this._slots.getClient(firstKey, isReadonly); + for (let i = 0; ; i++) { + try { + return await client.sendCommand(args, options); + } catch (err) { + // TODO: error class + if (++i > maxCommandRedirections || !(err instanceof Error)) { + throw err; } - } - - MULTI(routing?: RedisCommandArgument): RedisClusterMultiCommandType { - return new this.#Multi( - (commands: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => { - return this.#execute( - firstKey, - false, - client => client.multiExecutor(commands, undefined, chainId) - ); - }, - routing - ); - } - - multi = this.MULTI; - - async SUBSCRIBE( - channels: string | Array, - listener: PubSubListener, - bufferMode?: T - ) { - return (await this.#slots.getPubSubClient()) - .SUBSCRIBE(channels, listener, bufferMode); - } - - subscribe = this.SUBSCRIBE; - - async UNSUBSCRIBE( - channels?: string | Array, - listener?: PubSubListener, - bufferMode?: T - ) { - return this.#slots.executeUnsubscribeCommand(client => - client.UNSUBSCRIBE(channels, listener, bufferMode) - ); - } - - unsubscribe = this.UNSUBSCRIBE; - - async PSUBSCRIBE( - patterns: string | Array, - listener: PubSubListener, - bufferMode?: T - ) { - return (await this.#slots.getPubSubClient()) - .PSUBSCRIBE(patterns, listener, bufferMode); - } - - pSubscribe = this.PSUBSCRIBE; - - async PUNSUBSCRIBE( - patterns?: string | Array, - listener?: PubSubListener, - bufferMode?: T - ) { - return this.#slots.executeUnsubscribeCommand(client => - client.PUNSUBSCRIBE(patterns, listener, bufferMode) - ); - } - pUnsubscribe = this.PUNSUBSCRIBE; - - async SSUBSCRIBE( - channels: string | Array, - listener: PubSubListener, - bufferMode?: T - ) { - const maxCommandRedirections = this.#options.maxCommandRedirections ?? 16, - firstChannel = Array.isArray(channels) ? channels[0] : channels; - let client = await this.#slots.getShardedPubSubClient(firstChannel); - for (let i = 0;; i++) { - try { - return await client.SSUBSCRIBE(channels, listener, bufferMode); - } catch (err) { - if (++i > maxCommandRedirections || !(err instanceof ErrorReply)) { - throw err; - } - - if (err.message.startsWith('MOVED')) { - await this.#slots.rediscover(client); - client = await this.#slots.getShardedPubSubClient(firstChannel); - continue; - } - - throw err; - } + if (err.message.startsWith('ASK')) { + const address = err.message.substring(err.message.lastIndexOf(' ') + 1); + let redirectTo = await this._slots.getMasterByAddress(address); + if (!redirectTo) { + await this._slots.rediscover(client); + redirectTo = await this._slots.getMasterByAddress(address); + } + + if (!redirectTo) { + throw new Error(`Cannot find node ${address}`); + } + + await redirectTo.asking(); + client = redirectTo; + continue; + } else if (err.message.startsWith('MOVED')) { + await this._slots.rediscover(client); + client = await this._slots.getClient(firstKey, isReadonly); + continue; } - } - - sSubscribe = this.SSUBSCRIBE; - - SUNSUBSCRIBE( - channels: string | Array, - listener: PubSubListener, - bufferMode?: T - ) { - return this.#slots.executeShardedUnsubscribeCommand( - Array.isArray(channels) ? channels[0] : channels, - client => client.SUNSUBSCRIBE(channels, listener, bufferMode) - ); - } - - sUnsubscribe = this.SUNSUBSCRIBE; - - quit(): Promise { - return this.#slots.quit(); - } - - disconnect(): Promise { - return this.#slots.disconnect(); - } - nodeClient(node: ShardNode) { - return this.#slots.nodeClient(node); - } - - getRandomNode() { - return this.#slots.getRandomNode(); - } - - getSlotRandomNode(slot: number) { - return this.#slots.getSlotRandomNode(slot); - } + throw err; + } + } + } + + // MULTI(routing?: RedisCommandArgument): RedisClusterMultiCommandType { + // return new this.#Multi( + // (commands: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => { + // return this.#execute( + // firstKey, + // false, + // client => client.multiExecutor(commands, undefined, chainId) + // ); + // }, + // routing + // ); + // } + + // multi = this.MULTI; + + async SUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return (await this._slots.getPubSubClient()) + .SUBSCRIBE(channels, listener, bufferMode); + } + + subscribe = this.SUBSCRIBE; + + async UNSUBSCRIBE( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this._slots.executeUnsubscribeCommand(client => + client.UNSUBSCRIBE(channels, listener, bufferMode) + ); + } + + unsubscribe = this.UNSUBSCRIBE; + + async PSUBSCRIBE( + patterns: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return (await this._slots.getPubSubClient()) + .PSUBSCRIBE(patterns, listener, bufferMode); + } + + pSubscribe = this.PSUBSCRIBE; + + async PUNSUBSCRIBE( + patterns?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this._slots.executeUnsubscribeCommand(client => + client.PUNSUBSCRIBE(patterns, listener, bufferMode) + ); + } + + pUnsubscribe = this.PUNSUBSCRIBE; + + async SSUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + const maxCommandRedirections = this._options.maxCommandRedirections ?? 16, + firstChannel = Array.isArray(channels) ? channels[0] : channels; + let client = await this._slots.getShardedPubSubClient(firstChannel); + for (let i = 0; ; i++) { + try { + return await client.SSUBSCRIBE(channels, listener, bufferMode); + } catch (err) { + if (++i > maxCommandRedirections || !(err instanceof ErrorReply)) { + throw err; + } - /** - * @deprecated use `.masters` instead - */ - getMasters() { - return this.masters; - } + if (err.message.startsWith('MOVED')) { + await this._slots.rediscover(client); + client = await this._slots.getShardedPubSubClient(firstChannel); + continue; + } - /** - * @deprecated use `.slots[]` instead - */ - getSlotMaster(slot: number) { - return this.slots[slot].master; - } + throw err; + } + } + } + + sSubscribe = this.SSUBSCRIBE; + + SUNSUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this._slots.executeShardedUnsubscribeCommand( + Array.isArray(channels) ? channels[0] : channels, + client => client.SUNSUBSCRIBE(channels, listener, bufferMode) + ); + } + + sUnsubscribe = this.SUNSUBSCRIBE; + + // quit(): Promise { + // return this.#slots.quit(); + // } + + disconnect(): Promise { + return this._slots.disconnect(); + } + + nodeClient(node: ShardNode) { + return this._slots.nodeClient(node); + } + + /** + * Returns a random node from the cluster. + * Userful for running "forward" commands (like PUBLISH) on a random node. + */ + getRandomNode() { + return this._slots.getRandomNode(); + } + + /** + * Get a random node from a slot. + * Useful for running readonly commands on a slot. + */ + getSlotRandomNode(slot: number) { + return this._slots.getSlotRandomNode(slot); + } + + /** + * @deprecated use `.masters` instead + * TODO + */ + getMasters() { + return this.masters; + } + + /** + * @deprecated use `.slots[]` instead + * TODO + */ + getSlotMaster(slot: number) { + return this.slots[slot].master; + } } - -attachCommands({ - BaseClass: RedisCluster, - commands: COMMANDS, - executor: RedisCluster.prototype.commandsExecutor -}); diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index ef3c7590ec7..379af544af1 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,141 +1,141 @@ -import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, ExcludeMappedString, RedisFunction } from '../commands'; -import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -import { attachCommands, attachExtensions } from '../commander'; -import RedisCluster from '.'; - -type RedisClusterMultiCommandSignature< - C extends RedisCommand, - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = (...args: Parameters) => RedisClusterMultiCommandType; - -type WithCommands< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = { - [P in keyof typeof COMMANDS]: RedisClusterMultiCommandSignature<(typeof COMMANDS)[P], M, F, S>; -}; - -type WithModules< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = { - [P in keyof M as ExcludeMappedString

]: { - [C in keyof M[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; - }; -}; - -type WithFunctions< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = { - [P in keyof F as ExcludeMappedString

]: { - [FF in keyof F[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; - }; -}; - -type WithScripts< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = { - [P in keyof S as ExcludeMappedString

]: RedisClusterMultiCommandSignature; -}; - -export type RedisClusterMultiCommandType< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = RedisClusterMultiCommand & WithCommands & WithModules & WithFunctions & WithScripts; - -export type InstantiableRedisClusterMultiCommandType< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts -> = new (...args: ConstructorParameters) => RedisClusterMultiCommandType; - -export type RedisClusterMultiExecutor = (queue: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => Promise>; - -export default class RedisClusterMultiCommand { - readonly #multi = new RedisMultiCommand(); - readonly #executor: RedisClusterMultiExecutor; - #firstKey: RedisCommandArgument | undefined; - - static extend< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(extensions?: RedisExtensions): InstantiableRedisClusterMultiCommandType { - return attachExtensions({ - BaseClass: RedisClusterMultiCommand, - modulesExecutor: RedisClusterMultiCommand.prototype.commandsExecutor, - modules: extensions?.modules, - functionsExecutor: RedisClusterMultiCommand.prototype.functionsExecutor, - functions: extensions?.functions, - scriptsExecutor: RedisClusterMultiCommand.prototype.scriptsExecutor, - scripts: extensions?.scripts - }); - } - - constructor(executor: RedisClusterMultiExecutor, firstKey?: RedisCommandArgument) { - this.#executor = executor; - this.#firstKey = firstKey; - } - - commandsExecutor(command: RedisCommand, args: Array): this { - const transformedArguments = command.transformArguments(...args); - this.#firstKey ??= RedisCluster.extractFirstKey(command, args, transformedArguments); - return this.addCommand(undefined, transformedArguments, command.transformReply); - } - - addCommand( - firstKey: RedisCommandArgument | undefined, - args: RedisCommandArguments, - transformReply?: RedisCommand['transformReply'] - ): this { - this.#firstKey ??= firstKey; - this.#multi.addCommand(args, transformReply); - return this; - } - - functionsExecutor(fn: RedisFunction, args: Array, name: string): this { - const transformedArguments = this.#multi.addFunction(name, fn, args); - this.#firstKey ??= RedisCluster.extractFirstKey(fn, args, transformedArguments); - return this; - } - - scriptsExecutor(script: RedisScript, args: Array): this { - const transformedArguments = this.#multi.addScript(script, args); - this.#firstKey ??= RedisCluster.extractFirstKey(script, args, transformedArguments); - return this; - } - - async exec(execAsPipeline = false): Promise> { - if (execAsPipeline) { - return this.execAsPipeline(); - } - - return this.#multi.handleExecReplies( - await this.#executor(this.#multi.queue, this.#firstKey, RedisMultiCommand.generateChainId()) - ); - } - - EXEC = this.exec; - - async execAsPipeline(): Promise> { - return this.#multi.transformReplies( - await this.#executor(this.#multi.queue, this.#firstKey) - ); - } -} - -attachCommands({ - BaseClass: RedisClusterMultiCommand, - commands: COMMANDS, - executor: RedisClusterMultiCommand.prototype.commandsExecutor -}); +// import COMMANDS from './commands'; +// import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, ExcludeMappedString, RedisFunction } from '../commands'; +// import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; +// import { attachCommands, attachExtensions } from '../commander'; +// import RedisCluster from '.'; + +// type RedisClusterMultiCommandSignature< +// C extends RedisCommand, +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = (...args: Parameters) => RedisClusterMultiCommandType; + +// type WithCommands< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = { +// [P in keyof typeof COMMANDS]: RedisClusterMultiCommandSignature<(typeof COMMANDS)[P], M, F, S>; +// }; + +// type WithModules< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = { +// [P in keyof M as ExcludeMappedString

]: { +// [C in keyof M[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; +// }; +// }; + +// type WithFunctions< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = { +// [P in keyof F as ExcludeMappedString

]: { +// [FF in keyof F[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; +// }; +// }; + +// type WithScripts< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = { +// [P in keyof S as ExcludeMappedString

]: RedisClusterMultiCommandSignature; +// }; + +// export type RedisClusterMultiCommandType< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = RedisClusterMultiCommand & WithCommands & WithModules & WithFunctions & WithScripts; + +// export type InstantiableRedisClusterMultiCommandType< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// > = new (...args: ConstructorParameters) => RedisClusterMultiCommandType; + +// export type RedisClusterMultiExecutor = (queue: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => Promise>; + +// export default class RedisClusterMultiCommand { +// readonly #multi = new RedisMultiCommand(); +// readonly #executor: RedisClusterMultiExecutor; +// #firstKey: RedisCommandArgument | undefined; + +// static extend< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// >(extensions?: RedisExtensions): InstantiableRedisClusterMultiCommandType { +// return attachExtensions({ +// BaseClass: RedisClusterMultiCommand, +// modulesExecutor: RedisClusterMultiCommand.prototype.commandsExecutor, +// modules: extensions?.modules, +// functionsExecutor: RedisClusterMultiCommand.prototype.functionsExecutor, +// functions: extensions?.functions, +// scriptsExecutor: RedisClusterMultiCommand.prototype.scriptsExecutor, +// scripts: extensions?.scripts +// }); +// } + +// constructor(executor: RedisClusterMultiExecutor, firstKey?: RedisCommandArgument) { +// this.#executor = executor; +// this.#firstKey = firstKey; +// } + +// commandsExecutor(command: RedisCommand, args: Array): this { +// const transformedArguments = command.transformArguments(...args); +// this.#firstKey ??= RedisCluster.extractFirstKey(command, args, transformedArguments); +// return this.addCommand(undefined, transformedArguments, command.transformReply); +// } + +// addCommand( +// firstKey: RedisCommandArgument | undefined, +// args: RedisCommandArguments, +// transformReply?: RedisCommand['transformReply'] +// ): this { +// this.#firstKey ??= firstKey; +// this.#multi.addCommand(args, transformReply); +// return this; +// } + +// functionsExecutor(fn: RedisFunction, args: Array, name: string): this { +// const transformedArguments = this.#multi.addFunction(name, fn, args); +// this.#firstKey ??= RedisCluster.extractFirstKey(fn, args, transformedArguments); +// return this; +// } + +// scriptsExecutor(script: RedisScript, args: Array): this { +// const transformedArguments = this.#multi.addScript(script, args); +// this.#firstKey ??= RedisCluster.extractFirstKey(script, args, transformedArguments); +// return this; +// } + +// async exec(execAsPipeline = false): Promise> { +// if (execAsPipeline) { +// return this.execAsPipeline(); +// } + +// return this.#multi.handleExecReplies( +// await this.#executor(this.#multi.queue, this.#firstKey, RedisMultiCommand.generateChainId()) +// ); +// } + +// EXEC = this.exec; + +// async execAsPipeline(): Promise> { +// return this.#multi.transformReplies( +// await this.#executor(this.#multi.queue, this.#firstKey) +// ); +// } +// } + +// attachCommands({ +// BaseClass: RedisClusterMultiCommand, +// commands: COMMANDS, +// executor: RedisClusterMultiCommand.prototype.commandsExecutor +// }); diff --git a/packages/client/lib/command-options.ts b/packages/client/lib/command-options.ts deleted file mode 100644 index 8f91130b557..00000000000 --- a/packages/client/lib/command-options.ts +++ /dev/null @@ -1,14 +0,0 @@ -const symbol = Symbol('Command Options'); - -export type CommandOptions = T & { - readonly [symbol]: true; -}; - -export function commandOptions(options: T): CommandOptions { - (options as any)[symbol] = true; - return options as CommandOptions; -} - -export function isCommandOptions(options: any): options is CommandOptions { - return options?.[symbol] === true; -} diff --git a/packages/client/lib/commander.ts b/packages/client/lib/commander.ts index 1407a80344c..b1db7e701f4 100644 --- a/packages/client/lib/commander.ts +++ b/packages/client/lib/commander.ts @@ -1,163 +1,115 @@ - -import { ClientCommandOptions } from './client'; -import { CommandOptions, isCommandOptions } from './command-options'; -import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandReply, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts } from './commands'; - -type Instantiable = new (...args: Array) => T; - -type CommandsExecutor = - (command: C, args: Array, name: string) => unknown; - -interface AttachCommandsConfig { - BaseClass: Instantiable; - commands: Record; - executor: CommandsExecutor; +import { Command, CommanderConfig, RedisCommands, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, RespVersions } from './RESP/types'; + +interface AttachConfigOptions< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> { + BaseClass: new (...args: any) => any; + commands: RedisCommands; + createCommand(command: Command, resp: RespVersions): (...args: any) => any; + createModuleCommand(command: Command, resp: RespVersions): (...args: any) => any; + createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions): (...args: any) => any; + createScriptCommand(script: RedisScript, resp: RespVersions): (...args: any) => any; + config?: CommanderConfig; } -export function attachCommands({ - BaseClass, - commands, - executor -}: AttachCommandsConfig): void { - for (const [name, command] of Object.entries(commands)) { - BaseClass.prototype[name] = function (...args: Array): unknown { - return executor.call(this, command, args, name); - }; +export function attachConfig< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +>({ + BaseClass, + commands, + createCommand, + createModuleCommand, + createFunctionCommand, + createScriptCommand, + config +}: AttachConfigOptions) { + const RESP = config?.RESP ?? 2, + Class: any = class extends BaseClass {}; + + for (const [name, command] of Object.entries(commands)) { + Class.prototype[name] = createCommand(command, RESP); + } + + if (config?.modules) { + for (const [moduleName, module] of Object.entries(config.modules)) { + const fns = Object.create(null); + for (const [name, command] of Object.entries(module)) { + fns[name] = createModuleCommand(command, RESP); + } + + attachNamespace(Class.prototype, moduleName, fns); } -} - -interface AttachExtensionsConfig { - BaseClass: T; - modulesExecutor: CommandsExecutor; - modules?: RedisModules; - functionsExecutor: CommandsExecutor; - functions?: RedisFunctions; - scriptsExecutor: CommandsExecutor; - scripts?: RedisScripts; -} - -export function attachExtensions(config: AttachExtensionsConfig): any { - let Commander; + } - if (config.modules) { - Commander = attachWithNamespaces({ - BaseClass: config.BaseClass, - namespaces: config.modules, - executor: config.modulesExecutor - }); - } + if (config?.functions) { + for (const [library, commands] of Object.entries(config.functions)) { + const fns = Object.create(null); + for (const [name, command] of Object.entries(commands)) { + fns[name] = createFunctionCommand(name, command, RESP); + } - if (config.functions) { - Commander = attachWithNamespaces({ - BaseClass: Commander ?? config.BaseClass, - namespaces: config.functions, - executor: config.functionsExecutor - }); + attachNamespace(Class.prototype, library, fns); } + } - if (config.scripts) { - Commander ??= class extends config.BaseClass {}; - attachCommands({ - BaseClass: Commander, - commands: config.scripts, - executor: config.scriptsExecutor - }); + if (config?.scripts) { + for (const [name, script] of Object.entries(config.scripts)) { + Class.prototype[name] = createScriptCommand(script, RESP); } + } - return Commander ?? config.BaseClass; -} - -interface AttachWithNamespacesConfig { - BaseClass: Instantiable; - namespaces: Record>; - executor: CommandsExecutor; + return Class; } -function attachWithNamespaces({ - BaseClass, - namespaces, - executor -}: AttachWithNamespacesConfig): any { - const Commander = class extends BaseClass { - constructor(...args: Array) { - super(...args); - - for (const namespace of Object.keys(namespaces)) { - this[namespace] = Object.create(this[namespace], { - self: { - value: this - } - }); - } - } - }; - - for (const [namespace, commands] of Object.entries(namespaces)) { - Commander.prototype[namespace] = {}; - for (const [name, command] of Object.entries(commands)) { - Commander.prototype[namespace][name] = function (...args: Array): unknown { - return executor.call(this.self, command, args, name); - }; - } +function attachNamespace(prototype: any, name: PropertyKey, fns: any) { + Object.defineProperty(prototype, name, { + get() { + const value = Object.create(fns); + value.self = this; + Object.defineProperty(this, name, { value }); + return value; } - - return Commander; + }); } -export function transformCommandArguments( - command: RedisCommand, - args: Array -): { - args: RedisCommandArguments; - options: CommandOptions | undefined; -} { - let options; - if (isCommandOptions(args[0])) { - options = args[0]; - args = args.slice(1); - } +export function getTransformReply(command: Command, resp: RespVersions) { + switch (typeof command.transformReply) { + case 'function': + return command.transformReply; - return { - args: command.transformArguments(...args), - options - }; + case 'object': + return command.transformReply[resp]; + } } -export function transformLegacyCommandArguments(args: Array): Array { - return args.flat().map(arg => { - return typeof arg === 'number' || arg instanceof Date ? - arg.toString() : - arg; - }); -} +export function functionArgumentsPrefix(name: string, fn: RedisFunction) { + const prefix: Array = [ + fn.IS_READ_ONLY ? 'FCALL_RO' : 'FCALL', + name + ]; -export function transformCommandReply( - command: C, - rawReply: unknown, - preserved: unknown -): RedisCommandReply { - if (!command.transformReply) { - return rawReply as RedisCommandReply; - } + if (fn.NUMBER_OF_KEYS !== undefined) { + prefix.push(fn.NUMBER_OF_KEYS.toString()); + } - return command.transformReply(rawReply, preserved); + return prefix; } -export function fCallArguments( - name: RedisCommandArgument, - fn: RedisFunction, - args: RedisCommandArguments -): RedisCommandArguments { - const actualArgs: RedisCommandArguments = [ - fn.IS_READ_ONLY ? 'FCALL_RO' : 'FCALL', - name - ]; - - if (fn.NUMBER_OF_KEYS !== undefined) { - actualArgs.push(fn.NUMBER_OF_KEYS.toString()); - } +export function scriptArgumentsPrefix(script: RedisScript) { + const prefix: Array = [ + script.IS_READ_ONLY ? 'EVALSHA_RO' : 'EVALSHA', + script.SHA1 + ]; - actualArgs.push(...args); + if (script.NUMBER_OF_KEYS !== undefined) { + prefix.push(script.NUMBER_OF_KEYS.toString()); + } - return actualArgs; + return prefix; } diff --git a/packages/client/lib/commands/ACL_CAT.spec.ts b/packages/client/lib/commands/ACL_CAT.spec.ts index 521871a1c6b..0fc8b08b2fa 100644 --- a/packages/client/lib/commands/ACL_CAT.spec.ts +++ b/packages/client/lib/commands/ACL_CAT.spec.ts @@ -1,23 +1,31 @@ import { strict as assert } from 'assert'; -import testUtils from '../test-utils'; -import { transformArguments } from './ACL_CAT'; +import testUtils, { GLOBAL } from '../test-utils'; +import ACL_CAT from './ACL_CAT'; describe('ACL CAT', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'CAT'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ACL_CAT.transformArguments(), + ['ACL', 'CAT'] + ); + }); - it('with categoryName', () => { - assert.deepEqual( - transformArguments('dangerous'), - ['ACL', 'CAT', 'dangerous'] - ); - }); + it('with categoryName', () => { + assert.deepEqual( + ACL_CAT.transformArguments('dangerous'), + ['ACL', 'CAT', 'dangerous'] + ); }); + }); + + testUtils.testWithClient('client.aclCat', async client => { + const categories = await client.aclCat(); + assert.ok(Array.isArray(categories)); + for (const category of categories) { + assert.equal(typeof category, 'string'); + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_CAT.ts b/packages/client/lib/commands/ACL_CAT.ts index 161546cfbe9..dd4762239a7 100644 --- a/packages/client/lib/commands/ACL_CAT.ts +++ b/packages/client/lib/commands/ACL_CAT.ts @@ -1,13 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(categoryName?: RedisCommandArgument): RedisCommandArguments { - const args: RedisCommandArguments = ['ACL', 'CAT']; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(categoryName?: RedisArgument) { + const args: Array = ['ACL', 'CAT']; if (categoryName) { - args.push(categoryName); + args.push(categoryName); } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_DELUSER.spec.ts b/packages/client/lib/commands/ACL_DELUSER.spec.ts index 5c5ea2fa2a3..bccd2ccdc5e 100644 --- a/packages/client/lib/commands/ACL_DELUSER.spec.ts +++ b/packages/client/lib/commands/ACL_DELUSER.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ACL_DELUSER'; +import ACL_DELUSER from './ACL_DELUSER'; describe('ACL DELUSER', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('username'), - ['ACL', 'DELUSER', 'username'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ACL_DELUSER.transformArguments('username'), + ['ACL', 'DELUSER', 'username'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ACL', 'DELUSER', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + ACL_DELUSER.transformArguments(['1', '2']), + ['ACL', 'DELUSER', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.aclDelUser', async client => { - assert.equal( - await client.aclDelUser('dosenotexists'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.aclDelUser', async client => { + assert.equal( + typeof await client.aclDelUser('user'), + 'number' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_DELUSER.ts b/packages/client/lib/commands/ACL_DELUSER.ts index 25ed1a10300..c0f8e15d672 100644 --- a/packages/client/lib/commands/ACL_DELUSER.ts +++ b/packages/client/lib/commands/ACL_DELUSER.ts @@ -1,10 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export function transformArguments( - username: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['ACL', 'DELUSER'], username); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(username: RedisVariadicArgument) { + return pushVariadicArguments(['ACL', 'DELUSER'], username); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_DRYRUN.spec.ts b/packages/client/lib/commands/ACL_DRYRUN.spec.ts index 3154689c29e..051e6a561da 100644 --- a/packages/client/lib/commands/ACL_DRYRUN.spec.ts +++ b/packages/client/lib/commands/ACL_DRYRUN.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ACL_DRYRUN'; +import ACL_DRYRUN from './ACL_DRYRUN'; describe('ACL DRYRUN', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('default', ['GET', 'key']), - ['ACL', 'DRYRUN', 'default', 'GET', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_DRYRUN.transformArguments('default', ['GET', 'key']), + ['ACL', 'DRYRUN', 'default', 'GET', 'key'] + ); + }); - testUtils.testWithClient('client.aclDryRun', async client => { - assert.equal( - await client.aclDryRun('default', ['GET', 'key']), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.aclDryRun', async client => { + assert.equal( + await client.aclDryRun('default', ['GET', 'key']), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_DRYRUN.ts b/packages/client/lib/commands/ACL_DRYRUN.ts index 95eed95066c..257f0fe61e2 100644 --- a/packages/client/lib/commands/ACL_DRYRUN.ts +++ b/packages/client/lib/commands/ACL_DRYRUN.ts @@ -1,18 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, BlobStringReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments( - username: RedisCommandArgument, - command: Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(username: RedisArgument, command: Array) { return [ - 'ACL', - 'DRYRUN', - username, - ...command + 'ACL', + 'DRYRUN', + username, + ...command ]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> | BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_GENPASS.spec.ts b/packages/client/lib/commands/ACL_GENPASS.spec.ts index 3b2a022f972..7b489f1e9ec 100644 --- a/packages/client/lib/commands/ACL_GENPASS.spec.ts +++ b/packages/client/lib/commands/ACL_GENPASS.spec.ts @@ -1,23 +1,30 @@ import { strict as assert } from 'assert'; -import testUtils from '../test-utils'; -import { transformArguments } from './ACL_GENPASS'; +import testUtils, { GLOBAL } from '../test-utils'; +import ACL_GENPASS from './ACL_GENPASS'; describe('ACL GENPASS', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'GENPASS'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ACL_GENPASS.transformArguments(), + ['ACL', 'GENPASS'] + ); + }); - it('with bits', () => { - assert.deepEqual( - transformArguments(128), - ['ACL', 'GENPASS', '128'] - ); - }); + it('with bits', () => { + assert.deepEqual( + ACL_GENPASS.transformArguments(128), + ['ACL', 'GENPASS', '128'] + ); }); + }); + + testUtils.testWithClient('client.aclGenPass', async client => { + assert.equal( + typeof await client.aclGenPass(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_GENPASS.ts b/packages/client/lib/commands/ACL_GENPASS.ts index 91a71e220e0..be89ff90a9a 100644 --- a/packages/client/lib/commands/ACL_GENPASS.ts +++ b/packages/client/lib/commands/ACL_GENPASS.ts @@ -1,13 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(bits?: number): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(bits?: number) { const args = ['ACL', 'GENPASS']; if (bits) { - args.push(bits.toString()); + args.push(bits.toString()); } return args; -} + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; -export declare function transformReply(): RedisCommandArgument; diff --git a/packages/client/lib/commands/ACL_GETUSER.spec.ts b/packages/client/lib/commands/ACL_GETUSER.spec.ts index f91f2ff9e5c..6a0948d6f07 100644 --- a/packages/client/lib/commands/ACL_GETUSER.spec.ts +++ b/packages/client/lib/commands/ACL_GETUSER.spec.ts @@ -1,44 +1,34 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ACL_GETUSER'; +import ACL_GETUSER from './ACL_GETUSER'; describe('ACL GETUSER', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('username'), - ['ACL', 'GETUSER', 'username'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_GETUSER.transformArguments('username'), + ['ACL', 'GETUSER', 'username'] + ); + }); - testUtils.testWithClient('client.aclGetUser', async client => { - const expectedReply: any = { - passwords: [], - commands: '+@all', - }; + testUtils.testWithClient('client.aclGetUser', async client => { + const reply = await client.aclGetUser('default'); - if (testUtils.isVersionGreaterThan([7])) { - expectedReply.flags = ['on', 'nopass']; - expectedReply.keys = '~*'; - expectedReply.channels = '&*'; - expectedReply.selectors = []; - } else { - expectedReply.keys = ['*']; - expectedReply.selectors = undefined; + assert.ok(Array.isArray(reply.passwords)); + assert.equal(typeof reply.commands, 'string'); + assert.ok(Array.isArray(reply.flags)); - if (testUtils.isVersionGreaterThan([6, 2])) { - expectedReply.flags = ['on', 'allkeys', 'allchannels', 'allcommands', 'nopass']; - expectedReply.channels = ['*']; - } else { - expectedReply.flags = ['on', 'allkeys', 'allcommands', 'nopass']; - expectedReply.channels = undefined; - } - } + if (testUtils.isVersionGreaterThan([7])) { + assert.equal(typeof reply.keys, 'string'); + assert.equal(typeof reply.channels, 'string'); + assert.ok(Array.isArray(reply.selectors)); + } else { + assert.ok(Array.isArray(reply.keys)); - assert.deepEqual( - await client.aclGetUser('default'), - expectedReply - ); - }, GLOBAL.SERVERS.OPEN); + if (testUtils.isVersionGreaterThan([6, 2])) { + assert.ok(Array.isArray(reply.channels)); + } + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_GETUSER.ts b/packages/client/lib/commands/ACL_GETUSER.ts index 818a945bac1..c9489abaf51 100644 --- a/packages/client/lib/commands/ACL_GETUSER.ts +++ b/packages/client/lib/commands/ACL_GETUSER.ts @@ -1,40 +1,40 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; -export function transformArguments(username: RedisCommandArgument): RedisCommandArguments { - return ['ACL', 'GETUSER', username]; -} - -type AclGetUserRawReply = [ - 'flags', - Array, - 'passwords', - Array, - 'commands', - RedisCommandArgument, - 'keys', - Array | RedisCommandArgument, - 'channels', - Array | RedisCommandArgument, - 'selectors' | undefined, - Array> | undefined -]; +type AclUser = TuplesToMapReply<[ + [BlobStringReply<'flags'>, ArrayReply], + [BlobStringReply<'passwords'>, ArrayReply], + [BlobStringReply<'commands'>, BlobStringReply], + /** changed to BlobStringReply in 7.0 */ + [BlobStringReply<'keys'>, ArrayReply | BlobStringReply], + /** added in 6.2, changed to BlobStringReply in 7.0 */ + [BlobStringReply<'channels'>, ArrayReply | BlobStringReply], + /** added in 7.0 */ + [BlobStringReply<'selectors'>, ArrayReply, BlobStringReply], + [BlobStringReply<'keys'>, BlobStringReply], + [BlobStringReply<'channels'>, BlobStringReply] + ]>>], +]>; -interface AclUser { - flags: Array; - passwords: Array; - commands: RedisCommandArgument; - keys: Array | RedisCommandArgument; - channels: Array | RedisCommandArgument; - selectors?: Array>; -} - -export function transformReply(reply: AclGetUserRawReply): AclUser { - return { - flags: reply[1], - passwords: reply[3], - commands: reply[5], - keys: reply[7], - channels: reply[9], - selectors: reply[11] - }; -} +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(username: RedisArgument) { + return ['ACL', 'GETUSER', username]; + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + flags: reply[1], + passwords: reply[3], + commands: reply[5], + keys: reply[7], + channels: reply[9], + selectors: reply[11]?.map(selector => ({ + commands: selector[1], + keys: selector[3], + channels: selector[5] + })) + }), + 3: undefined as unknown as () => AclUser + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_LIST.spec.ts b/packages/client/lib/commands/ACL_LIST.spec.ts index 9f9156db7a2..8b2d875bda1 100644 --- a/packages/client/lib/commands/ACL_LIST.spec.ts +++ b/packages/client/lib/commands/ACL_LIST.spec.ts @@ -1,14 +1,22 @@ import { strict as assert } from 'assert'; -import testUtils from '../test-utils'; -import { transformArguments } from './ACL_LIST'; +import testUtils, { GLOBAL } from '../test-utils'; +import ACL_LIST from './ACL_LIST'; describe('ACL LIST', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'LIST'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_LIST.transformArguments(), + ['ACL', 'LIST'] + ); + }); + + testUtils.testWithClient('client.aclList', async client => { + const users = await client.aclList(); + assert.ok(Array.isArray(users)); + for (const user of users) { + assert.equal(typeof user, 'string'); + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_LIST.ts b/packages/client/lib/commands/ACL_LIST.ts index ae523fe9ce9..1a831a4987c 100644 --- a/packages/client/lib/commands/ACL_LIST.ts +++ b/packages/client/lib/commands/ACL_LIST.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['ACL', 'LIST']; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_LOAD.spec.ts b/packages/client/lib/commands/ACL_LOAD.spec.ts index 703d5eeb252..66afcf356a7 100644 --- a/packages/client/lib/commands/ACL_LOAD.spec.ts +++ b/packages/client/lib/commands/ACL_LOAD.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './ACL_SAVE'; +import ACL_LOAD from './ACL_LOAD'; -describe('ACL SAVE', () => { - testUtils.isVersionGreaterThanHook([6]); +describe('ACL LOAD', () => { + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'SAVE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_LOAD.transformArguments(), + ['ACL', 'LOAD'] + ); + }); }); diff --git a/packages/client/lib/commands/ACL_LOAD.ts b/packages/client/lib/commands/ACL_LOAD.ts index 88309102b95..39587829b17 100644 --- a/packages/client/lib/commands/ACL_LOAD.ts +++ b/packages/client/lib/commands/ACL_LOAD.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['ACL', 'LOAD']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_LOG.spec.ts b/packages/client/lib/commands/ACL_LOG.spec.ts index a8296d31da6..6b63b59f81c 100644 --- a/packages/client/lib/commands/ACL_LOG.spec.ts +++ b/packages/client/lib/commands/ACL_LOG.spec.ts @@ -1,53 +1,53 @@ import { strict as assert } from 'assert'; -import testUtils from '../test-utils'; -import { transformArguments, transformReply } from './ACL_LOG'; +import testUtils, { GLOBAL } from '../test-utils'; +import ACL_LOG from './ACL_LOG'; describe('ACL LOG', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'LOG'] - ); - }); - - it('with count', () => { - assert.deepEqual( - transformArguments(10), - ['ACL', 'LOG', '10'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ACL_LOG.transformArguments(), + ['ACL', 'LOG'] + ); }); - it('transformReply', () => { - assert.deepEqual( - transformReply([[ - 'count', - 1, - 'reason', - 'auth', - 'context', - 'toplevel', - 'object', - 'AUTH', - 'username', - 'someuser', - 'age-seconds', - '4.096', - 'client-info', - 'id=6 addr=127.0.0.1:63026 fd=8 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=48 qbuf-free=32720 obl=0 oll=0 omem=0 events=r cmd=auth user=default' - ]]), - [{ - count: 1, - reason: 'auth', - context: 'toplevel', - object: 'AUTH', - username: 'someuser', - ageSeconds: 4.096, - clientInfo: 'id=6 addr=127.0.0.1:63026 fd=8 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=48 qbuf-free=32720 obl=0 oll=0 omem=0 events=r cmd=auth user=default' - }] - ); + it('with count', () => { + assert.deepEqual( + ACL_LOG.transformArguments(10), + ['ACL', 'LOG', '10'] + ); }); + }); + + testUtils.testWithClient('client.aclLog', async client => { + // make sure to create at least one log + await Promise.all([ + client.aclSetUser('test', 'on >test'), + client.auth({ + username: 'test', + password: 'test' + }), + client.auth({ + username: 'default', + password: '' + }) + ]); + + const logs = await client.aclLog(); + assert.ok(Array.isArray(logs)); + for (const log of logs) { + + assert.equal(typeof log.count, 'number'); + assert.equal(typeof log.timestamp, 'number'); + assert.equal(typeof log.username, 'string'); + assert.equal(typeof log.clientId, 'string'); + assert.equal(typeof log.command, 'string'); + assert.equal(typeof log.args, 'string'); + assert.equal(typeof log.key, 'string'); + assert.equal(typeof log.result, 'number'); + assert.equal(typeof log.duration, 'number'); + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_LOG.ts b/packages/client/lib/commands/ACL_LOG.ts index 0fd9aa6f19d..4140111ecfc 100644 --- a/packages/client/lib/commands/ACL_LOG.ts +++ b/packages/client/lib/commands/ACL_LOG.ts @@ -1,50 +1,38 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { Resp2Reply } from '../RESP/types'; +import { ArrayReply, BlobStringReply, Command, NumberReply, TuplesToMapReply } from '../RESP/types'; -export function transformArguments(count?: number): RedisCommandArguments { +export type AclLogReply = ArrayReply, NumberReply], + [BlobStringReply<'reason'>, BlobStringReply], + [BlobStringReply<'context'>, BlobStringReply], + [BlobStringReply<'object'>, BlobStringReply], + [BlobStringReply<'username'>, BlobStringReply], + [BlobStringReply<'age-seconds'>, BlobStringReply], + [BlobStringReply<'client-info'>, BlobStringReply] +]>>; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(count?: number) { const args = ['ACL', 'LOG']; - if (count) { - args.push(count.toString()); + if (count !== undefined) { + args.push(count.toString()); } return args; -} - -type AclLogRawReply = [ - _: RedisCommandArgument, - count: number, - _: RedisCommandArgument, - reason: RedisCommandArgument, - _: RedisCommandArgument, - context: RedisCommandArgument, - _: RedisCommandArgument, - object: RedisCommandArgument, - _: RedisCommandArgument, - username: RedisCommandArgument, - _: RedisCommandArgument, - ageSeconds: RedisCommandArgument, - _: RedisCommandArgument, - clientInfo: RedisCommandArgument -]; - -interface AclLog { - count: number; - reason: RedisCommandArgument; - context: RedisCommandArgument; - object: RedisCommandArgument; - username: RedisCommandArgument; - ageSeconds: number; - clientInfo: RedisCommandArgument; -} - -export function transformReply(reply: Array): Array { - return reply.map(log => ({ - count: log[1], - reason: log[3], - context: log[5], - object: log[7], - username: log[9], - ageSeconds: Number(log[11]), - clientInfo: log[13] - })); -} + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + count: Number(reply[1]), + reason: reply[3], + context: reply[5], + object: reply[7], + username: reply[9], + 'age-seconds': Number(reply[11]), + 'client-info': reply[13] + }), + 3: undefined as unknown as () => AclLogReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_LOG_RESET.spec.ts b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts index 5d26e45d04f..7f3fbf1ade9 100644 --- a/packages/client/lib/commands/ACL_LOG_RESET.spec.ts +++ b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts @@ -1,14 +1,21 @@ import { strict as assert } from 'assert'; -import testUtils from '../test-utils'; -import { transformArguments } from './ACL_LOG_RESET'; +import testUtils, { GLOBAL } from '../test-utils'; +import ACL_LOG_RESET from './ACL_LOG_RESET'; describe('ACL LOG RESET', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'LOG', 'RESET'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_LOG_RESET.transformArguments(), + ['ACL', 'LOG', 'RESET'] + ); + }); + + testUtils.testWithClient('client.aclLogReset', async client => { + assert.equal( + await client.aclLogReset(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_LOG_RESET.ts b/packages/client/lib/commands/ACL_LOG_RESET.ts index 8ff0be4f8b9..91d58d538e9 100644 --- a/packages/client/lib/commands/ACL_LOG_RESET.ts +++ b/packages/client/lib/commands/ACL_LOG_RESET.ts @@ -1,7 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; +import ACL_LOG from './ACL_LOG'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: ACL_LOG.IS_READ_ONLY, + transformArguments() { return ['ACL', 'LOG', 'RESET']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_SAVE.spec.ts b/packages/client/lib/commands/ACL_SAVE.spec.ts index f4de312bb7a..065b75f93b6 100644 --- a/packages/client/lib/commands/ACL_SAVE.spec.ts +++ b/packages/client/lib/commands/ACL_SAVE.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './ACL_LOAD'; +import ACL_SAVE from './ACL_SAVE'; -describe('ACL LOAD', () => { - testUtils.isVersionGreaterThanHook([6]); +describe('ACL SAVE', () => { + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'LOAD'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_SAVE.transformArguments(), + ['ACL', 'SAVE'] + ); + }); }); diff --git a/packages/client/lib/commands/ACL_SAVE.ts b/packages/client/lib/commands/ACL_SAVE.ts index e57cd697297..8c2e2dab115 100644 --- a/packages/client/lib/commands/ACL_SAVE.ts +++ b/packages/client/lib/commands/ACL_SAVE.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['ACL', 'SAVE']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_SETUSER.ts b/packages/client/lib/commands/ACL_SETUSER.ts index a12cc8ed24e..c99fec3d9ba 100644 --- a/packages/client/lib/commands/ACL_SETUSER.ts +++ b/packages/client/lib/commands/ACL_SETUSER.ts @@ -1,11 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export function transformArguments( - username: RedisCommandArgument, - rule: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['ACL', 'SETUSER', username], rule); -} - -export declare function transformReply(): RedisCommandArgument; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(username: RedisArgument, rule: RedisVariadicArgument) { + return pushVariadicArguments(['ACL', 'SETUSER', username], rule); + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_USERS.ts b/packages/client/lib/commands/ACL_USERS.ts index 7970a262e26..ee8c619f25f 100644 --- a/packages/client/lib/commands/ACL_USERS.ts +++ b/packages/client/lib/commands/ACL_USERS.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['ACL', 'USERS']; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_WHOAMI.ts b/packages/client/lib/commands/ACL_WHOAMI.ts index 3c41171638e..5aa56c4d351 100644 --- a/packages/client/lib/commands/ACL_WHOAMI.ts +++ b/packages/client/lib/commands/ACL_WHOAMI.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { - return ['ACL', 'WHOAMI']; -} - -export declare function transformReply(): RedisCommandArgument; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['ACL', 'USERS']; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/APPEND.spec.ts b/packages/client/lib/commands/APPEND.spec.ts index 23353866843..4481c0571e9 100644 --- a/packages/client/lib/commands/APPEND.spec.ts +++ b/packages/client/lib/commands/APPEND.spec.ts @@ -1,11 +1,22 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './APPEND'; +import testUtils, { GLOBAL } from '../test-utils'; +import APPEND from './APPEND'; -describe('APPEND', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'value'), - ['APPEND', 'key', 'value'] - ); - }); +describe.only('APPEND', () => { + it('transformArguments', () => { + assert.deepEqual( + APPEND.transformArguments('key', 'value'), + ['APPEND', 'key', 'value'] + ); + }); + + testUtils.testAll('append', async client => { + assert.equal( + await client.append('key', 'value'), + 5 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/APPEND.ts b/packages/client/lib/commands/APPEND.ts index 66f7fc84798..1bc01024998 100644 --- a/packages/client/lib/commands/APPEND.ts +++ b/packages/client/lib/commands/APPEND.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - value: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, value: RedisArgument) { return ['APPEND', key, value]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ASKING.ts b/packages/client/lib/commands/ASKING.ts index 8a87806fe62..c6ada477ee4 100644 --- a/packages/client/lib/commands/ASKING.ts +++ b/packages/client/lib/commands/ASKING.ts @@ -1,7 +1,10 @@ -import { RedisCommandArguments, RedisCommandArgument } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['ASKING']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/AUTH.spec.ts b/packages/client/lib/commands/AUTH.spec.ts index 1907488346e..290ba936bf7 100644 --- a/packages/client/lib/commands/AUTH.spec.ts +++ b/packages/client/lib/commands/AUTH.spec.ts @@ -1,25 +1,25 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './AUTH'; +import AUTH from './AUTH'; describe('AUTH', () => { - describe('transformArguments', () => { - it('password only', () => { - assert.deepEqual( - transformArguments({ - password: 'password' - }), - ['AUTH', 'password'] - ); - }); + describe('transformArguments', () => { + it('password only', () => { + assert.deepEqual( + AUTH.transformArguments({ + password: 'password' + }), + ['AUTH', 'password'] + ); + }); - it('username & password', () => { - assert.deepEqual( - transformArguments({ - username: 'username', - password: 'password' - }), - ['AUTH', 'username', 'password'] - ); - }); + it('username & password', () => { + assert.deepEqual( + AUTH.transformArguments({ + username: 'username', + password: 'password' + }), + ['AUTH', 'username', 'password'] + ); }); + }); }); diff --git a/packages/client/lib/commands/AUTH.ts b/packages/client/lib/commands/AUTH.ts index 49b0df6d313..4c7a0b0c765 100644 --- a/packages/client/lib/commands/AUTH.ts +++ b/packages/client/lib/commands/AUTH.ts @@ -1,16 +1,23 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export interface AuthOptions { - username?: RedisCommandArgument; - password: RedisCommandArgument; + username?: RedisArgument; + password: RedisArgument; } -export function transformArguments({ username, password }: AuthOptions): RedisCommandArguments { - if (!username) { - return ['AUTH', password]; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments({ username, password }: AuthOptions) { + const args: Array = ['AUTH']; + + if (username !== undefined) { + args.push(username); } - return ['AUTH', username, password]; -} + args.push(password); -export declare function transformReply(): RedisCommandArgument; + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/BGREWRITEAOF.ts b/packages/client/lib/commands/BGREWRITEAOF.ts index be4ec2546ab..5f9a46e318f 100644 --- a/packages/client/lib/commands/BGREWRITEAOF.ts +++ b/packages/client/lib/commands/BGREWRITEAOF.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['BGREWRITEAOF']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BGSAVE.ts b/packages/client/lib/commands/BGSAVE.ts index 9c90f3485be..1cc60cb5dae 100644 --- a/packages/client/lib/commands/BGSAVE.ts +++ b/packages/client/lib/commands/BGSAVE.ts @@ -1,17 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -interface BgSaveOptions { - SCHEDULE?: true; -} - -export function transformArguments(options?: BgSaveOptions): RedisCommandArguments { - const args = ['BGSAVE']; - - if (options?.SCHEDULE) { - args.push('SCHEDULE'); - } - - return args; -} - -export declare function transformReply(): RedisCommandArgument; +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['BGSAVE']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BITCOUNT.ts b/packages/client/lib/commands/BITCOUNT.ts index 4bbd4f00911..6ec6b89be8b 100644 --- a/packages/client/lib/commands/BITCOUNT.ts +++ b/packages/client/lib/commands/BITCOUNT.ts @@ -1,33 +1,29 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -interface BitCountRange { - start: number; - end: number; - mode?: 'BYTE' | 'BIT'; +export interface BitCountRange { + start: number; + end: number; + mode?: 'BYTE' | 'BIT'; } -export function transformArguments( - key: RedisCommandArgument, - range?: BitCountRange -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, range?: BitCountRange) { const args = ['BITCOUNT', key]; if (range) { - args.push( - range.start.toString(), - range.end.toString() - ); - - if (range.mode) { - args.push(range.mode); - } + args.push( + range.start.toString(), + range.end.toString() + ); + + if (range.mode) { + args.push(range.mode); + } } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BITFIELD.spec.ts b/packages/client/lib/commands/BITFIELD.spec.ts index aaf0f93e501..9b94b19d240 100644 --- a/packages/client/lib/commands/BITFIELD.spec.ts +++ b/packages/client/lib/commands/BITFIELD.spec.ts @@ -1,46 +1,49 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BITFIELD'; +import BITFIELD from './BITFIELD'; describe('BITFIELD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [{ - operation: 'OVERFLOW', - behavior: 'WRAP' - }, { - operation: 'GET', - encoding: 'i8', - offset: 0 - }, { - operation: 'OVERFLOW', - behavior: 'SAT' - }, { - operation: 'SET', - encoding: 'i16', - offset: 1, - value: 0 - }, { - operation: 'OVERFLOW', - behavior: 'FAIL' - }, { - operation: 'INCRBY', - encoding: 'i32', - offset: 2, - increment: 1 - }]), - ['BITFIELD', 'key', 'OVERFLOW', 'WRAP', 'GET', 'i8', '0', 'OVERFLOW', 'SAT', 'SET', 'i16', '1', '0', 'OVERFLOW', 'FAIL', 'INCRBY', 'i32', '2', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BITFIELD.transformArguments('key', [{ + operation: 'OVERFLOW', + behavior: 'WRAP' + }, { + operation: 'GET', + encoding: 'i8', + offset: 0 + }, { + operation: 'OVERFLOW', + behavior: 'SAT' + }, { + operation: 'SET', + encoding: 'i16', + offset: 1, + value: 0 + }, { + operation: 'OVERFLOW', + behavior: 'FAIL' + }, { + operation: 'INCRBY', + encoding: 'i32', + offset: 2, + increment: 1 + }]), + ['BITFIELD', 'key', 'OVERFLOW', 'WRAP', 'GET', 'i8', '0', 'OVERFLOW', 'SAT', 'SET', 'i16', '1', '0', 'OVERFLOW', 'FAIL', 'INCRBY', 'i32', '2', '1'] + ); + }); - testUtils.testWithClient('client.bitField', async client => { - assert.deepEqual( - await client.bitField('key', [{ - operation: 'GET', - encoding: 'i8', - offset: 0 - }]), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bitField', async client => { + assert.deepEqual( + await client.bitField('key', [{ + operation: 'GET', + encoding: 'i8', + offset: 0 + }]), + [0] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BITFIELD.ts b/packages/client/lib/commands/BITFIELD.ts index 6a477b89f01..5d7d4bf7282 100644 --- a/packages/client/lib/commands/BITFIELD.ts +++ b/packages/client/lib/commands/BITFIELD.ts @@ -1,80 +1,87 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '../RESP/types'; export type BitFieldEncoding = `${'i' | 'u'}${number}`; export interface BitFieldOperation { - operation: S; + operation: S; } export interface BitFieldGetOperation extends BitFieldOperation<'GET'> { - encoding: BitFieldEncoding; - offset: number | string; + encoding: BitFieldEncoding; + offset: number | string; } -interface BitFieldSetOperation extends BitFieldOperation<'SET'> { - encoding: BitFieldEncoding; - offset: number | string; - value: number; +export interface BitFieldSetOperation extends BitFieldOperation<'SET'> { + encoding: BitFieldEncoding; + offset: number | string; + value: number; } -interface BitFieldIncrByOperation extends BitFieldOperation<'INCRBY'> { - encoding: BitFieldEncoding; - offset: number | string; - increment: number; +export interface BitFieldIncrByOperation extends BitFieldOperation<'INCRBY'> { + encoding: BitFieldEncoding; + offset: number | string; + increment: number; } -interface BitFieldOverflowOperation extends BitFieldOperation<'OVERFLOW'> { - behavior: string; +export interface BitFieldOverflowOperation extends BitFieldOperation<'OVERFLOW'> { + behavior: string; } -type BitFieldOperations = Array< - BitFieldGetOperation | - BitFieldSetOperation | - BitFieldIncrByOperation | - BitFieldOverflowOperation +export type BitFieldOperations = Array< + BitFieldGetOperation | + BitFieldSetOperation | + BitFieldIncrByOperation | + BitFieldOverflowOperation >; -export function transformArguments(key: string, operations: BitFieldOperations): Array { +export type BitFieldRoOperations = Array< + Omit +>; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, operations: BitFieldOperations) { const args = ['BITFIELD', key]; for (const options of operations) { - switch (options.operation) { - case 'GET': - args.push( - 'GET', - options.encoding, - options.offset.toString() - ); - break; + switch (options.operation) { + case 'GET': + args.push( + 'GET', + options.encoding, + options.offset.toString() + ); + break; - case 'SET': - args.push( - 'SET', - options.encoding, - options.offset.toString(), - options.value.toString() - ); - break; + case 'SET': + args.push( + 'SET', + options.encoding, + options.offset.toString(), + options.value.toString() + ); + break; - case 'INCRBY': - args.push( - 'INCRBY', - options.encoding, - options.offset.toString(), - options.increment.toString() - ); - break; + case 'INCRBY': + args.push( + 'INCRBY', + options.encoding, + options.offset.toString(), + options.increment.toString() + ); + break; - case 'OVERFLOW': - args.push( - 'OVERFLOW', - options.behavior - ); - break; - } + case 'OVERFLOW': + args.push( + 'OVERFLOW', + options.behavior + ); + break; + } } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BITFIELD_RO.spec.ts b/packages/client/lib/commands/BITFIELD_RO.spec.ts index 98399d5f235..2857155a60f 100644 --- a/packages/client/lib/commands/BITFIELD_RO.spec.ts +++ b/packages/client/lib/commands/BITFIELD_RO.spec.ts @@ -1,27 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BITFIELD_RO'; +import BITFIELD_RO from './BITFIELD_RO'; -describe('BITFIELD RO', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +describe('BITFIELD_RO', () => { + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [{ - encoding: 'i8', - offset: 0 - }]), - ['BITFIELD_RO', 'key', 'GET', 'i8', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BITFIELD_RO.transformArguments('key', [{ + encoding: 'i8', + offset: 0 + }]), + ['BITFIELD_RO', 'key', 'GET', 'i8', '0'] + ); + }); - testUtils.testWithClient('client.bitFieldRo', async client => { - assert.deepEqual( - await client.bitFieldRo('key', [{ - encoding: 'i8', - offset: 0 - }]), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bitFieldRo', async client => { + assert.deepEqual( + await client.bitFieldRo('key', [{ + encoding: 'i8', + offset: 0 + }]), + [0] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BITFIELD_RO.ts b/packages/client/lib/commands/BITFIELD_RO.ts index efd4eac188e..99e500abc04 100644 --- a/packages/client/lib/commands/BITFIELD_RO.ts +++ b/packages/client/lib/commands/BITFIELD_RO.ts @@ -1,26 +1,25 @@ +import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; import { BitFieldGetOperation } from './BITFIELD'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -type BitFieldRoOperations = Array< - Omit & - Partial> +export type BitFieldRoOperations = Array< + Omit >; -export function transformArguments(key: string, operations: BitFieldRoOperations): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, operations: BitFieldRoOperations) { const args = ['BITFIELD_RO', key]; for (const operation of operations) { - args.push( - 'GET', - operation.encoding, - operation.offset.toString() - ); + args.push( + 'GET', + operation.encoding, + operation.offset.toString() + ); } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BITOP.spec.ts b/packages/client/lib/commands/BITOP.spec.ts index 554530d56f4..c89d5ea0b37 100644 --- a/packages/client/lib/commands/BITOP.spec.ts +++ b/packages/client/lib/commands/BITOP.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BITOP'; +import BITOP from './BITOP'; describe('BITOP', () => { - describe('transformArguments', () => { - it('single key', () => { - assert.deepEqual( - transformArguments('AND', 'destKey', 'key'), - ['BITOP', 'AND', 'destKey', 'key'] - ); - }); - - it('multiple keys', () => { - assert.deepEqual( - transformArguments('AND', 'destKey', ['1', '2']), - ['BITOP', 'AND', 'destKey', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('single key', () => { + assert.deepEqual( + BITOP.transformArguments('AND', 'destKey', 'key'), + ['BITOP', 'AND', 'destKey', 'key'] + ); }); - testUtils.testWithClient('client.bitOp', async client => { - assert.equal( - await client.bitOp('AND', 'destKey', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + it('multiple keys', () => { + assert.deepEqual( + BITOP.transformArguments('AND', 'destKey', ['1', '2']), + ['BITOP', 'AND', 'destKey', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.bitOp', async cluster => { - assert.equal( - await cluster.bitOp('AND', '{tag}destKey', '{tag}key'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('client.bitOp', async client => { + assert.equal( + await client.bitOp('AND', '{tag}destKey', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BITOP.ts b/packages/client/lib/commands/BITOP.ts index e2953303d41..4c34845699e 100644 --- a/packages/client/lib/commands/BITOP.ts +++ b/packages/client/lib/commands/BITOP.ts @@ -1,16 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; +export type BitOperations = 'AND' | 'OR' | 'XOR' | 'NOT'; -type BitOperations = 'AND' | 'OR' | 'XOR' | 'NOT'; - -export function transformArguments( +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( operation: BitOperations, - destKey: RedisCommandArgument, - key: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['BITOP', operation, destKey], key); -} - -export declare function transformReply(): number; + destKey: RedisArgument, + key: RedisVariadicArgument + ) { + return pushVariadicArguments(['BITOP', operation, destKey], key); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BITPOS.ts b/packages/client/lib/commands/BITPOS.ts index a9a035fd9f2..5f8a1031a45 100644 --- a/packages/client/lib/commands/BITPOS.ts +++ b/packages/client/lib/commands/BITPOS.ts @@ -1,32 +1,31 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { BitValue } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, bit: BitValue, start?: number, end?: number, mode?: 'BYTE' | 'BIT' -): RedisCommandArguments { + ) { const args = ['BITPOS', key, bit.toString()]; if (typeof start === 'number') { - args.push(start.toString()); + args.push(start.toString()); } if (typeof end === 'number') { - args.push(end.toString()); + args.push(end.toString()); } if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BLMOVE.ts b/packages/client/lib/commands/BLMOVE.ts index ee808e70fcc..c7e4844375f 100644 --- a/packages/client/lib/commands/BLMOVE.ts +++ b/packages/client/lib/commands/BLMOVE.ts @@ -1,23 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { ListSide } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument, - sourceDirection: ListSide, - destinationDirection: ListSide, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + source: RedisArgument, + destination: RedisArgument, + sourceSide: ListSide, + destinationSide: ListSide, timeout: number -): RedisCommandArguments { + ) { return [ - 'BLMOVE', - source, - destination, - sourceDirection, - destinationDirection, - timeout.toString() + 'BLMOVE', + source, + destination, + sourceSide, + destinationSide, + timeout.toString() ]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BLMPOP.ts b/packages/client/lib/commands/BLMPOP.ts index 11bfad8b99b..32d249899b0 100644 --- a/packages/client/lib/commands/BLMPOP.ts +++ b/packages/client/lib/commands/BLMPOP.ts @@ -1,20 +1,22 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, Command } from '../RESP/types'; import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; +import LMPOP from './LMPOP'; -export const FIRST_KEY_INDEX = 3; - -export function transformArguments( +export default { + FIRST_KEY_INDEX: 3, + IS_READ_ONLY: false, + transformArguments( timeout: number, - keys: RedisCommandArgument | Array, + keys: RedisArgument | Array, side: ListSide, options?: LMPopOptions -): RedisCommandArguments { + ) { return transformLMPopArguments( - ['BLMPOP', timeout.toString()], - keys, - side, - options + ['BLMPOP', timeout.toString()], + keys, + side, + options ); -} - -export { transformReply } from './LMPOP'; + }, + transformReply: LMPOP.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BLPOP.ts b/packages/client/lib/commands/BLPOP.ts index 46ef41ad6f0..feb0fd65127 100644 --- a/packages/client/lib/commands/BLPOP.ts +++ b/packages/client/lib/commands/BLPOP.ts @@ -1,31 +1,23 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - keys: RedisCommandArgument | Array, +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument | Array, timeout: number -): RedisCommandArguments { - const args = pushVerdictArguments(['BLPOP'], keys); - + ) { + const args = pushVariadicArguments(['BRPOP'], key); args.push(timeout.toString()); - return args; -} - -type BLPopRawReply = null | [RedisCommandArgument, RedisCommandArgument]; - -type BLPopReply = null | { - key: RedisCommandArgument; - element: RedisCommandArgument; -}; - -export function transformReply(reply: BLPopRawReply): BLPopReply { + }, + transformReply(reply: NullReply | [BlobStringReply, BlobStringReply]) { if (reply === null) return null; return { - key: reply[0], - element: reply[1] + key: reply[0], + element: reply[1] }; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/BRPOP.ts b/packages/client/lib/commands/BRPOP.ts index b30e7e2cc29..64e8ed8404d 100644 --- a/packages/client/lib/commands/BRPOP.ts +++ b/packages/client/lib/commands/BRPOP.ts @@ -1,17 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; +import BLPOP from './BLPOP'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument | Array, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument | Array, timeout: number -): RedisCommandArguments { - const args = pushVerdictArguments(['BRPOP'], key); - + ) { + const args = pushVariadicArguments(['BRPOP'], key); args.push(timeout.toString()); - return args; -} - -export { transformReply } from './BLPOP'; + }, + transformReply: BLPOP.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BRPOPLPUSH.ts b/packages/client/lib/commands/BRPOPLPUSH.ts index 72c3e4aa5b2..d342ea75725 100644 --- a/packages/client/lib/commands/BRPOPLPUSH.ts +++ b/packages/client/lib/commands/BRPOPLPUSH.ts @@ -1,13 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + source: RedisArgument, + destination: RedisArgument, timeout: number -): RedisCommandArguments { + ) { return ['BRPOPLPUSH', source, destination, timeout.toString()]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BZMPOP.ts b/packages/client/lib/commands/BZMPOP.ts index e4e9699cbd4..936ccf800c8 100644 --- a/packages/client/lib/commands/BZMPOP.ts +++ b/packages/client/lib/commands/BZMPOP.ts @@ -18,3 +18,17 @@ export function transformArguments( } export { transformReply } from './ZMPOP'; + + +import { Command } from '../RESP/types'; +import ZMPOP from './ZMPOP'; + +export default { + IS_READ_ONLY: false, + FIRST_KEY_INDEX: 3, + transformArguments() { + return ['BZMPOP']; + }, + transformReply: ZMPOP.transformReply +} as const satisfies Command; + diff --git a/packages/client/lib/commands/BZPOPMAX.ts b/packages/client/lib/commands/BZPOPMAX.ts index 94a30fb8dce..be92c194ef1 100644 --- a/packages/client/lib/commands/BZPOPMAX.ts +++ b/packages/client/lib/commands/BZPOPMAX.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments, transformNumberInfinityReply, ZMember } from './generic-transformers'; +import { pushVariadicArguments, transformNumberInfinityReply, ZMember } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: RedisCommandArgument | Array, timeout: number ): RedisCommandArguments { - const args = pushVerdictArguments(['BZPOPMAX'], key); + const args = pushVariadicArguments(['BZPOPMAX'], key); args.push(timeout.toString()); diff --git a/packages/client/lib/commands/BZPOPMIN.ts b/packages/client/lib/commands/BZPOPMIN.ts index 40cb3d5dc75..02d9f9215bf 100644 --- a/packages/client/lib/commands/BZPOPMIN.ts +++ b/packages/client/lib/commands/BZPOPMIN.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: RedisCommandArgument | Array, timeout: number ): RedisCommandArguments { - const args = pushVerdictArguments(['BZPOPMIN'], key); + const args = pushVariadicArguments(['BZPOPMIN'], key); args.push(timeout.toString()); diff --git a/packages/client/lib/commands/CLIENT_CACHING.spec.ts b/packages/client/lib/commands/CLIENT_CACHING.spec.ts index d9cb9a3f796..bf8e4ed12bf 100644 --- a/packages/client/lib/commands/CLIENT_CACHING.spec.ts +++ b/packages/client/lib/commands/CLIENT_CACHING.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLIENT_CACHING'; +import CLIENT_CACHING from './CLIENT_CACHING'; describe('CLIENT CACHING', () => { - describe('transformArguments', () => { - it('true', () => { - assert.deepEqual( - transformArguments(true), - ['CLIENT', 'CACHING', 'YES'] - ); - }); + describe('transformArguments', () => { + it('true', () => { + assert.deepEqual( + CLIENT_CACHING.transformArguments(true), + ['CLIENT', 'CACHING', 'YES'] + ); + }); - it('false', () => { - assert.deepEqual( - transformArguments(false), - ['CLIENT', 'CACHING', 'NO'] - ); - }); + it('false', () => { + assert.deepEqual( + CLIENT_CACHING.transformArguments(false), + ['CLIENT', 'CACHING', 'NO'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLIENT_CACHING.ts b/packages/client/lib/commands/CLIENT_CACHING.ts index bc2fbe41e9d..35edf889fa7 100644 --- a/packages/client/lib/commands/CLIENT_CACHING.ts +++ b/packages/client/lib/commands/CLIENT_CACHING.ts @@ -1,11 +1,13 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(value: boolean): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(value: boolean) { return [ - 'CLIENT', - 'CACHING', - value ? 'YES' : 'NO' + 'CLIENT', + 'CACHING', + value ? 'YES' : 'NO' ]; -} - -export declare function transformReply(): 'OK' | Buffer; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts index 0a09713882f..cbd65768917 100644 --- a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts +++ b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLIENT_GETNAME'; +import CLIENT_GETNAME from './CLIENT_GETNAME'; describe('CLIENT GETNAME', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'GETNAME'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_GETNAME.transformArguments(), + ['CLIENT', 'GETNAME'] + ); + }); }); diff --git a/packages/client/lib/commands/CLIENT_GETNAME.ts b/packages/client/lib/commands/CLIENT_GETNAME.ts index da00539d7fb..5e3272553e9 100644 --- a/packages/client/lib/commands/CLIENT_GETNAME.ts +++ b/packages/client/lib/commands/CLIENT_GETNAME.ts @@ -1,7 +1,12 @@ -import { RedisCommandArguments } from '.'; +import { BlobStringReply, NullReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { - return ['CLIENT', 'GETNAME']; -} - -export declare function transformReply(): string | null; +export default { + IS_READ_ONLY: true, + transformArguments() { + return [ + 'CLIENT', + 'GETNAME' + ]; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts b/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts index 09dd9677e32..057eb237129 100644 --- a/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts +++ b/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLIENT_GETREDIR'; +import CLIENT_GETREDIR from './CLIENT_GETREDIR'; describe('CLIENT GETREDIR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'GETREDIR'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_GETREDIR.transformArguments(), + ['CLIENT', 'GETREDIR'] + ); + }); }); diff --git a/packages/client/lib/commands/CLIENT_GETREDIR.ts b/packages/client/lib/commands/CLIENT_GETREDIR.ts index d192adf284a..c2e68de5b6f 100644 --- a/packages/client/lib/commands/CLIENT_GETREDIR.ts +++ b/packages/client/lib/commands/CLIENT_GETREDIR.ts @@ -1,7 +1,9 @@ -import { RedisCommandArguments } from '.'; +import { NumberReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { - return ['CLIENT', 'GETREDIR']; -} - -export declare function transformReply(): number; +export default { + IS_READ_ONLY: true, + transformArguments() { + return ['CLIENT', 'GETREDIR'] + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_ID.spec.ts b/packages/client/lib/commands/CLIENT_ID.spec.ts index 6792a8c31be..28865a4ade7 100644 --- a/packages/client/lib/commands/CLIENT_ID.spec.ts +++ b/packages/client/lib/commands/CLIENT_ID.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_ID'; +import CLIENT_ID from './CLIENT_ID'; describe('CLIENT ID', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'ID'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_ID.transformArguments(), + ['CLIENT', 'ID'] + ); + }); - testUtils.testWithClient('client.clientId', async client => { - assert.equal( - typeof (await client.clientId()), - 'number' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientId', async client => { + assert.equal( + typeof (await client.clientId()), + 'number' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_ID.ts b/packages/client/lib/commands/CLIENT_ID.ts index a57e392ade6..cc298ed122e 100644 --- a/packages/client/lib/commands/CLIENT_ID.ts +++ b/packages/client/lib/commands/CLIENT_ID.ts @@ -1,7 +1,9 @@ -export const IS_READ_ONLY = true; +import { NumberReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + IS_READ_ONLY: true, + transformArguments() { return ['CLIENT', 'ID']; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_INFO.ts b/packages/client/lib/commands/CLIENT_INFO.ts index 7f6b6e1884e..1bd9fc2f25f 100644 --- a/packages/client/lib/commands/CLIENT_INFO.ts +++ b/packages/client/lib/commands/CLIENT_INFO.ts @@ -1,89 +1,115 @@ -export const IS_READ_ONLY = true; - -export function transformArguments(): Array { - return ['CLIENT', 'INFO']; -} +import { Command, VerbatimStringReply } from '../RESP/types'; export interface ClientInfoReply { - id: number; - addr: string; - laddr?: string; // 6.2 - fd: number; - name: string; - age: number; - idle: number; - flags: string; - db: number; - sub: number; - psub: number; - ssub?: number; // 7.0.3 - multi: number; - qbuf: number; - qbufFree: number; - argvMem?: number; // 6.0 - multiMem?: number; // 7.0 - obl: number; - oll: number; - omem: number; - totMem?: number; // 6.0 - events: string; - cmd: string; - user?: string; // 6.0 - redir?: number; // 6.2 - resp?: number; // 7.0 + id: number; + addr: string; + /** + * available since 6.2 + */ + laddr?: string; + fd: number; + name: string; + age: number; + idle: number; + flags: string; + db: number; + sub: number; + psub: number; + /** + * available since 7.0.3 + */ + ssub?: number; + multi: number; + qbuf: number; + qbufFree: number; + /** + * available since 6.0 + */ + argvMem?: number; + /** + * available since 7.0 + */ + multiMem?: number; + obl: number; + oll: number; + omem: number; + /** + * available since 6.0 + */ + totMem?: number; + events: string; + cmd: string; + /** + * available since 6.0 + */ + user?: string; + /** + * available since 6.2 + */ + redir?: number; + /** + * available since 7.0 + */ + resp?: number; } const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g; -export function transformReply(rawReply: string): ClientInfoReply { +export default { + IS_READ_ONLY: true, + transformArguments() { + return ['CLIENT', 'INFO'] + }, + transformReply(rawReply: VerbatimStringReply) { const map: Record = {}; - for (const item of rawReply.matchAll(CLIENT_INFO_REGEX)) { - map[item[1]] = item[2]; + for (const item of rawReply.toString().matchAll(CLIENT_INFO_REGEX)) { + map[item[1]] = item[2]; } const reply: ClientInfoReply = { - id: Number(map.id), - addr: map.addr, - fd: Number(map.fd), - name: map.name, - age: Number(map.age), - idle: Number(map.idle), - flags: map.flags, - db: Number(map.db), - sub: Number(map.sub), - psub: Number(map.psub), - multi: Number(map.multi), - qbuf: Number(map.qbuf), - qbufFree: Number(map['qbuf-free']), - argvMem: Number(map['argv-mem']), - obl: Number(map.obl), - oll: Number(map.oll), - omem: Number(map.omem), - totMem: Number(map['tot-mem']), - events: map.events, - cmd: map.cmd, - user: map.user + id: Number(map.id), + addr: map.addr, + fd: Number(map.fd), + name: map.name, + age: Number(map.age), + idle: Number(map.idle), + flags: map.flags, + db: Number(map.db), + sub: Number(map.sub), + psub: Number(map.psub), + multi: Number(map.multi), + qbuf: Number(map.qbuf), + qbufFree: Number(map['qbuf-free']), + argvMem: Number(map['argv-mem']), + obl: Number(map.obl), + oll: Number(map.oll), + omem: Number(map.omem), + totMem: Number(map['tot-mem']), + events: map.events, + cmd: map.cmd, + user: map.user }; if (map.laddr !== undefined) { - reply.laddr = map.laddr; + reply.laddr = map.laddr; } if (map.redir !== undefined) { - reply.redir = Number(map.redir); + reply.redir = Number(map.redir); } if (map.ssub !== undefined) { - reply.ssub = Number(map.ssub); + reply.ssub = Number(map.ssub); } if (map['multi-mem'] !== undefined) { - reply.multiMem = Number(map['multi-mem']); + reply.multiMem = Number(map['multi-mem']); } if (map.resp !== undefined) { - reply.resp = Number(map.resp); + reply.resp = Number(map.resp); } return reply; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_KILL.spec.ts b/packages/client/lib/commands/CLIENT_KILL.spec.ts index 2fe894f3610..4a64cb2c6e3 100644 --- a/packages/client/lib/commands/CLIENT_KILL.spec.ts +++ b/packages/client/lib/commands/CLIENT_KILL.spec.ts @@ -2,109 +2,109 @@ import { strict as assert } from 'assert'; import { ClientKillFilters, transformArguments } from './CLIENT_KILL'; describe('CLIENT KILL', () => { - describe('transformArguments', () => { - it('ADDRESS', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ADDRESS, - address: 'ip:6379' - }), - ['CLIENT', 'KILL', 'ADDR', 'ip:6379'] - ); - }); + describe('transformArguments', () => { + it('ADDRESS', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.ADDRESS, + address: 'ip:6379' + }), + ['CLIENT', 'KILL', 'ADDR', 'ip:6379'] + ); + }); - it('LOCAL_ADDRESS', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.LOCAL_ADDRESS, - localAddress: 'ip:6379' - }), - ['CLIENT', 'KILL', 'LADDR', 'ip:6379'] - ); - }); + it('LOCAL_ADDRESS', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.LOCAL_ADDRESS, + localAddress: 'ip:6379' + }), + ['CLIENT', 'KILL', 'LADDR', 'ip:6379'] + ); + }); - describe('ID', () => { - it('string', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ID, - id: '1' - }), - ['CLIENT', 'KILL', 'ID', '1'] - ); - }); + describe('ID', () => { + it('string', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.ID, + id: '1' + }), + ['CLIENT', 'KILL', 'ID', '1'] + ); + }); - it('number', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ID, - id: 1 - }), - ['CLIENT', 'KILL', 'ID', '1'] - ); - }); - }); + it('number', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.ID, + id: 1 + }), + ['CLIENT', 'KILL', 'ID', '1'] + ); + }); + }); - it('TYPE', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.TYPE, - type: 'master' - }), - ['CLIENT', 'KILL', 'TYPE', 'master'] - ); - }); + it('TYPE', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.TYPE, + type: 'master' + }), + ['CLIENT', 'KILL', 'TYPE', 'master'] + ); + }); - it('USER', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.USER, - username: 'username' - }), - ['CLIENT', 'KILL', 'USER', 'username'] - ); - }); + it('USER', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.USER, + username: 'username' + }), + ['CLIENT', 'KILL', 'USER', 'username'] + ); + }); + + describe('SKIP_ME', () => { + it('undefined', () => { + assert.deepEqual( + transformArguments(ClientKillFilters.SKIP_ME), + ['CLIENT', 'KILL', 'SKIPME'] + ); + }); - describe('SKIP_ME', () => { - it('undefined', () => { - assert.deepEqual( - transformArguments(ClientKillFilters.SKIP_ME), - ['CLIENT', 'KILL', 'SKIPME'] - ); - }); + it('true', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.SKIP_ME, + skipMe: true + }), + ['CLIENT', 'KILL', 'SKIPME', 'yes'] + ); + }); - it('true', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.SKIP_ME, - skipMe: true - }), - ['CLIENT', 'KILL', 'SKIPME', 'yes'] - ); - }); + it('false', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.SKIP_ME, + skipMe: false + }), + ['CLIENT', 'KILL', 'SKIPME', 'no'] + ); + }); + }); - it('false', () => { - assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.SKIP_ME, - skipMe: false - }), - ['CLIENT', 'KILL', 'SKIPME', 'no'] - ); - }); - }); - - it('TYPE & SKIP_ME', () => { - assert.deepEqual( - transformArguments([ - { - filter: ClientKillFilters.TYPE, - type: 'master' - }, - ClientKillFilters.SKIP_ME - ]), - ['CLIENT', 'KILL', 'TYPE', 'master', 'SKIPME'] - ); - }); + it('TYPE & SKIP_ME', () => { + assert.deepEqual( + transformArguments([ + { + filter: ClientKillFilters.TYPE, + type: 'master' + }, + ClientKillFilters.SKIP_ME + ]), + ['CLIENT', 'KILL', 'TYPE', 'master', 'SKIPME'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index adb2a5a6569..c1663f80e3a 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -1,95 +1,99 @@ -import { RedisCommandArguments } from '.'; - -export enum ClientKillFilters { - ADDRESS = 'ADDR', - LOCAL_ADDRESS = 'LADDR', - ID = 'ID', - TYPE = 'TYPE', - USER = 'USER', - SKIP_ME = 'SKIPME' -} +import { RedisArgument, NumberReply, Command } from '../RESP/types'; + +export const CLIENT_KILL_FILTERS = { + ADDRESS: 'ADDR', + LOCAL_ADDRESS: 'LADDR', + ID: 'ID', + TYPE: 'TYPE', + USER: 'USER', + SKIP_ME: 'SKIPME' +} as const; -interface KillFilter { - filter: T; +type CLIENT_KILL_FILTERS = typeof CLIENT_KILL_FILTERS; + +export interface ClientKillFilterCommon { + filter: T; } -interface KillAddress extends KillFilter { - address: `${string}:${number}`; +export interface ClientKillAddress extends ClientKillFilterCommon { + address: `${string}:${number}`; } -interface KillLocalAddress extends KillFilter { - localAddress: `${string}:${number}`; +export interface ClientKillLocalAddress extends ClientKillFilterCommon { + localAddress: `${string}:${number}`; } -interface KillId extends KillFilter { - id: number | `${number}`; +export interface ClientKillId extends ClientKillFilterCommon { + id: number | `${number}`; } -interface KillType extends KillFilter { - type: 'normal' | 'master' | 'replica' | 'pubsub'; +export interface ClientKillType extends ClientKillFilterCommon { + type: 'normal' | 'master' | 'replica' | 'pubsub'; } -interface KillUser extends KillFilter { - username: string; +export interface ClientKillUser extends ClientKillFilterCommon { + username: string; } -type KillSkipMe = ClientKillFilters.SKIP_ME | (KillFilter & { - skipMe: boolean; +export type ClientKillSkipMe = CLIENT_KILL_FILTERS['SKIP_ME'] | (ClientKillFilterCommon & { + skipMe: boolean; }); -type KillFilters = KillAddress | KillLocalAddress | KillId | KillType | KillUser | KillSkipMe; +export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe; -export function transformArguments(filters: KillFilters | Array): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(filters: ClientKillFilter | Array) { const args = ['CLIENT', 'KILL']; if (Array.isArray(filters)) { - for (const filter of filters) { - pushFilter(args, filter); - } + for (const filter of filters) { + pushFilter(args, filter); + } } else { - pushFilter(args, filters); + pushFilter(args, filters); } return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; + +function pushFilter(args: Array, filter: ClientKillFilter): void { + if (filter === CLIENT_KILL_FILTERS.SKIP_ME) { + args.push('SKIPME'); + return; + } + + args.push(filter.filter); + + switch (filter.filter) { + case CLIENT_KILL_FILTERS.ADDRESS: + args.push(filter.address); + break; + + case CLIENT_KILL_FILTERS.LOCAL_ADDRESS: + args.push(filter.localAddress); + break; + + case CLIENT_KILL_FILTERS.ID: + args.push( + typeof filter.id === 'number' ? + filter.id.toString() : + filter.id + ); + break; + + case CLIENT_KILL_FILTERS.TYPE: + args.push(filter.type); + break; + + case CLIENT_KILL_FILTERS.USER: + args.push(filter.username); + break; + + case CLIENT_KILL_FILTERS.SKIP_ME: + args.push(filter.skipMe ? 'yes' : 'no'); + break; + } } - -function pushFilter(args: RedisCommandArguments, filter: KillFilters): void { - if (filter === ClientKillFilters.SKIP_ME) { - args.push('SKIPME'); - return; - } - - args.push(filter.filter); - - switch(filter.filter) { - case ClientKillFilters.ADDRESS: - args.push(filter.address); - break; - - case ClientKillFilters.LOCAL_ADDRESS: - args.push(filter.localAddress); - break; - - case ClientKillFilters.ID: - args.push( - typeof filter.id === 'number' ? - filter.id.toString() : - filter.id - ); - break; - - case ClientKillFilters.TYPE: - args.push(filter.type); - break; - - case ClientKillFilters.USER: - args.push(filter.username); - break; - - case ClientKillFilters.SKIP_ME: - args.push(filter.skipMe ? 'yes' : 'no'); - break; - } -} - -export declare function transformReply(): number; diff --git a/packages/client/lib/commands/CLIENT_LIST.ts b/packages/client/lib/commands/CLIENT_LIST.ts index 6f71dc7d999..b1c2e5d2db4 100644 --- a/packages/client/lib/commands/CLIENT_LIST.ts +++ b/packages/client/lib/commands/CLIENT_LIST.ts @@ -1,43 +1,43 @@ -import { RedisCommandArguments, RedisCommandArgument } from '.'; -import { pushVerdictArguments } from './generic-transformers'; -import { transformReply as transformClientInfoReply, ClientInfoReply } from './CLIENT_INFO'; +import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; +import CLIENT_INFO, { ClientInfoReply } from './CLIENT_INFO'; -interface ListFilterType { - TYPE: 'NORMAL' | 'MASTER' | 'REPLICA' | 'PUBSUB'; - ID?: never; +export interface ListFilterType { + TYPE: 'NORMAL' | 'MASTER' | 'REPLICA' | 'PUBSUB'; + ID?: never; } -interface ListFilterId { - ID: Array; - TYPE?: never; +export interface ListFilterId { + ID: Array; + TYPE?: never; } export type ListFilter = ListFilterType | ListFilterId; -export const IS_READ_ONLY = true; - -export function transformArguments(filter?: ListFilter): RedisCommandArguments { - let args: RedisCommandArguments = ['CLIENT', 'LIST']; +export default { + IS_READ_ONLY: true, + transformArguments(filter?: ListFilter) { + let args: Array = ['CLIENT', 'LIST']; if (filter) { - if (filter.TYPE !== undefined) { - args.push('TYPE', filter.TYPE); - } else { - args.push('ID'); - args = pushVerdictArguments(args, filter.ID); - } + if (filter.TYPE !== undefined) { + args.push('TYPE', filter.TYPE); + } else { + args.push('ID'); + args = pushVariadicArguments(args, filter.ID); + } } return args; -} - -export function transformReply(rawReply: string): Array { - const split = rawReply.split('\n'), - length = split.length - 1, - reply: Array = []; + }, + transformReply(rawReply: VerbatimStringReply): Array { + const split = rawReply.toString().split('\n'), + length = split.length - 1, + reply: Array = []; for (let i = 0; i < length; i++) { - reply.push(transformClientInfoReply(split[i])); + reply.push(CLIENT_INFO.transformReply(split[i] as VerbatimStringReply)); } - + return reply; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_NO-EVICT.ts b/packages/client/lib/commands/CLIENT_NO-EVICT.ts index 86edbde1d23..226405d0320 100644 --- a/packages/client/lib/commands/CLIENT_NO-EVICT.ts +++ b/packages/client/lib/commands/CLIENT_NO-EVICT.ts @@ -1,11 +1,13 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(value: boolean): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(value: boolean) { return [ - 'CLIENT', - 'NO-EVICT', - value ? 'ON' : 'OFF' + 'CLIENT', + 'NO-EVICT', + value ? 'ON' : 'OFF' ]; -} - -export declare function transformReply(): 'OK' | Buffer; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_PAUSE.ts b/packages/client/lib/commands/CLIENT_PAUSE.ts index 090002272c9..b01e356cf54 100644 --- a/packages/client/lib/commands/CLIENT_PAUSE.ts +++ b/packages/client/lib/commands/CLIENT_PAUSE.ts @@ -1,20 +1,19 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments( - timeout: number, - mode?: 'WRITE' | 'ALL' -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(timeout: number, mode?: 'WRITE' | 'ALL') { const args = [ - 'CLIENT', - 'PAUSE', - timeout.toString() + 'CLIENT', + 'PAUSE', + timeout.toString() ]; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): 'OK' | Buffer; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_SETNAME.ts b/packages/client/lib/commands/CLIENT_SETNAME.ts index f5cf1c786fb..9208bba9243 100644 --- a/packages/client/lib/commands/CLIENT_SETNAME.ts +++ b/packages/client/lib/commands/CLIENT_SETNAME.ts @@ -1,7 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(name: RedisCommandArgument): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(name: RedisArgument) { return ['CLIENT', 'SETNAME', name]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_UNPAUSE.ts b/packages/client/lib/commands/CLIENT_UNPAUSE.ts index e139436d004..b2baf9c4bea 100644 --- a/packages/client/lib/commands/CLIENT_UNPAUSE.ts +++ b/packages/client/lib/commands/CLIENT_UNPAUSE.ts @@ -1,7 +1,9 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments() { return ['CLIENT', 'UNPAUSE']; -} - -export declare function transformReply(): 'OK' | Buffer; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts index 6cd357fb823..0841b42eca6 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts @@ -1,11 +1,13 @@ -import { RedisCommandArguments } from '.'; -import { pushVerdictNumberArguments } from './generic-transformers'; +import { SimpleStringReply, Command } from '../RESP/types'; +import { pushVariadicNumberArguments } from './generic-transformers'; -export function transformArguments(slots: number | Array): RedisCommandArguments { - return pushVerdictNumberArguments( - ['CLUSTER', 'ADDSLOTS'], - slots +export default { + IS_READ_ONLY: true, + transformArguments(slots: number | Array) { + return pushVariadicNumberArguments( + ['CLUSTER', 'ADDSLOTS'], + slots ); -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts index 6a8d6dc668f..ebbd4529e1e 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts @@ -1,13 +1,13 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; -export function transformArguments( - ranges: SlotRange | Array -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(ranges: SlotRange | Array) { return pushSlotRangesArguments( - ['CLUSTER', 'ADDSLOTSRANGE'], - ranges + ['CLUSTER', 'ADDSLOTSRANGE'], + ranges ); -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts index 7f81c8fdc42..c2587e82ae9 100644 --- a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts +++ b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts @@ -1,5 +1,9 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'BUMPEPOCH']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'BUMPED' | 'STILL'; +export default { + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'BUMPEPOCH']; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'BUMPED' | 'STILL'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts index 3fbc33052f8..1c33ca7453c 100644 --- a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts +++ b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts @@ -1,5 +1,9 @@ -export function transformArguments(nodeId: string): Array { - return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId]; -} +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export declare function transformReply(): number; +export default { + IS_READ_ONLY: true, + transformArguments(nodeId: RedisArgument) { + return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts index a5ff75e58a9..939d09d2082 100644 --- a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts @@ -1,5 +1,9 @@ -export function transformArguments(slot: number): Array { - return ['CLUSTER', 'COUNTKEYSINSLOT', slot.toString()]; -} +import { NumberReply, Command } from '../RESP/types'; -export declare function transformReply(): number; +export default { + IS_READ_ONLY: true, + transformArguments(slot: number) { + return ['CLUSTER', 'COUNT-FAILURE-REPORTS', slot.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTS.ts b/packages/client/lib/commands/CLUSTER_DELSLOTS.ts index bf8d9c18900..f9f408fa936 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTS.ts @@ -1,11 +1,13 @@ -import { RedisCommandArguments } from '.'; -import { pushVerdictNumberArguments } from './generic-transformers'; +import { SimpleStringReply, Command } from '../RESP/types'; +import { pushVariadicNumberArguments } from './generic-transformers'; -export function transformArguments(slots: number | Array): RedisCommandArguments { - return pushVerdictNumberArguments( - ['CLUSTER', 'DELSLOTS'], - slots +export default { + IS_READ_ONLY: true, + transformArguments(slots: number | Array) { + return pushVariadicNumberArguments( + ['CLUSTER', 'DELSLOTS'], + slots ); -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts index b136113c65f..81e46ba2dc7 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts @@ -1,13 +1,13 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; -export function transformArguments( - ranges: SlotRange | Array -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(ranges: SlotRange | Array) { return pushSlotRangesArguments( - ['CLUSTER', 'DELSLOTSRANGE'], - ranges + ['CLUSTER', 'DELSLOTSRANGE'], + ranges ); -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_FAILOVER.ts b/packages/client/lib/commands/CLUSTER_FAILOVER.ts index 9bc4b69f343..948d1f4864e 100644 --- a/packages/client/lib/commands/CLUSTER_FAILOVER.ts +++ b/packages/client/lib/commands/CLUSTER_FAILOVER.ts @@ -1,16 +1,22 @@ -export enum FailoverModes { - FORCE = 'FORCE', - TAKEOVER = 'TAKEOVER' -} +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(mode?: FailoverModes): Array { +export const FAILOVER_MODES = { + FORCE: 'FORCE', + TAKEOVER: 'TAKEOVER' +} as const; + +export type FailoverModes = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES]; + +export default { + IS_READ_ONLY: true, + transformArguments(mode?: FailoverModes) { const args = ['CLUSTER', 'FAILOVER']; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts index dfb1e1ccde8..d4f783cd114 100644 --- a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts @@ -1,5 +1,9 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'FLUSHSLOTS']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'OK'; +export default { + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'FLUSHSLOTS']; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_FORGET.ts b/packages/client/lib/commands/CLUSTER_FORGET.ts index fc557073aeb..19bc4657e4b 100644 --- a/packages/client/lib/commands/CLUSTER_FORGET.ts +++ b/packages/client/lib/commands/CLUSTER_FORGET.ts @@ -1,5 +1,9 @@ -export function transformArguments(nodeId: string): Array { - return ['CLUSTER', 'FORGET', nodeId]; -} +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'OK'; +export default { + IS_READ_ONLY: true, + transformArguments(nodeId: RedisArgument) { + return ['CLUSTER', 'FORGET', nodeId]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts index ec75b7b7336..b9970a07db8 100644 --- a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts @@ -1,5 +1,9 @@ -export function transformArguments(slot: number, count: number): Array { - return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()]; -} +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export declare function transformReply(): Array; +export default { + IS_READ_ONLY: true, + transformArguments(slot: number, count: number) { + return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()]; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_KEYSLOT.ts b/packages/client/lib/commands/CLUSTER_KEYSLOT.ts index 0af524ff128..fc68287eae5 100644 --- a/packages/client/lib/commands/CLUSTER_KEYSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_KEYSLOT.ts @@ -1,5 +1,8 @@ -export function transformArguments(key: string): Array { - return ['CLUSTER', 'KEYSLOT', key]; -} +import { Command, NumberReply, RedisArgument } from '../RESP/types'; -export declare function transformReply(): number; +export default { + transformArguments(key: RedisArgument) { + return ['CLUSTER', 'KEYSLOT', key]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_MEET.ts b/packages/client/lib/commands/CLUSTER_MEET.ts index e6ce1c1fce4..3e5d343b6f1 100644 --- a/packages/client/lib/commands/CLUSTER_MEET.ts +++ b/packages/client/lib/commands/CLUSTER_MEET.ts @@ -1,5 +1,8 @@ -export function transformArguments(ip: string, port: number): Array { - return ['CLUSTER', 'MEET', ip, port.toString()]; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'OK'; +export default { + transformArguments(host: string, port: number) { + return ['CLUSTER', 'MEET', host, port.toString()]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_MYID.ts b/packages/client/lib/commands/CLUSTER_MYID.ts index 2b61684634d..a7a4184f9c4 100644 --- a/packages/client/lib/commands/CLUSTER_MYID.ts +++ b/packages/client/lib/commands/CLUSTER_MYID.ts @@ -1,5 +1,8 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'MYID']; -} +import { BlobStringReply, Command } from "../RESP/types"; -export declare function transformReply(): string; +export default { + transformArguments() { + return ['CLUSTER', 'MYID']; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_REPLICATE.ts b/packages/client/lib/commands/CLUSTER_REPLICATE.ts index c74e1ec5960..c589ad33d71 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICATE.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICATE.ts @@ -1,5 +1,8 @@ -export function transformArguments(nodeId: string): Array { - return ['CLUSTER', 'REPLICATE', nodeId]; -} +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'OK'; +export default { + transformArguments(nodeId: RedisArgument) { + return ['CLUSTER', 'REPLICATE', nodeId]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.ts b/packages/client/lib/commands/CLUSTER_SLOTS.ts index 20d9782dd9e..5d4e5d7d0b8 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.ts @@ -1,46 +1,39 @@ -import { RedisCommandArguments } from '.'; +import { NumberReply, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { - return ['CLUSTER', 'SLOTS']; -} - -type ClusterSlotsRawNode = [ip: string, port: number, id: string]; +type RawNode = [ + host: BlobStringReply, + port: NumberReply, + id: BlobStringReply +]; -type ClusterSlotsRawReply = Array<[ - from: number, - to: number, - master: ClusterSlotsRawNode, - ...replicas: Array +type ClusterSlotsRawReply = ArrayReply<[ + from: NumberReply, + to: NumberReply, + master: RawNode, + ...replicas: Array ]>; -export interface ClusterSlotsNode { - ip: string; - port: number; - id: string; -}; +export type ClusterSlotsNode = ReturnType; -export type ClusterSlotsReply = Array<{ - from: number; - to: number; - master: ClusterSlotsNode; - replicas: Array; -}>; - -export function transformReply(reply: ClusterSlotsRawReply): ClusterSlotsReply { - return reply.map(([from, to, master, ...replicas]) => { - return { - from, - to, - master: transformNode(master), - replicas: replicas.map(transformNode) - }; - }); -} +export default { + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'SLOTS']; + }, + transformReply(reply: ClusterSlotsRawReply) { + return reply.map(([from, to, master, ...replicas]) => ({ + from, + to, + master: transformNode(master), + replicas: replicas.map(transformNode) + })); + } +} as const satisfies Command; -function transformNode([ip, port, id]: ClusterSlotsRawNode): ClusterSlotsNode { - return { - ip, - port, - id - }; +function transformNode([host, port, id ]: RawNode) { + return { + host, + port, + id + }; } diff --git a/packages/client/lib/commands/CONFIG_GET.ts b/packages/client/lib/commands/CONFIG_GET.ts index 3afc0eddfd0..45b8e61ac4a 100644 --- a/packages/client/lib/commands/CONFIG_GET.ts +++ b/packages/client/lib/commands/CONFIG_GET.ts @@ -1,5 +1,10 @@ -export function transformArguments(parameter: string): Array { - return ['CONFIG', 'GET', parameter]; -} +import { RedisArgument, Command } from '../RESP/types'; +import { transformTuplesReply } from './generic-transformers'; -export { transformTuplesReply as transformReply } from './generic-transformers'; +export default { + IS_READ_ONLY: true, + transformArguments(parameter: RedisArgument) { + return ['CONFIG', 'GET', parameter]; + }, + transformReply: transformTuplesReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CONFIG_RESETSTAT.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.ts index aba54bc3c7b..119bbd6051b 100644 --- a/packages/client/lib/commands/CONFIG_RESETSTAT.ts +++ b/packages/client/lib/commands/CONFIG_RESETSTAT.ts @@ -1,5 +1,8 @@ -export function transformArguments(): Array { - return ['CONFIG', 'RESETSTAT']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + transformArguments() { + return ['CONFIG', 'RESETSTAT']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CONFIG_REWRITE.ts b/packages/client/lib/commands/CONFIG_REWRITE.ts index 67984adf300..63f9acdb90e 100644 --- a/packages/client/lib/commands/CONFIG_REWRITE.ts +++ b/packages/client/lib/commands/CONFIG_REWRITE.ts @@ -1,5 +1,8 @@ -export function transformArguments(): Array { - return ['CONFIG', 'REWRITE']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + transformArguments() { + return ['CONFIG', 'REWRITE']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CONFIG_SET.ts b/packages/client/lib/commands/CONFIG_SET.ts index 41f40d035d2..426a314fc17 100644 --- a/packages/client/lib/commands/CONFIG_SET.ts +++ b/packages/client/lib/commands/CONFIG_SET.ts @@ -1,23 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command, RedisArgument } from '../RESP/types'; -type SingleParameter = [parameter: RedisCommandArgument, value: RedisCommandArgument]; +type SingleParameter = [parameter: RedisArgument, value: RedisArgument]; -type MultipleParameters = [config: Record]; +type MultipleParameters = [config: Record]; -export function transformArguments( +export default { + transformArguments( ...[parameterOrConfig, value]: SingleParameter | MultipleParameters -): RedisCommandArguments { - const args: RedisCommandArguments = ['CONFIG', 'SET']; - - if (typeof parameterOrConfig === 'string') { - args.push(parameterOrConfig, value!); + ) { + const args: Array = ['CONFIG', 'SET']; + + if (typeof parameterOrConfig === 'string' || Buffer.isBuffer(parameterOrConfig)) { + args.push(parameterOrConfig, value!); } else { - for (const [key, value] of Object.entries(parameterOrConfig)) { - args.push(key, value); - } + for (const [key, value] of Object.entries(parameterOrConfig)) { + args.push(key, value); + } } - + return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/COPY.ts b/packages/client/lib/commands/COPY.ts index b1e212a9956..2ef3c3224f8 100644 --- a/packages/client/lib/commands/COPY.ts +++ b/packages/client/lib/commands/COPY.ts @@ -1,28 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -interface CopyCommandOptions { - destinationDb?: number; - replace?: boolean; +export interface CopyCommandOptions { + DB?: number; + REPLACE?: boolean; } -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument, - options?: CopyCommandOptions -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(source: RedisArgument, destination: RedisArgument, options?: CopyCommandOptions) { const args = ['COPY', source, destination]; - if (options?.destinationDb) { - args.push('DB', options.destinationDb.toString()); + if (options?.DB) { + args.push('DB', options.DB.toString()); } - if (options?.replace) { - args.push('REPLACE'); + if (options?.REPLACE) { + args.push('REPLACE'); } return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DBSIZE.ts b/packages/client/lib/commands/DBSIZE.ts index 6b442ec33a2..c4d3c8d857a 100644 --- a/packages/client/lib/commands/DBSIZE.ts +++ b/packages/client/lib/commands/DBSIZE.ts @@ -1,7 +1,9 @@ -export const IS_READ_ONLY = true; +import { NumberReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + IS_READ_ONLY: true, + transformArguments() { return ['DBSIZE']; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DECR.ts b/packages/client/lib/commands/DECR.ts index 2b5f2c4bb5c..540148b7eed 100644 --- a/packages/client/lib/commands/DECR.ts +++ b/packages/client/lib/commands/DECR.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument) { return ['DECR', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DECRBY.ts b/packages/client/lib/commands/DECRBY.ts index afe4d79f0a1..4a22aeb34cd 100644 --- a/packages/client/lib/commands/DECRBY.ts +++ b/packages/client/lib/commands/DECRBY.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - decrement: number -): RedisCommandArguments { - return ['DECRBY', key, decrement.toString()]; -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, decrement: number) { + return ['DECR', key, decrement.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DEL.ts b/packages/client/lib/commands/DEL.ts index d60abe0f28e..faba0712cdb 100644 --- a/packages/client/lib/commands/DEL.ts +++ b/packages/client/lib/commands/DEL.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['DEL'], keys); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments(keys: RedisArgument | Array) { + return pushVariadicArguments(['DEL'], keys); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DISCARD.ts b/packages/client/lib/commands/DISCARD.ts index acad8a722e1..e153070c989 100644 --- a/packages/client/lib/commands/DISCARD.ts +++ b/packages/client/lib/commands/DISCARD.ts @@ -1,7 +1,8 @@ -import { RedisCommandArgument } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + transformArguments() { return ['DISCARD']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/DUMP.ts b/packages/client/lib/commands/DUMP.ts index fd4354db45c..06b12f06d09 100644 --- a/packages/client/lib/commands/DUMP.ts +++ b/packages/client/lib/commands/DUMP.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['DUMP', key]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ECHO.ts b/packages/client/lib/commands/ECHO.ts index 7a837307e2b..828ab0382e2 100644 --- a/packages/client/lib/commands/ECHO.ts +++ b/packages/client/lib/commands/ECHO.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(message: RedisCommandArgument): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(message: RedisArgument) { return ['ECHO', message]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EXISTS.ts b/packages/client/lib/commands/EXISTS.ts index 3bbc72ada46..2dfa5963d54 100644 --- a/packages/client/lib/commands/EXISTS.ts +++ b/packages/client/lib/commands/EXISTS.ts @@ -1,14 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['EXISTS'], keys); -} - -export declare function transformReply(): number; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(keys: RedisArgument | Array) { + return pushVariadicArguments(['EXISTS'], keys); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EXPIRE.ts b/packages/client/lib/commands/EXPIRE.ts index d9e85595c3b..3e57769bd6e 100644 --- a/packages/client/lib/commands/EXPIRE.ts +++ b/packages/client/lib/commands/EXPIRE.ts @@ -1,19 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, seconds: number, mode?: 'NX' | 'XX' | 'GT' | 'LT' -): RedisCommandArguments { + ) { const args = ['EXPIRE', key, seconds.toString()]; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EXPIREAT.ts b/packages/client/lib/commands/EXPIREAT.ts index 84e7760fe7f..b9b5986caca 100644 --- a/packages/client/lib/commands/EXPIREAT.ts +++ b/packages/client/lib/commands/EXPIREAT.ts @@ -1,24 +1,21 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { transformEXAT } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, timestamp: number | Date, mode?: 'NX' | 'XX' | 'GT' | 'LT' -): RedisCommandArguments { - const args = [ - 'EXPIREAT', - key, - transformEXAT(timestamp) - ]; + ) { + const args = ['EXPIRE', key, transformEXAT(timestamp)]; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EXPIRETIME.ts b/packages/client/lib/commands/EXPIRETIME.ts index 8c1bb075995..d6ac35aeb3d 100644 --- a/packages/client/lib/commands/EXPIRETIME.ts +++ b/packages/client/lib/commands/EXPIRETIME.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['EXPIRETIME', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FAILOVER.ts b/packages/client/lib/commands/FAILOVER.ts index c31dbc063de..0c1e710d321 100644 --- a/packages/client/lib/commands/FAILOVER.ts +++ b/packages/client/lib/commands/FAILOVER.ts @@ -1,33 +1,36 @@ +import { SimpleStringReply, Command } from '../RESP/types'; + interface FailoverOptions { - TO?: { - host: string; - port: number; - FORCE?: true; - }; - ABORT?: true; - TIMEOUT?: number; + TO?: { + host: string; + port: number; + FORCE?: true; + }; + ABORT?: true; + TIMEOUT?: number; } -export function transformArguments(options?: FailoverOptions): Array { +export default { + transformArguments(options?: FailoverOptions) { const args = ['FAILOVER']; if (options?.TO) { - args.push('TO', options.TO.host, options.TO.port.toString()); + args.push('TO', options.TO.host, options.TO.port.toString()); - if (options.TO.FORCE) { - args.push('FORCE'); - } + if (options.TO.FORCE) { + args.push('FORCE'); + } } if (options?.ABORT) { - args.push('ABORT'); + args.push('ABORT'); } if (options?.TIMEOUT) { - args.push('TIMEOUT', options.TIMEOUT.toString()); + args.push('TIMEOUT', options.TIMEOUT.toString()); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FLUSHALL.ts b/packages/client/lib/commands/FLUSHALL.ts index 967096bb9bd..bc41e24e0d5 100644 --- a/packages/client/lib/commands/FLUSHALL.ts +++ b/packages/client/lib/commands/FLUSHALL.ts @@ -1,16 +1,21 @@ -export enum RedisFlushModes { - ASYNC = 'ASYNC', - SYNC = 'SYNC' -} +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(mode?: RedisFlushModes): Array { - const args = ['FLUSHALL']; +export const REDIS_FLUSH_MODES = { + ASYNC: 'ASYNC', + SYNC: 'SYNC' +} as const; + +export type RedisFlushModes = typeof REDIS_FLUSH_MODES[keyof typeof REDIS_FLUSH_MODES]; +export default { + transformArguments(mode?: RedisFlushModes) { + const args = ['FLUSHALL']; + if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FLUSHDB.ts b/packages/client/lib/commands/FLUSHDB.ts index 5b8060df9eb..3dade5c0c50 100644 --- a/packages/client/lib/commands/FLUSHDB.ts +++ b/packages/client/lib/commands/FLUSHDB.ts @@ -1,13 +1,15 @@ +import { SimpleStringReply, Command } from '../RESP/types'; import { RedisFlushModes } from './FLUSHALL'; -export function transformArguments(mode?: RedisFlushModes): Array { +export default { + transformArguments(mode?: RedisFlushModes) { const args = ['FLUSHDB']; - + if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_DELETE.ts b/packages/client/lib/commands/FUNCTION_DELETE.ts index 4aa6be40e12..b614c5a9ecf 100644 --- a/packages/client/lib/commands/FUNCTION_DELETE.ts +++ b/packages/client/lib/commands/FUNCTION_DELETE.ts @@ -1,7 +1,10 @@ -import { RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(library: string): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(library: RedisArgument) { return ['FUNCTION', 'DELETE', library]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_DUMP.ts b/packages/client/lib/commands/FUNCTION_DUMP.ts index f608e078c27..cd53312caf9 100644 --- a/packages/client/lib/commands/FUNCTION_DUMP.ts +++ b/packages/client/lib/commands/FUNCTION_DUMP.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['FUNCTION', 'DUMP']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.ts b/packages/client/lib/commands/FUNCTION_FLUSH.ts index 143282de97f..b421181bf38 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.ts @@ -1,13 +1,17 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; +import { RedisFlushModes } from './FLUSHALL'; -export function transformArguments(mode?: 'ASYNC' | 'SYNC'): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(mode?: RedisFlushModes) { const args = ['FUNCTION', 'FLUSH']; - + if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_KILL.ts b/packages/client/lib/commands/FUNCTION_KILL.ts index 517272e8376..2e89746d593 100644 --- a/packages/client/lib/commands/FUNCTION_KILL.ts +++ b/packages/client/lib/commands/FUNCTION_KILL.ts @@ -1,7 +1,10 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['FUNCTION', 'KILL']; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_STATS.ts b/packages/client/lib/commands/FUNCTION_STATS.ts index bb5c957e78b..eacbcc19ad0 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.ts @@ -1,56 +1,87 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export function transformArguments(): RedisCommandArguments { +// export function transformArguments(): RedisCommandArguments { +// return ['FUNCTION', 'STATS']; +// } + +// type FunctionStatsRawReply = [ +// 'running_script', +// null | [ +// 'name', +// string, +// 'command', +// string, +// 'duration_ms', +// number +// ], +// 'engines', +// Array // "flat tuples" (there is no way to type that) +// // ...[string, [ +// // 'libraries_count', +// // number, +// // 'functions_count', +// // number +// // ]] +// ]; + +// interface FunctionStatsReply { +// runningScript: null | { +// name: string; +// command: string; +// durationMs: number; +// }; +// engines: Record; +// } + +// export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { +// const engines = Object.create(null); +// for (let i = 0; i < reply[3].length; i++) { +// engines[reply[3][i]] = { +// librariesCount: reply[3][++i][1], +// functionsCount: reply[3][i][3] +// }; +// } + +// return { +// runningScript: reply[1] === null ? null : { +// name: reply[1][1], +// command: reply[1][3], +// durationMs: reply[1][5] +// }, +// engines +// }; +// } + + +// #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } + +import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; + +type FunctionStatsReply = TuplesToMapReply<[ + [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ + [BlobStringReply<'name'>, BlobStringReply], + [BlobStringReply<'command'>, BlobStringReply], + [BlobStringReply<'duration_ms'>, NumberReply] + ]>], + [BlobStringReply<'engines'>, MapReply, NumberReply], + [BlobStringReply<'functions_count'>, NumberReply] + ]>>] +]>; + +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['FUNCTION', 'STATS']; -} - -type FunctionStatsRawReply = [ - 'running_script', - null | [ - 'name', - string, - 'command', - string, - 'duration_ms', - number - ], - 'engines', - Array // "flat tuples" (there is no way to type that) - // ...[string, [ - // 'libraries_count', - // number, - // 'functions_count', - // number - // ]] -]; - -interface FunctionStatsReply { - runningScript: null | { - name: string; - command: string; - durationMs: number; - }; - engines: Record; -} - -export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { - const engines = Object.create(null); - for (let i = 0; i < reply[3].length; i++) { - engines[reply[3][i]] = { - librariesCount: reply[3][++i][1], - functionsCount: reply[3][i][3] - }; - } - - return { - runningScript: reply[1] === null ? null : { - name: reply[1][1], - command: reply[1][3], - durationMs: reply[1][5] - }, - engines - }; -} + }, + transformReply: { + 2: (reply) => { + + }, + 3: undefined as unknown as () => + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOHASH.ts b/packages/client/lib/commands/GEOHASH.ts index 55e22c497e2..12bc9368ebd 100644 --- a/packages/client/lib/commands/GEOHASH.ts +++ b/packages/client/lib/commands/GEOHASH.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,7 +9,7 @@ export function transformArguments( key: RedisCommandArgument, member: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['GEOHASH', key], member); + return pushVariadicArguments(['GEOHASH', key], member); } export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEOPOS.ts b/packages/client/lib/commands/GEOPOS.ts index 0a5f079deeb..c2e0056155b 100644 --- a/packages/client/lib/commands/GEOPOS.ts +++ b/packages/client/lib/commands/GEOPOS.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -9,7 +9,7 @@ export function transformArguments( key: RedisCommandArgument, member: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['GEOPOS', key], member); + return pushVariadicArguments(['GEOPOS', key], member); } type GeoCoordinatesRawReply = Array<[RedisCommandArgument, RedisCommandArgument] | null>; diff --git a/packages/client/lib/commands/GET.ts b/packages/client/lib/commands/GET.ts index 127b0a56349..bb3db4f76d9 100644 --- a/packages/client/lib/commands/GET.ts +++ b/packages/client/lib/commands/GET.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['GET', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GETDEL.ts b/packages/client/lib/commands/GETDEL.ts index 2d91e6cc025..c11fd047df4 100644 --- a/packages/client/lib/commands/GETDEL.ts +++ b/packages/client/lib/commands/GETDEL.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['GETDEL', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GETEX.ts b/packages/client/lib/commands/GETEX.ts index 5b3cec6d887..201a888208a 100644 --- a/packages/client/lib/commands/GETEX.ts +++ b/packages/client/lib/commands/GETEX.ts @@ -1,39 +1,37 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { transformEXAT, transformPXAT } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -type GetExModes = { - EX: number; +export type GetExModes = { + EX: number; } | { - PX: number; + PX: number; } | { - EXAT: number | Date; + EXAT: number | Date; } | { - PXAT: number | Date; + PXAT: number | Date; } | { - PERSIST: true; + PERSIST: true; }; -export function transformArguments( - key: RedisCommandArgument, - mode: GetExModes -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, mode: GetExModes) { const args = ['GETEX', key]; if ('EX' in mode) { - args.push('EX', mode.EX.toString()); + args.push('EX', mode.EX.toString()); } else if ('PX' in mode) { - args.push('PX', mode.PX.toString()); + args.push('PX', mode.PX.toString()); } else if ('EXAT' in mode) { - args.push('EXAT', transformEXAT(mode.EXAT)); + args.push('EXAT', transformEXAT(mode.EXAT)); } else if ('PXAT' in mode) { - args.push('PXAT', transformPXAT(mode.PXAT)); + args.push('PXAT', transformPXAT(mode.PXAT)); } else { // PERSIST - args.push('PERSIST'); + args.push('PERSIST'); } return args; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GETRANGE.ts b/packages/client/lib/commands/GETRANGE.ts index 2d12d937cc6..e5357cd120b 100644 --- a/packages/client/lib/commands/GETRANGE.ts +++ b/packages/client/lib/commands/GETRANGE.ts @@ -1,15 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - start: number, - end: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, start: number, end: number) { return ['GETRANGE', key, start.toString(), end.toString()]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GETSET.ts b/packages/client/lib/commands/GETSET.ts index 87d111792c6..bbe920181b2 100644 --- a/packages/client/lib/commands/GETSET.ts +++ b/packages/client/lib/commands/GETSET.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - value: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, value: RedisArgument) { return ['GETSET', key, value]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HDEL.ts b/packages/client/lib/commands/HDEL.ts index 1a994e109d6..64aa55edda6 100644 --- a/packages/client/lib/commands/HDEL.ts +++ b/packages/client/lib/commands/HDEL.ts @@ -1,13 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['HDEL', key], field); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, field: RedisVariadicArgument) { + return pushVariadicArguments(['HDEL', key], field); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HELLO.ts b/packages/client/lib/commands/HELLO.ts index d943f2e4c35..d4784b67c40 100644 --- a/packages/client/lib/commands/HELLO.ts +++ b/packages/client/lib/commands/HELLO.ts @@ -1,65 +1,54 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { AuthOptions } from './AUTH'; - -interface HelloOptions { - protover: number; - auth?: Required; - clientName?: string; +import { RedisArgument, ArrayReply, BlobStringReply, Command, NumberReply, Resp2Reply, RespVersions, TuplesToMapReply } from '../RESP/types'; + +export interface HelloOptions { + AUTH?: { + username: RedisArgument; + password: RedisArgument; + }; + SETNAME?: string; } -export function transformArguments(options?: HelloOptions): RedisCommandArguments { - const args: RedisCommandArguments = ['HELLO']; - - if (options) { - args.push(options.protover.toString()); - - if (options.auth) { - args.push('AUTH', options.auth.username, options.auth.password); - } - - if (options.clientName) { - args.push('SETNAME', options.clientName); - } +export type HelloReply = TuplesToMapReply<[ + [BlobStringReply<'server'>, BlobStringReply], + [BlobStringReply<'version'>, BlobStringReply], + [BlobStringReply<'proto'>, NumberReply], + [BlobStringReply<'id'>, NumberReply], + [BlobStringReply<'mode'>, BlobStringReply], + [BlobStringReply<'role'>, BlobStringReply], + [BlobStringReply<'modules'>, ArrayReply] +]>; + +export default { + transformArguments(protoover: RespVersions, options?: HelloOptions) { + const args: Array = ['HELLO', protoover.toString()]; + + if (options?.AUTH) { + args.push( + 'AUTH', + options.AUTH.username, + options.AUTH.password + ); } + if (options?.SETNAME) { + args.push( + 'SETNAME', + options.SETNAME + ); + } + return args; -} - -type HelloRawReply = [ - _: never, - server: RedisCommandArgument, - _: never, - version: RedisCommandArgument, - _: never, - proto: number, - _: never, - id: number, - _: never, - mode: RedisCommandArgument, - _: never, - role: RedisCommandArgument, - _: never, - modules: Array -]; - -interface HelloTransformedReply { - server: RedisCommandArgument; - version: RedisCommandArgument; - proto: number; - id: number; - mode: RedisCommandArgument; - role: RedisCommandArgument; - modules: Array; -} - -export function transformReply(reply: HelloRawReply): HelloTransformedReply { - return { - server: reply[1], - version: reply[3], - proto: reply[5], - id: reply[7], - mode: reply[9], - role: reply[11], - modules: reply[13] - }; -} + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + server: reply[1], + version: reply[3], + proto: reply[5], + id: reply[7], + mode: reply[9], + role: reply[11], + modules: reply[13] + }), + 3: undefined as unknown as () => HelloReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/HEXISTS.ts b/packages/client/lib/commands/HEXISTS.ts index 289be20aa83..dc7e937ee78 100644 --- a/packages/client/lib/commands/HEXISTS.ts +++ b/packages/client/lib/commands/HEXISTS.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, field: RedisArgument) { return ['HEXISTS', key, field]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply<0 | 1> +} as const satisfies Command; diff --git a/packages/client/lib/commands/HGET.ts b/packages/client/lib/commands/HGET.ts index fcfd31e6172..d83f84e24fa 100644 --- a/packages/client/lib/commands/HGET.ts +++ b/packages/client/lib/commands/HGET.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, field: RedisArgument) { return ['HGET', key, field]; -} - -export declare function transformReply(): RedisCommandArgument | undefined; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HGETALL.ts b/packages/client/lib/commands/HGETALL.ts index bf51760ff0e..f1f0ac50bcb 100644 --- a/packages/client/lib/commands/HGETALL.ts +++ b/packages/client/lib/commands/HGETALL.ts @@ -1,13 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, MapReply, BlobStringReply, Command } from '../RESP/types'; +import { transformTuplesReply } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export const TRANSFORM_LEGACY_REPLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['HGETALL', key]; -} - -export { transformTuplesReply as transformReply } from './generic-transformers'; + }, + TRANSFORM_LEGACY_REPLY: true, + transformReply: { + 2: transformTuplesReply, + 3: undefined as unknown as () => MapReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/HINCRBY.ts b/packages/client/lib/commands/HINCRBY.ts index b2cf6eefe89..cb7f62ebef5 100644 --- a/packages/client/lib/commands/HINCRBY.ts +++ b/packages/client/lib/commands/HINCRBY.ts @@ -1,13 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + field: RedisArgument, increment: number -): RedisCommandArguments { - return ['HINCRBY', key, field, increment.toString()]; -} - -export declare function transformReply(): number; + ) { + return [ + 'HINCRBY', + key, + field, + increment.toString() + ]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HINCRBYFLOAT.ts b/packages/client/lib/commands/HINCRBYFLOAT.ts index 0e2de6e9b29..a4eea75c827 100644 --- a/packages/client/lib/commands/HINCRBYFLOAT.ts +++ b/packages/client/lib/commands/HINCRBYFLOAT.ts @@ -1,13 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + field: RedisArgument, increment: number -): RedisCommandArguments { - return ['HINCRBYFLOAT', key, field, increment.toString()]; -} - -export declare function transformReply(): number; + ) { + return [ + 'HINCRBYFLOAT', + key, + field, + increment.toString() + ]; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HKEYS.ts b/packages/client/lib/commands/HKEYS.ts index 3d629733d0e..00af43f7a40 100644 --- a/packages/client/lib/commands/HKEYS.ts +++ b/packages/client/lib/commands/HKEYS.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['HKEYS', key]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HLEN.ts b/packages/client/lib/commands/HLEN.ts index 15a93d408d7..8f156d303e2 100644 --- a/packages/client/lib/commands/HLEN.ts +++ b/packages/client/lib/commands/HLEN.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['HLEN', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HMGET.ts b/packages/client/lib/commands/HMGET.ts index 64b4014abeb..1c4acafdeef 100644 --- a/packages/client/lib/commands/HMGET.ts +++ b/packages/client/lib/commands/HMGET.ts @@ -1,15 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - fields: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['HMGET', key], fields); -} - -export declare function transformReply(): Array; +import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + fields: RedisVariadicArgument + ) { + return pushVariadicArguments(['HMGET'], fields); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HRANDFIELD.ts b/packages/client/lib/commands/HRANDFIELD.ts index a2c70aabd52..be878e244a0 100644 --- a/packages/client/lib/commands/HRANDFIELD.ts +++ b/packages/client/lib/commands/HRANDFIELD.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['HRANDFIELD', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT.ts b/packages/client/lib/commands/HRANDFIELD_COUNT.ts index 01b8df63273..4b6f42a115b 100644 --- a/packages/client/lib/commands/HRANDFIELD_COUNT.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT.ts @@ -1,16 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformHRandFieldArguments } from './HRANDFIELD'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './HRANDFIELD'; - -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformHRandFieldArguments(key), - count.toString() - ]; -} - -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, count: number) { + return ['HRANDFIELD', key, count.toString()]; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts deleted file mode 100644 index c4e6409a726..00000000000 --- a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HRANDFIELD_COUNT_WITHVALUES'; - -describe('HRANDFIELD COUNT WITHVALUES', () => { - testUtils.isVersionGreaterThanHook([6, 2, 5]); - - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['HRANDFIELD', 'key', '1', 'WITHVALUES'] - ); - }); - - testUtils.testWithClient('client.hRandFieldCountWithValues', async client => { - assert.deepEqual( - await client.hRandFieldCountWithValues('key', 1), - Object.create(null) - ); - }, GLOBAL.SERVERS.OPEN); -}); diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts index 3e09dbb9a14..2c7b17d5761 100644 --- a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts @@ -1,16 +1,36 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformHRandFieldCountArguments } from './HRANDFIELD_COUNT'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './HRANDFIELD_COUNT'; +export type HRandFieldCountWithValuesReply = Array<{ + field: BlobStringReply; + value: BlobStringReply; +}>; -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformHRandFieldCountArguments(key, count), - 'WITHVALUES' - ]; -} +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, count: number) { + return ['HRANDFIELD', key, count.toString(), 'WITHVALUES']; + }, + transformReply: { + 2: (rawReply: ArrayReply) => { + const reply: HRandFieldCountWithValuesReply = []; -export { transformTuplesReply as transformReply } from './generic-transformers'; + let i = 0; + while (i < rawReply.length) { + reply.push({ + field: rawReply[i++], + value: rawReply[i++] + }); + } + + return reply; + }, + 3: (reply: ArrayReply<[BlobStringReply, BlobStringReply]>) => { + return reply.map(([field, value]) => ({ + field, + value + })) satisfies HRandFieldCountWithValuesReply; + } + } +} as const satisfies Command; + \ No newline at end of file diff --git a/packages/client/lib/commands/HSCAN.ts b/packages/client/lib/commands/HSCAN.ts index ba18fb986bc..a23063e34f8 100644 --- a/packages/client/lib/commands/HSCAN.ts +++ b/packages/client/lib/commands/HSCAN.ts @@ -1,44 +1,34 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; import { ScanOptions, pushScanArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; +export interface HScanEntry { + field: BlobStringReply; + value: BlobStringReply; +} -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, cursor: number, options?: ScanOptions -): RedisCommandArguments { - return pushScanArguments([ - 'HSCAN', - key - ], cursor, options); -} - -type HScanRawReply = [RedisCommandArgument, Array]; - -export interface HScanTuple { - field: RedisCommandArgument; - value: RedisCommandArgument; -} - -interface HScanReply { - cursor: number; - tuples: Array; -} - -export function transformReply([cursor, rawTuples]: HScanRawReply): HScanReply { - const parsedTuples = []; - for (let i = 0; i < rawTuples.length; i += 2) { - parsedTuples.push({ - field: rawTuples[i], - value: rawTuples[i + 1] - }); + ) { + return pushScanArguments(['HSCAN', key], cursor, options); + }, + transformReply([cursor, rawEntries]: [BlobStringReply, Array]) { + const entries = []; + let i = 0; + while (i < rawEntries.length) { + entries.push({ + field: rawEntries[i++], + value: rawEntries[i++] + } satisfies HScanEntry); } return { - cursor: Number(cursor), - tuples: parsedTuples + cursor: Number(cursor), + entries }; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/HSET.ts b/packages/client/lib/commands/HSET.ts index 261ef98c779..7cb98c827bd 100644 --- a/packages/client/lib/commands/HSET.ts +++ b/packages/client/lib/commands/HSET.ts @@ -1,73 +1,75 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; +export type HashTypes = RedisArgument | number; -type Types = RedisCommandArgument | number; +type HSETObject = Record; -type HSETObject = Record; +type HSETMap = Map; -type HSETMap = Map; +type HSETTuples = Array<[HashTypes, HashTypes]> | Array; -type HSETTuples = Array<[Types, Types]> | Array; +type GenericArguments = [key: RedisArgument]; -type GenericArguments = [key: RedisCommandArgument]; - -type SingleFieldArguments = [...generic: GenericArguments, field: Types, value: Types]; +type SingleFieldArguments = [...generic: GenericArguments, field: HashTypes, value: HashTypes]; type MultipleFieldsArguments = [...generic: GenericArguments, value: HSETObject | HSETMap | HSETTuples]; -export function transformArguments(...[ key, value, fieldValue ]: SingleFieldArguments | MultipleFieldsArguments): RedisCommandArguments { - const args: RedisCommandArguments = ['HSET', key]; +export type HSETArguments = SingleFieldArguments | MultipleFieldsArguments; + +export default { + FIRST_KEY_INDEX: 1, + transformArguments(...[key, value, fieldValue]: SingleFieldArguments | MultipleFieldsArguments) { + const args: Array = ['HSET', key]; if (typeof value === 'string' || typeof value === 'number' || Buffer.isBuffer(value)) { - args.push( - convertValue(value), - convertValue(fieldValue!) - ); + args.push( + convertValue(value), + convertValue(fieldValue!) + ); } else if (value instanceof Map) { - pushMap(args, value); + pushMap(args, value); } else if (Array.isArray(value)) { - pushTuples(args, value); + pushTuples(args, value); } else { - pushObject(args, value); + pushObject(args, value); } return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; + +function pushMap(args: Array, map: HSETMap): void { + for (const [key, value] of map.entries()) { + args.push( + convertValue(key), + convertValue(value) + ); + } } -function pushMap(args: RedisCommandArguments, map: HSETMap): void { - for (const [key, value] of map.entries()) { - args.push( - convertValue(key), - convertValue(value) - ); +function pushTuples(args: Array, tuples: HSETTuples): void { + for (const tuple of tuples) { + if (Array.isArray(tuple)) { + pushTuples(args, tuple); + continue; } -} - -function pushTuples(args: RedisCommandArguments, tuples: HSETTuples): void { - for (const tuple of tuples) { - if (Array.isArray(tuple)) { - pushTuples(args, tuple); - continue; - } - args.push(convertValue(tuple)); - } + args.push(convertValue(tuple)); + } } -function pushObject(args: RedisCommandArguments, object: HSETObject): void { - for (const key of Object.keys(object)) { - args.push( - convertValue(key), - convertValue(object[key]) - ); - } +function pushObject(args: Array, object: HSETObject): void { + for (const key of Object.keys(object)) { + args.push( + convertValue(key), + convertValue(object[key]) + ); + } } -function convertValue(value: Types): RedisCommandArgument { - return typeof value === 'number' ? - value.toString() : - value; +function convertValue(value: HashTypes): RedisArgument { + return typeof value === 'number' ? + value.toString() : + value; } - -export declare function transformReply(): number; diff --git a/packages/client/lib/commands/HSETNX.ts b/packages/client/lib/commands/HSETNX.ts index 9ac6ef0edd8..d26c42a76b4 100644 --- a/packages/client/lib/commands/HSETNX.ts +++ b/packages/client/lib/commands/HSETNX.ts @@ -1,13 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, Command, NumberReply } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument, - value: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + field: RedisArgument, + value: RedisArgument + ) { return ['HSETNX', key, field, value]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply<0 | 1> +} as const satisfies Command; diff --git a/packages/client/lib/commands/HSTRLEN.ts b/packages/client/lib/commands/HSTRLEN.ts index a820e6c5643..61e2e1b1acd 100644 --- a/packages/client/lib/commands/HSTRLEN.ts +++ b/packages/client/lib/commands/HSTRLEN.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - field: RedisCommandArgument -): RedisCommandArguments { - return ['HSTRLEN', key, field]; -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, field: RedisArgument) { + return ['HSETLEN', key, field]; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HVALS.ts b/packages/client/lib/commands/HVALS.ts index ef63fdc7f8a..ee4193f5cec 100644 --- a/packages/client/lib/commands/HVALS.ts +++ b/packages/client/lib/commands/HVALS.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['HVALS', key]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/INCR.ts b/packages/client/lib/commands/INCR.ts index 2f9a9adfe2b..eb38256c9dc 100644 --- a/packages/client/lib/commands/INCR.ts +++ b/packages/client/lib/commands/INCR.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument) { return ['INCR', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/INCRBY.ts b/packages/client/lib/commands/INCRBY.ts index 75c61156d6b..5e94348fe63 100644 --- a/packages/client/lib/commands/INCRBY.ts +++ b/packages/client/lib/commands/INCRBY.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - increment: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, increment: number) { return ['INCRBY', key, increment.toString()]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/INCRBYFLOAT.ts b/packages/client/lib/commands/INCRBYFLOAT.ts index ace3702339e..16f59e68c17 100644 --- a/packages/client/lib/commands/INCRBYFLOAT.ts +++ b/packages/client/lib/commands/INCRBYFLOAT.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - increment: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, increment: number) { return ['INCRBYFLOAT', key, increment.toString()]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/INFO.ts b/packages/client/lib/commands/INFO.ts index 8ab24221b26..3adc3efd334 100644 --- a/packages/client/lib/commands/INFO.ts +++ b/packages/client/lib/commands/INFO.ts @@ -1,13 +1,15 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; -export function transformArguments(section?: string): Array { - const args = ['INFO']; +export default { + IS_READ_ONLY: true, + transformArguments(section?: RedisArgument) { + const args: Array = ['INFO']; if (section) { - args.push(section); + args.push(section); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => VerbatimStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/KEYS.ts b/packages/client/lib/commands/KEYS.ts index c96ee001436..507681a56aa 100644 --- a/packages/client/lib/commands/KEYS.ts +++ b/packages/client/lib/commands/KEYS.ts @@ -1,7 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(pattern: RedisCommandArgument): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(pattern: RedisArgument) { return ['KEYS', pattern]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LCS.ts b/packages/client/lib/commands/LCS.ts index b075b73e8a8..b798f12aa37 100644 --- a/packages/client/lib/commands/LCS.ts +++ b/packages/client/lib/commands/LCS.ts @@ -1,18 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key1: RedisCommandArgument, - key2: RedisCommandArgument -): RedisCommandArguments { - return [ - 'LCS', - key1, - key2 - ]; -} - -export declare function transformReply(): string | Buffer; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key1: RedisArgument, + key2: RedisArgument + ) { + return ['LCS', key1, key2]; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_IDX.ts b/packages/client/lib/commands/LCS_IDX.ts index 262a02ba4c6..b9961830578 100644 --- a/packages/client/lib/commands/LCS_IDX.ts +++ b/packages/client/lib/commands/LCS_IDX.ts @@ -1,42 +1,48 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { RangeReply, RawRangeReply, transformRangeReply } from './generic-transformers'; -import { transformArguments as transformLcsArguments } from './LCS'; +// import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +// import LCS from './LCS'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './LCS'; +// export interface LcsIdxOptions { +// MINMATCHLEN?: number; +// } -export function transformArguments( - key1: RedisCommandArgument, - key2: RedisCommandArgument -): RedisCommandArguments { - const args = transformLcsArguments(key1, key2); - args.push('IDX'); - return args; -} +// export type LcsIdxRange = TuplesReply<[ +// start: NumberReply, +// end: NumberReply +// ]>; -type RawReply = [ - 'matches', - Array<[ - key1: RawRangeReply, - key2: RawRangeReply - ]>, - 'len', - number -]; +// export type LcsIdxMatches = ArrayReply< +// TuplesReply<[ +// key1: LcsIdxRange, +// key2: LcsIdxRange +// ]> +// >; -interface Reply { - matches: Array<{ - key1: RangeReply; - key2: RangeReply; - }>; - length: number; -} +// export type LcsIdxReply = TuplesToMapReply<[ +// [BlobStringReply<'matches'>, LcsIdxMatches], +// [BlobStringReply<'len'>, NumberReply] +// ]>; -export function transformReply(reply: RawReply): Reply { - return { - matches: reply[1].map(([key1, key2]) => ({ - key1: transformRangeReply(key1), - key2: transformRangeReply(key2) - })), - length: reply[3] - }; -} +// export default { +// FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, +// IS_READ_ONLY: LCS.IS_READ_ONLY, +// transformArguments( +// key1: RedisArgument, +// key2: RedisArgument, +// options?: LcsIdxOptions +// ) { +// const args = LCS.transformArguments(key1, key2); + +// if (options?.MINMATCHLEN) { +// args.push('MINMATCHLEN', options.MINMATCHLEN.toString()); +// } + +// return args; +// }, +// transformReply: { +// 2: (reply: Resp2Reply) => ({ +// matches: reply[1], +// len: reply[2] +// }), +// 3: undefined as unknown as () => LcsIdxReply +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts index 989870d6ca2..2b6a87672a9 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts @@ -1,45 +1,47 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { RangeReply, RawRangeReply, transformRangeReply } from './generic-transformers'; -import { transformArguments as transformLcsArguments } from './LCS'; +// import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +// import LCS from './LCS'; +// import { LcsIdxRange } from './LCS_IDX'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './LCS'; +// interface LcsIdxOptions { +// MINMATCHLEN?: number; +// } -export function transformArguments( - key1: RedisCommandArgument, - key2: RedisCommandArgument -): RedisCommandArguments { - const args = transformLcsArguments(key1, key2); - args.push('IDX', 'WITHMATCHLEN'); - return args; -} +// export type LcsIdxWithMatchLenMatches = ArrayReply< +// TuplesReply<[ +// key1: LcsIdxRange, +// key2: LcsIdxRange, +// len: NumberReply +// ]> +// >; -type RawReply = [ - 'matches', - Array<[ - key1: RawRangeReply, - key2: RawRangeReply, - length: number - ]>, - 'len', - number -]; +// export type LcsIdxReply = TuplesToMapReply<[ +// [BlobStringReply<'matches'>, LcsIdxWithMatchLenMatches], +// [BlobStringReply<'len'>, NumberReply] +// ]>; -interface Reply { - matches: Array<{ - key1: RangeReply; - key2: RangeReply; - length: number; - }>; - length: number; -} +// export default { +// FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, +// IS_READ_ONLY: LCS.IS_READ_ONLY, +// transformArguments( +// key1: RedisArgument, +// key2: RedisArgument, +// options?: LcsIdxOptions +// ) { +// const args = LCS.transformArguments(key1, key2); -export function transformReply(reply: RawReply): Reply { - return { - matches: reply[1].map(([key1, key2, length]) => ({ - key1: transformRangeReply(key1), - key2: transformRangeReply(key2), - length - })), - length: reply[3] - }; -} +// if (options?.MINMATCHLEN) { +// args.push('MINMATCHLEN', options.MINMATCHLEN.toString()); +// } + +// args.push('WITHMATCHLEN'); + +// return args; +// }, +// transformReply: { +// 2: (reply: Resp2Reply) => ({ +// matches: reply[1], +// len: reply[2] +// }), +// 3: undefined as unknown as () => LcsIdxReply +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_LEN.ts b/packages/client/lib/commands/LCS_LEN.ts index a5121e4c13f..d5d0e77e4d6 100644 --- a/packages/client/lib/commands/LCS_LEN.ts +++ b/packages/client/lib/commands/LCS_LEN.ts @@ -1,15 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformLcsArguments } from './LCS'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import LCS from './LCS'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './LCS'; - -export function transformArguments( - key1: RedisCommandArgument, - key2: RedisCommandArgument -): RedisCommandArguments { - const args = transformLcsArguments(key1, key2); +export default { + FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, + IS_READ_ONLY: LCS.IS_READ_ONLY, + transformArguments( + key1: RedisArgument, + key2: RedisArgument + ) { + const args = LCS.transformArguments(key1, key2); args.push('LEN'); return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LINDEX.ts b/packages/client/lib/commands/LINDEX.ts index 8e74ad8aae6..0478bf9dc41 100644 --- a/packages/client/lib/commands/LINDEX.ts +++ b/packages/client/lib/commands/LINDEX.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - index: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, index: number) { return ['LINDEX', key, index.toString()]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LINSERT.ts b/packages/client/lib/commands/LINSERT.ts index 0a8e1f32ba4..4bdc77de5a4 100644 --- a/packages/client/lib/commands/LINSERT.ts +++ b/packages/client/lib/commands/LINSERT.ts @@ -1,22 +1,23 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; type LInsertPosition = 'BEFORE' | 'AFTER'; -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, position: LInsertPosition, - pivot: RedisCommandArgument, - element: RedisCommandArgument -): RedisCommandArguments { + pivot: RedisArgument, + element: RedisArgument + ) { return [ - 'LINSERT', - key, - position, - pivot, - element + 'LINSERT', + key, + position, + pivot, + element ]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LLEN.ts b/packages/client/lib/commands/LLEN.ts index 3410e57d424..dda59ddf291 100644 --- a/packages/client/lib/commands/LLEN.ts +++ b/packages/client/lib/commands/LLEN.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['LLEN', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LMOVE.ts b/packages/client/lib/commands/LMOVE.ts index 849c6385f5a..3ec118b9905 100644 --- a/packages/client/lib/commands/LMOVE.ts +++ b/packages/client/lib/commands/LMOVE.ts @@ -1,21 +1,21 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { ListSide } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + source: RedisArgument, + destination: RedisArgument, sourceSide: ListSide, destinationSide: ListSide -): RedisCommandArguments { + ) { return [ - 'LMOVE', - source, - destination, - sourceSide, - destinationSide, + 'LMOVE', + source, + destination, + sourceSide, + destinationSide, ]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts index 29d868b982f..d52245251b4 100644 --- a/packages/client/lib/commands/LMPOP.ts +++ b/packages/client/lib/commands/LMPOP.ts @@ -1,22 +1,22 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; - -export function transformArguments( - keys: RedisCommandArgument | Array, +export default { + FIRST_KEY_INDEX: 2, + transformArguments( + keys: RedisArgument | Array, side: ListSide, options?: LMPopOptions -): RedisCommandArguments { + ) { return transformLMPopArguments( - ['LMPOP'], - keys, - side, - options + ['LMPOP'], + keys, + side, + options ); -} - -export declare function transformReply(): null | [ - key: string, - elements: Array -]; + }, + transformReply: undefined as unknown as () => NullReply | TuplesReply<[ + key: BlobStringReply, + elements: Array + ]> +} as const satisfies Command; diff --git a/packages/client/lib/commands/LOLWUT.ts b/packages/client/lib/commands/LOLWUT.ts index 5d5fc726065..8536711d322 100644 --- a/packages/client/lib/commands/LOLWUT.ts +++ b/packages/client/lib/commands/LOLWUT.ts @@ -1,19 +1,20 @@ -import { RedisCommandArgument } from '.'; +import { BlobStringReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(version?: number, ...optionalArguments: Array): Array { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(version?: number, ...optionalArguments: Array) { const args = ['LOLWUT']; if (version) { - args.push( - 'VERSION', - version.toString(), - ...optionalArguments.map(String), - ); + args.push( + 'VERSION', + version.toString(), + ...optionalArguments.map(String), + ); } return args; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPOP.ts b/packages/client/lib/commands/LPOP.ts index 5dd1bea5196..7c85c30f9a1 100644 --- a/packages/client/lib/commands/LPOP.ts +++ b/packages/client/lib/commands/LPOP.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument) { return ['LPOP', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPOP_COUNT.ts b/packages/client/lib/commands/LPOP_COUNT.ts index 021517b018a..6cbc8564abb 100644 --- a/packages/client/lib/commands/LPOP_COUNT.ts +++ b/packages/client/lib/commands/LPOP_COUNT.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NullReply, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { +export default { + IS_READ_ONLY: false, + FIRST_KEY_INDEX: 2, + transformArguments(key: RedisArgument, count: number) { return ['LPOP', key, count.toString()]; -} - -export declare function transformReply(): Array | null; + }, + transformReply: undefined as unknown as () => NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPOS.ts b/packages/client/lib/commands/LPOS.ts index 1f2e34ab88e..047d80d7c29 100644 --- a/packages/client/lib/commands/LPOS.ts +++ b/packages/client/lib/commands/LPOS.ts @@ -1,30 +1,31 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; +import { RedisArgument, NumberReply, NullReply, Command } from '../RESP/types'; export interface LPosOptions { - RANK?: number; - MAXLEN?: number; + RANK?: number; + MAXLEN?: number; } -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + element: RedisArgument, options?: LPosOptions -): RedisCommandArguments { + ) { const args = ['LPOS', key, element]; - if (typeof options?.RANK === 'number') { + if (options) { + if (typeof options.RANK === 'number') { args.push('RANK', options.RANK.toString()); - } + } - if (typeof options?.MAXLEN === 'number') { + if (typeof options.MAXLEN === 'number') { args.push('MAXLEN', options.MAXLEN.toString()); + } } return args; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPOS_COUNT.ts b/packages/client/lib/commands/LPOS_COUNT.ts index 0549df82db5..91bf602f39c 100644 --- a/packages/client/lib/commands/LPOS_COUNT.ts +++ b/packages/client/lib/commands/LPOS_COUNT.ts @@ -1,27 +1,28 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { LPosOptions } from './LPOS'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; +import LPOS, { LPosOptions } from './LPOS'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './LPOS'; - -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: LPOS.FIRST_KEY_INDEX, + IS_READ_ONLY: LPOS.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + element: RedisArgument, count: number, options?: LPosOptions -): RedisCommandArguments { + ) { const args = ['LPOS', key, element]; if (typeof options?.RANK === 'number') { - args.push('RANK', options.RANK.toString()); + args.push('RANK', options.RANK.toString()); } args.push('COUNT', count.toString()); if (typeof options?.MAXLEN === 'number') { - args.push('MAXLEN', options.MAXLEN.toString()); + args.push('MAXLEN', options.MAXLEN.toString()); } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPUSH.ts b/packages/client/lib/commands/LPUSH.ts index 7144b146e27..72d4d7b6768 100644 --- a/packages/client/lib/commands/LPUSH.ts +++ b/packages/client/lib/commands/LPUSH.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - elements: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['LPUSH', key], elements);} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, elements: RedisArgument | Array) { + return pushVariadicArguments(['LPUSH', key], elements); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LPUSHX.ts b/packages/client/lib/commands/LPUSHX.ts index 0b518add6da..1265c56a262 100644 --- a/packages/client/lib/commands/LPUSHX.ts +++ b/packages/client/lib/commands/LPUSHX.ts @@ -1,13 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['LPUSHX', key], element); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, elements: RedisArgument | Array) { + return pushVariadicArguments(['LPUSHX', key], elements); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LRANGE.ts b/packages/client/lib/commands/LRANGE.ts index df12c57d804..4b4b3488baa 100644 --- a/packages/client/lib/commands/LRANGE.ts +++ b/packages/client/lib/commands/LRANGE.ts @@ -1,20 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, start: number, stop: number -): RedisCommandArguments { +) { return [ - 'LRANGE', - key, - start.toString(), - stop.toString() + 'LRANGE', + key, + start.toString(), + stop.toString() ]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LREM.ts b/packages/client/lib/commands/LREM.ts index b4951334888..dbd2002be8b 100644 --- a/packages/client/lib/commands/LREM.ts +++ b/packages/client/lib/commands/LREM.ts @@ -1,18 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, count: number, - element: RedisCommandArgument -): RedisCommandArguments { + element: RedisArgument + ) { return [ - 'LREM', - key, - count.toString(), - element + 'LREM', + key, + count.toString(), + element ]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LSET.ts b/packages/client/lib/commands/LSET.ts index 33c7b4cc060..3c5b7867469 100644 --- a/packages/client/lib/commands/LSET.ts +++ b/packages/client/lib/commands/LSET.ts @@ -1,18 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, index: number, - element: RedisCommandArgument -): RedisCommandArguments { + element: RedisArgument + ) { return [ - 'LSET', - key, - index.toString(), - element + 'LREM', + key, + index.toString(), + element ]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LTRIM.ts b/packages/client/lib/commands/LTRIM.ts index 668497cdde6..d4c69513165 100644 --- a/packages/client/lib/commands/LTRIM.ts +++ b/packages/client/lib/commands/LTRIM.ts @@ -1,18 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, start: number, - stop: number -): RedisCommandArguments { + stop: RedisArgument + ) { return [ - 'LTRIM', - key, - start.toString(), - stop.toString() + 'LREM', + key, + start.toString(), + stop.toString() ]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MGET.ts b/packages/client/lib/commands/MGET.ts index 6635a2ca20c..0f0f9e52ffb 100644 --- a/packages/client/lib/commands/MGET.ts +++ b/packages/client/lib/commands/MGET.ts @@ -1,13 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - keys: Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(keys: Array) { return ['MGET', ...keys]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => Array +} as const satisfies Command; diff --git a/packages/client/lib/commands/MIGRATE.ts b/packages/client/lib/commands/MIGRATE.ts index aaff3164081..adb1ae8d197 100644 --- a/packages/client/lib/commands/MIGRATE.ts +++ b/packages/client/lib/commands/MIGRATE.ts @@ -1,65 +1,66 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { AuthOptions } from './AUTH'; interface MigrateOptions { - COPY?: true; - REPLACE?: true; - AUTH?: AuthOptions; + COPY?: true; + REPLACE?: true; + AUTH?: AuthOptions; } -export function transformArguments( - host: RedisCommandArgument, +export default { + transformArguments( + host: RedisArgument, port: number, - key: RedisCommandArgument | Array, + key: RedisArgument | Array, destinationDb: number, timeout: number, options?: MigrateOptions -): RedisCommandArguments { + ) { const args = ['MIGRATE', host, port.toString()], - isKeyArray = Array.isArray(key); - + isKeyArray = Array.isArray(key); + if (isKeyArray) { - args.push(''); + args.push(''); } else { - args.push(key); + args.push(key); } - + args.push( - destinationDb.toString(), - timeout.toString() + destinationDb.toString(), + timeout.toString() ); - + if (options?.COPY) { - args.push('COPY'); + args.push('COPY'); } - + if (options?.REPLACE) { - args.push('REPLACE'); + args.push('REPLACE'); } - + if (options?.AUTH) { - if (options.AUTH.username) { - args.push( - 'AUTH2', - options.AUTH.username, - options.AUTH.password - ); - } else { - args.push( - 'AUTH', - options.AUTH.password - ); - } - } - - if (isKeyArray) { + if (options.AUTH.username) { args.push( - 'KEYS', - ...key + 'AUTH2', + options.AUTH.username, + options.AUTH.password ); + } else { + args.push( + 'AUTH', + options.AUTH.password + ); + } } - + + if (isKeyArray) { + args.push( + 'KEYS', + ...key + ); + } + return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_LIST.ts b/packages/client/lib/commands/MODULE_LIST.ts index d75b2428308..56a61095282 100644 --- a/packages/client/lib/commands/MODULE_LIST.ts +++ b/packages/client/lib/commands/MODULE_LIST.ts @@ -1,5 +1,23 @@ -export function transformArguments(): Array { - return ['MODULE', 'LIST']; -} +import { ArrayReply, BlobStringReply, NumberReply, Command, Resp2Reply, TuplesToMapReply } from '../RESP/types'; + +export type ModuleListReply = ArrayReply, BlobStringReply], + [BlobStringReply<'version'>, NumberReply], +]>>; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['MODULE', 'LIST']; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply.map(module => ({ + name: module[1], + version: module[3] + })); + }, + 3: undefined as unknown as () => ModuleListReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts index b44b4b57ce6..ed0520adf48 100644 --- a/packages/client/lib/commands/MODULE_LOAD.ts +++ b/packages/client/lib/commands/MODULE_LOAD.ts @@ -1,11 +1,11 @@ -export function transformArguments(path: string, moduleArgs?: Array): Array { - const args = ['MODULE', 'LOAD', path]; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; - if (moduleArgs) { - args.push(...moduleArgs); - } - - return args; -} - -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(path: RedisArgument, moduleArguments?: Array) { + return pushVariadicArguments(['MODULE', 'LOAD', path], moduleArguments); + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_UNLOAD.ts b/packages/client/lib/commands/MODULE_UNLOAD.ts index d5927778fe6..4f47abbdead 100644 --- a/packages/client/lib/commands/MODULE_UNLOAD.ts +++ b/packages/client/lib/commands/MODULE_UNLOAD.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string): Array { - return ['MODULE', 'UNLOAD', name]; -} +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(name: RedisArgument) { + return ['MODULE', 'UNLOAD', name]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MOVE.ts b/packages/client/lib/commands/MOVE.ts index 17cc6742c5f..60aac4b1457 100644 --- a/packages/client/lib/commands/MOVE.ts +++ b/packages/client/lib/commands/MOVE.ts @@ -1,7 +1,9 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export function transformArguments(key: string, db: number): Array { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, db: number) { return ['MOVE', key, db.toString()]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MSET.ts b/packages/client/lib/commands/MSET.ts index bd7111659d1..136fde3e7f7 100644 --- a/packages/client/lib/commands/MSET.ts +++ b/packages/client/lib/commands/MSET.ts @@ -1,24 +1,27 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export type MSetArguments = - Array<[RedisCommandArgument, RedisCommandArgument]> | - Array | - Record; + Array<[RedisArgument, RedisArgument]> | + Array | + Record; -export function transformArguments(toSet: MSetArguments): RedisCommandArguments { - const args: RedisCommandArguments = ['MSET']; +export function mSetArguments(command: string, toSet: MSetArguments) { + const args: Array = [command]; - if (Array.isArray(toSet)) { - args.push(...toSet.flat()); - } else { - for (const key of Object.keys(toSet)) { - args.push(key, toSet[key]); - } + if (Array.isArray(toSet)) { + args.push(...toSet.flat()); + } else { + for (const tuple of Object.entries(toSet)) { + args.push(...tuple); } + } - return args; + return args; } -export declare function transformReply(): RedisCommandArgument; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: mSetArguments.bind(undefined, 'MSET'), + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/MSETNX.ts b/packages/client/lib/commands/MSETNX.ts index 0ef33936114..4867b3ea092 100644 --- a/packages/client/lib/commands/MSETNX.ts +++ b/packages/client/lib/commands/MSETNX.ts @@ -1,20 +1,9 @@ -import { RedisCommandArguments } from '.'; -import { MSetArguments } from './MSET'; - -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(toSet: MSetArguments): RedisCommandArguments { - const args: RedisCommandArguments = ['MSETNX']; - - if (Array.isArray(toSet)) { - args.push(...toSet.flat()); - } else { - for (const key of Object.keys(toSet)) { - args.push(key, toSet[key]); - } - } - - return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; +import { SimpleStringReply, Command } from '../RESP/types'; +import { mSetArguments } from './MSET'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: mSetArguments.bind(undefined, 'MSETNX'), + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/OBJECT_ENCODING.ts b/packages/client/lib/commands/OBJECT_ENCODING.ts index ac219ae89ed..e74c3f99ebd 100644 --- a/packages/client/lib/commands/OBJECT_ENCODING.ts +++ b/packages/client/lib/commands/OBJECT_ENCODING.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['OBJECT', 'ENCODING', key]; -} - -export declare function transformReply(): string | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/OBJECT_FREQ.ts b/packages/client/lib/commands/OBJECT_FREQ.ts index 071d16f2748..b6757c6c57b 100644 --- a/packages/client/lib/commands/OBJECT_FREQ.ts +++ b/packages/client/lib/commands/OBJECT_FREQ.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['OBJECT', 'FREQ', key]; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/OBJECT_IDLETIME.ts b/packages/client/lib/commands/OBJECT_IDLETIME.ts index 38847d6f4cf..f0fef24e2d8 100644 --- a/packages/client/lib/commands/OBJECT_IDLETIME.ts +++ b/packages/client/lib/commands/OBJECT_IDLETIME.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['OBJECT', 'IDLETIME', key]; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/OBJECT_REFCOUNT.ts b/packages/client/lib/commands/OBJECT_REFCOUNT.ts index 9fd259b5b90..c8381a76bf7 100644 --- a/packages/client/lib/commands/OBJECT_REFCOUNT.ts +++ b/packages/client/lib/commands/OBJECT_REFCOUNT.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['OBJECT', 'REFCOUNT', key]; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PERSIST.ts b/packages/client/lib/commands/PERSIST.ts index d7c9f8623e4..64637fabc14 100644 --- a/packages/client/lib/commands/PERSIST.ts +++ b/packages/client/lib/commands/PERSIST.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument) { return ['PERSIST', key]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PEXPIRE.ts b/packages/client/lib/commands/PEXPIRE.ts index cbb5666a514..4d64281e922 100644 --- a/packages/client/lib/commands/PEXPIRE.ts +++ b/packages/client/lib/commands/PEXPIRE.ts @@ -1,19 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - milliseconds: number, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + ms: number, mode?: 'NX' | 'XX' | 'GT' | 'LT' -): RedisCommandArguments { - const args = ['PEXPIRE', key, milliseconds.toString()]; + ) { + const args = ['PEXPIRE', key, ms.toString()]; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PEXPIREAT.ts b/packages/client/lib/commands/PEXPIREAT.ts index da912ec4fcb..cbae589fba6 100644 --- a/packages/client/lib/commands/PEXPIREAT.ts +++ b/packages/client/lib/commands/PEXPIREAT.ts @@ -1,24 +1,21 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { transformPXAT } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - millisecondsTimestamp: number | Date, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + msTimestamp: number | Date, mode?: 'NX' | 'XX' | 'GT' | 'LT' -): RedisCommandArguments { - const args = [ - 'PEXPIREAT', - key, - transformPXAT(millisecondsTimestamp) - ]; + ) { + const args = ['PEXPIREAT', key, transformPXAT(msTimestamp)]; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PEXPIRETIME.ts b/packages/client/lib/commands/PEXPIRETIME.ts index 4c1acba8f04..49877701b60 100644 --- a/packages/client/lib/commands/PEXPIRETIME.ts +++ b/packages/client/lib/commands/PEXPIRETIME.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return ['PEXPIRETIME', key]; -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['PEXPIREAT', key]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PFADD.ts b/packages/client/lib/commands/PFADD.ts index 8c8985de890..bdde0648f35 100644 --- a/packages/client/lib/commands/PFADD.ts +++ b/packages/client/lib/commands/PFADD.ts @@ -1,13 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['PFADD', key], element); -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, element?: RedisArgument | Array) { + return pushVariadicArguments(['PFADD', key], element); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PFCOUNT.ts b/packages/client/lib/commands/PFCOUNT.ts index a4cf2dbcb26..d2370d32283 100644 --- a/packages/client/lib/commands/PFCOUNT.ts +++ b/packages/client/lib/commands/PFCOUNT.ts @@ -1,12 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['PFCOUNT'], key); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key?: RedisArgument | Array) { + return pushVariadicArguments(['PFCOUNT'], key); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PFMERGE.ts b/packages/client/lib/commands/PFMERGE.ts index e934062b3fe..5735e51bba6 100644 --- a/packages/client/lib/commands/PFMERGE.ts +++ b/packages/client/lib/commands/PFMERGE.ts @@ -1,10 +1,13 @@ -import { RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(destination: string, source: string | Array): RedisCommandArguments { - return pushVerdictArguments(['PFMERGE', destination], source); -} - -export declare function transformReply(): string; +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + destination: RedisArgument, + source?: RedisArgument | Array + ) { + return pushVariadicArguments(['PFMERGE', destination], source); + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PING.spec.ts b/packages/client/lib/commands/PING.spec.ts index 06cbae43a13..fa2a8b172fb 100644 --- a/packages/client/lib/commands/PING.spec.ts +++ b/packages/client/lib/commands/PING.spec.ts @@ -1,37 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PING'; +import PING from './PING'; -describe('PING', () => { - describe('transformArguments', () => { - it('default', () => { - assert.deepEqual( - transformArguments(), - ['PING'] - ); - }); - - it('with message', () => { - assert.deepEqual( - transformArguments('message'), - ['PING', 'message'] - ); - }); +describe.only('PING', () => { + describe('transformArguments', () => { + it('default', () => { + assert.deepEqual( + PING.transformArguments(), + ['PING'] + ); }); - describe('client.ping', () => { - testUtils.testWithClient('string', async client => { - assert.equal( - await client.ping(), - 'PONG' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('buffer', async client => { - assert.deepEqual( - await client.ping(client.commandOptions({ returnBuffers: true })), - Buffer.from('PONG') - ); - }, GLOBAL.SERVERS.OPEN); + it('with message', () => { + assert.deepEqual( + PING.transformArguments('message'), + ['PING', 'message'] + ); }); + }); + + testUtils.testAll('ping', async client => { + assert.equal( + await client.ping(), + 'PONG' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PING.ts b/packages/client/lib/commands/PING.ts index 95fa006122d..5ca95f932d4 100644 --- a/packages/client/lib/commands/PING.ts +++ b/packages/client/lib/commands/PING.ts @@ -1,12 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(message?: RedisCommandArgument): RedisCommandArguments { - const args: RedisCommandArguments = ['PING']; +export default { + IS_READ_ONLY: true, + transformArguments(message?: RedisArgument) { + const args: Array = ['PING']; if (message) { - args.push(message); + args.push(message); } return args; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PSETEX.ts b/packages/client/lib/commands/PSETEX.ts index f2739b6e274..4e345a1a1c9 100644 --- a/packages/client/lib/commands/PSETEX.ts +++ b/packages/client/lib/commands/PSETEX.ts @@ -1,18 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - milliseconds: number, - value: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + ms: number, + value: RedisArgument + ) { return [ - 'PSETEX', - key, - milliseconds.toString(), - value + 'PSETEX', + key, + ms.toString(), + value ]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/PTTL.ts b/packages/client/lib/commands/PTTL.ts index a2975623f7a..35854337877 100644 --- a/packages/client/lib/commands/PTTL.ts +++ b/packages/client/lib/commands/PTTL.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['PTTL', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PUBLISH.ts b/packages/client/lib/commands/PUBLISH.ts index 7862a0936cb..1038dea52fd 100644 --- a/packages/client/lib/commands/PUBLISH.ts +++ b/packages/client/lib/commands/PUBLISH.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments( - channel: RedisCommandArgument, - message: RedisCommandArgument -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(channel: RedisArgument, message: RedisArgument) { return ['PUBLISH', channel, message]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PUBSUB_CHANNELS.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.ts index 86a144ede8e..c828ebefce9 100644 --- a/packages/client/lib/commands/PUBSUB_CHANNELS.ts +++ b/packages/client/lib/commands/PUBSUB_CHANNELS.ts @@ -1,13 +1,17 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export function transformArguments(pattern?: string): Array { - const args = ['PUBSUB', 'CHANNELS']; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(pattern?: RedisArgument) { + const args: Array = ['PUBSUB', 'CHANNELS']; if (pattern) { - args.push(pattern); + args.push(pattern); } return args; -} + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; -export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/PUBSUB_NUMPAT.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.ts index 15be6aa1b18..b800b719dc1 100644 --- a/packages/client/lib/commands/PUBSUB_NUMPAT.ts +++ b/packages/client/lib/commands/PUBSUB_NUMPAT.ts @@ -1,7 +1,10 @@ -export const IS_READ_ONLY = true; +import { NumberReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['PUBSUB', 'NUMPAT']; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/PUBSUB_NUMSUB.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.ts index f47238f8882..f0da89069d1 100644 --- a/packages/client/lib/commands/PUBSUB_NUMSUB.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.ts @@ -1,24 +1,23 @@ -import { pushVerdictArguments } from './generic-transformers'; -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments( - channels?: Array | RedisCommandArgument -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(channels?: RedisArgument | Array) { const args = ['PUBSUB', 'NUMSUB']; - if (channels) return pushVerdictArguments(args, channels); + if (channels) return pushVariadicArguments(args, channels); return args; -} - -export function transformReply(rawReply: Array): Record { - const transformedReply = Object.create(null); - - for (let i = 0; i < rawReply.length; i +=2) { - transformedReply[rawReply[i]] = rawReply[i + 1]; + }, + transformReply(rawReply: ArrayReply) { + const reply = Object.create(null); + let i = 0; + while (i < rawReply.length) { + reply[rawReply[i++].toString()] = rawReply[i++].toString(); } - return transformedReply; -} + return reply as Record; + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts index e998677848a..8acf29c15b4 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts @@ -1,13 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(pattern?: RedisArgument) { + const args: Array = ['PUBSUB', 'bb']; -export function transformArguments( - pattern?: RedisCommandArgument -): RedisCommandArguments { - const args: RedisCommandArguments = ['PUBSUB', 'SHARDCHANNELS']; - if (pattern) args.push(pattern); - return args; -} + if (pattern) { + args.push(pattern); + } -export declare function transformReply(): Array; + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RANDOMKEY.ts b/packages/client/lib/commands/RANDOMKEY.ts index f2d511d4dec..81d956209ea 100644 --- a/packages/client/lib/commands/RANDOMKEY.ts +++ b/packages/client/lib/commands/RANDOMKEY.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { NumberReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments() { return ['RANDOMKEY']; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/READONLY.ts b/packages/client/lib/commands/READONLY.ts index db7db881628..094ff1cc02c 100644 --- a/packages/client/lib/commands/READONLY.ts +++ b/packages/client/lib/commands/READONLY.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['READONLY']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['READONLY']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/READWRITE.ts b/packages/client/lib/commands/READWRITE.ts index 60dc865e89e..b370ec74170 100644 --- a/packages/client/lib/commands/READWRITE.ts +++ b/packages/client/lib/commands/READWRITE.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['READWRITE']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['READWRITE']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RENAME.ts b/packages/client/lib/commands/RENAME.ts index 2d1134084fb..ded9e7e0b22 100644 --- a/packages/client/lib/commands/RENAME.ts +++ b/packages/client/lib/commands/RENAME.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - newKey: RedisCommandArgument -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAME', key, newKey]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts index 322ff0a88cc..01dedc87798 100644 --- a/packages/client/lib/commands/RENAMENX.ts +++ b/packages/client/lib/commands/RENAMENX.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - newKey: RedisCommandArgument -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAMENX', key, newKey]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/REPLICAOF.ts b/packages/client/lib/commands/REPLICAOF.ts index bd452e0f371..4024e94bc49 100644 --- a/packages/client/lib/commands/REPLICAOF.ts +++ b/packages/client/lib/commands/REPLICAOF.ts @@ -1,5 +1,10 @@ -export function transformArguments(host: string, port: number): Array { - return ['REPLICAOF', host, port.toString()]; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(host: string, port: number) { + return ['REPLICAOF', host, port.toString()]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ROLE.ts b/packages/client/lib/commands/ROLE.ts index b1d6041fdfa..49196cb279d 100644 --- a/packages/client/lib/commands/ROLE.ts +++ b/packages/client/lib/commands/ROLE.ts @@ -1,75 +1,67 @@ -export const IS_READ_ONLY = true; +import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types'; -export function transformArguments(): Array { - return ['ROLE']; -} - -interface RoleReplyInterface { - role: T; -} - -type RoleMasterRawReply = ['master', number, Array<[string, string, string]>]; - -interface RoleMasterReply extends RoleReplyInterface<'master'> { - replicationOffest: number; - replicas: Array<{ - ip: string; - port: number; - replicationOffest: number; - }>; -} - -type RoleReplicaState = 'connect' | 'connecting' | 'sync' | 'connected'; +type MasterRole = [ + role: BlobStringReply<'master'>, + replicationOffest: NumberReply, + replicas: ArrayReply<[host: BlobStringReply, port: NumberReply, replicationOffest: NumberReply]>, +]; -type RoleReplicaRawReply = ['slave', string, number, RoleReplicaState, number]; +type SlaveRole = [ + role: BlobStringReply<'slave'>, + masterHost: BlobStringReply, + masterPort: NumberReply, + state: BlobStringReply<'connect' | 'connecting' | 'sync' | 'connected'>, + dataReceived: NumberReply +]; -interface RoleReplicaReply extends RoleReplyInterface<'slave'> { - master: { - ip: string; - port: number; - }; - state: RoleReplicaState; - dataReceived: number; -} +type SentinelRole = [ + role: BlobStringReply<'sentinel'>, + masterNames: ArrayReply +]; -type RoleSentinelRawReply = ['sentinel', Array]; +type Role = MasterRole | SlaveRole | SentinelRole; -interface RoleSentinelReply extends RoleReplyInterface<'sentinel'> { - masterNames: Array; -} - -type RoleRawReply = RoleMasterRawReply | RoleReplicaRawReply | RoleSentinelRawReply; - -type RoleReply = RoleMasterReply | RoleReplicaReply | RoleSentinelReply; - -export function transformReply(reply: RoleRawReply): RoleReply { - switch (reply[0]) { - case 'master': - return { - role: 'master', - replicationOffest: reply[1], - replicas: reply[2].map(([ip, port, replicationOffest]) => ({ - ip, - port: Number(port), - replicationOffest: Number(replicationOffest) - })) - }; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['ROLE']; + }, + transformReply(reply: Role) { + switch (reply[0] as Role[0]['DEFAULT']) { + case 'master': { + const [role, replicationOffest, replicas] = reply as MasterRole; + return { + role, + replicationOffest, + replicas: replicas.map(([host, port, replicationOffest]) => ({ + host, + port, + replicationOffest, + })), + }; + } - case 'slave': - return { - role: 'slave', - master: { - ip: reply[1], - port: reply[2] - }, - state: reply[3], - dataReceived: reply[4] - }; + case 'slave': { + const [role, masterHost, masterPort, state, dataReceived] = reply as SlaveRole; + return { + role, + master: { + host: masterHost, + port: masterPort, + }, + state, + dataReceived, + }; + } - case 'sentinel': - return { - role: 'sentinel', - masterNames: reply[1] - }; + case 'sentinel': { + const [role, masterNames] = reply as SentinelRole; + return { + role, + masterNames, + }; + } } -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/RPOP.ts b/packages/client/lib/commands/RPOP.ts index ed696b6d522..f7d0b33d3af 100644 --- a/packages/client/lib/commands/RPOP.ts +++ b/packages/client/lib/commands/RPOP.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument) { return ['RPOP', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RPOPLPUSH.ts b/packages/client/lib/commands/RPOPLPUSH.ts index da45f6f6024..1a5e1cc59bc 100644 --- a/packages/client/lib/commands/RPOPLPUSH.ts +++ b/packages/client/lib/commands/RPOPLPUSH.ts @@ -1,12 +1,12 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + source: RedisArgument, + destination: RedisArgument + ) { return ['RPOPLPUSH', source, destination]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RPOP_COUNT.ts b/packages/client/lib/commands/RPOP_COUNT.ts index b3bc778ee5c..b60dec6ab9d 100644 --- a/packages/client/lib/commands/RPOP_COUNT.ts +++ b/packages/client/lib/commands/RPOP_COUNT.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, count: number) { return ['RPOP', key, count.toString()]; -} - -export declare function transformReply(): Array | null; + }, + transformReply: undefined as unknown as () => ArrayReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RPUSH.ts b/packages/client/lib/commands/RPUSH.ts index 15e282f0892..6dca8c81ce3 100644 --- a/packages/client/lib/commands/RPUSH.ts +++ b/packages/client/lib/commands/RPUSH.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['RPUSH', key], element); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + element: RedisArgument + ) { + return pushVariadicArguments(['RPUSH', key], element); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/RPUSHX.ts b/packages/client/lib/commands/RPUSHX.ts index 29253cd6edb..ce38ba6b5fd 100644 --- a/packages/client/lib/commands/RPUSHX.ts +++ b/packages/client/lib/commands/RPUSHX.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - element: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['RPUSHX', key], element); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + element: RedisArgument + ) { + return pushVariadicArguments(['RPUSHX', key], element); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SADD.ts b/packages/client/lib/commands/SADD.ts index 7d7121e5391..d3f164e7af7 100644 --- a/packages/client/lib/commands/SADD.ts +++ b/packages/client/lib/commands/SADD.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - members: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['SADD', key], members); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + members: Array | RedisArgument + ) { + return pushVariadicArguments(['SADD', key], members); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index ee5908eb9bd..b1660ddbbcd 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -1,34 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, ArrayReply, Command } from '../RESP/types'; import { ScanOptions, pushScanArguments } from './generic-transformers'; -export const IS_READ_ONLY = true; export interface ScanCommandOptions extends ScanOptions { - TYPE?: RedisCommandArgument; + TYPE?: RedisArgument; } -export function transformArguments( - cursor: number, - options?: ScanCommandOptions -): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + transformArguments(cursor: number, options?: ScanCommandOptions) { const args = pushScanArguments(['SCAN'], cursor, options); if (options?.TYPE) { - args.push('TYPE', options.TYPE); + args.push('TYPE', options.TYPE); } return args; -} - -type ScanRawReply = [string, Array]; - -export interface ScanReply { - cursor: number; - keys: Array; -} - -export function transformReply([cursor, keys]: ScanRawReply): ScanReply { + }, + transformReply([cursor, keys]: [BlobStringReply, ArrayReply]) { return { - cursor: Number(cursor), - keys + cursor: Number(cursor), + keys }; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCARD.ts b/packages/client/lib/commands/SCARD.ts index 0d3ce49b6b2..c13d042ba60 100644 --- a/packages/client/lib/commands/SCARD.ts +++ b/packages/client/lib/commands/SCARD.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['SCARD', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts index cee889215d3..72123806e85 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.ts @@ -1,8 +1,8 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export function transformArguments(sha1: string | Array): RedisCommandArguments { - return pushVerdictArguments(['SCRIPT', 'EXISTS'], sha1); + return pushVariadicArguments(['SCRIPT', 'EXISTS'], sha1); } export { transformBooleanArrayReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/SDIFF.ts b/packages/client/lib/commands/SDIFF.ts index 9c4f3b4820b..895a48da260 100644 --- a/packages/client/lib/commands/SDIFF.ts +++ b/packages/client/lib/commands/SDIFF.ts @@ -1,14 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['SDIFF'], keys); -} - -export declare function transformReply(): Array; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + keys: Array | RedisArgument + ) { + return pushVariadicArguments(['SDIFF'], keys); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SDIFFSTORE.ts b/packages/client/lib/commands/SDIFFSTORE.ts index a927e12ef0e..526469d69ba 100644 --- a/packages/client/lib/commands/SDIFFSTORE.ts +++ b/packages/client/lib/commands/SDIFFSTORE.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - destination: RedisCommandArgument, - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['SDIFFSTORE', destination], keys); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + destination: RedisArgument, + keys: Array | RedisArgument + ) { + return pushVariadicArguments(['SDIFFSTORE', destination], keys); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts index 08ae56552b9..bb39bd89606 100644 --- a/packages/client/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -1,63 +1,59 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, BlobStringReply, NullReply, Command } from '../RESP/types'; type MaximumOneOf = - K extends keyof T ? { [P in K]?: T[K] } & Partial, never>> : never; + K extends keyof T ? { [P in K]?: T[K] } & Partial, never>> : never; type SetTTL = MaximumOneOf<{ - EX: number; - PX: number; - EXAT: number; - PXAT: number; - KEEPTTL: true; + EX: number; + PX: number; + EXAT: number; + PXAT: number; + KEEPTTL: true; }>; type SetGuards = MaximumOneOf<{ - NX: true; - XX: true; + NX: true; + XX: true; }>; interface SetCommonOptions { - GET?: true; + GET?: true; } export type SetOptions = SetTTL & SetGuards & SetCommonOptions; -export function transformArguments( - key: RedisCommandArgument, - value: RedisCommandArgument | number, - options?: SetOptions -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, value: RedisArgument | number, options?: SetOptions) { const args = [ - 'SET', - key, - typeof value === 'number' ? value.toString() : value + 'SET', + key, + typeof value === 'number' ? value.toString() : value ]; if (options?.EX !== undefined) { - args.push('EX', options.EX.toString()); + args.push('EX', options.EX.toString()); } else if (options?.PX !== undefined) { - args.push('PX', options.PX.toString()); + args.push('PX', options.PX.toString()); } else if (options?.EXAT !== undefined) { - args.push('EXAT', options.EXAT.toString()); + args.push('EXAT', options.EXAT.toString()); } else if (options?.PXAT !== undefined) { - args.push('PXAT', options.PXAT.toString()); + args.push('PXAT', options.PXAT.toString()); } else if (options?.KEEPTTL) { - args.push('KEEPTTL'); + args.push('KEEPTTL'); } if (options?.NX) { - args.push('NX'); + args.push('NX'); } else if (options?.XX) { - args.push('XX'); + args.push('XX'); } if (options?.GET) { - args.push('GET'); + args.push('GET'); } return args; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> | BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SETEX.ts b/packages/client/lib/commands/SETEX.ts index bb3068501f0..bbd77e5d990 100644 --- a/packages/client/lib/commands/SETEX.ts +++ b/packages/client/lib/commands/SETEX.ts @@ -1,18 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, seconds: number, - value: RedisCommandArgument -): RedisCommandArguments { + value: RedisArgument + ) { return [ - 'SETEX', - key, - seconds.toString(), - value + 'SETEX', + key, + seconds.toString(), + value ]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/SETNX.ts b/packages/client/lib/commands/SETNX.ts index b01d45dc32f..0940efad693 100644 --- a/packages/client/lib/commands/SETNX.ts +++ b/packages/client/lib/commands/SETNX.ts @@ -1,12 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - value: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + transformArguments(key: RedisArgument, value: RedisArgument) { return ['SETNX', key, value]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SETRANGE.ts b/packages/client/lib/commands/SETRANGE.ts index 038a8a5dd7f..1951a82c07d 100644 --- a/packages/client/lib/commands/SETRANGE.ts +++ b/packages/client/lib/commands/SETRANGE.ts @@ -1,13 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, offset: number, - value: RedisCommandArgument -): RedisCommandArguments { - return ['SETRANGE', key, offset.toString(), value]; -} - -export declare function transformReply(): number; + value: RedisArgument + ) { + return [ + 'SETRANGE', + key, + offset.toString(), + value + ]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SINTER.ts b/packages/client/lib/commands/SINTER.ts index fe1feee7ade..d5c0fbc98d6 100644 --- a/packages/client/lib/commands/SINTER.ts +++ b/packages/client/lib/commands/SINTER.ts @@ -1,14 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['SINTER'], keys); -} - -export declare function transformReply(): Array; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + keys: Array | RedisArgument + ) { + return pushVariadicArguments(['SINTER'], keys); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SINTERCARD.ts b/packages/client/lib/commands/SINTERCARD.ts index ddb7e5b00ef..967db96110a 100644 --- a/packages/client/lib/commands/SINTERCARD.ts +++ b/packages/client/lib/commands/SINTERCARD.ts @@ -1,21 +1,26 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; +export interface SInterCardOptions { + LIMIT?: number; +} -export function transformArguments( - keys: Array | RedisCommandArgument, - limit?: number -): RedisCommandArguments { - const args = pushVerdictArgument(['SINTERCARD'], keys); +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + keys: Array | RedisArgument, + options?: SInterCardOptions | number // `number` for backwards compatibility + ) { + const args = pushVariadicArguments(['SINTERCARD'], keys); - if (limit) { - args.push('LIMIT', limit.toString()); + if (typeof options === 'number') { // backwards compatibility + args.push('LIMIT', options.toString()); + } else if (options?.LIMIT !== undefined) { + args.push('LIMIT', options.LIMIT.toString()); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SINTERSTORE.ts b/packages/client/lib/commands/SINTERSTORE.ts index 02bf9d061a0..8ab9c0065e6 100644 --- a/packages/client/lib/commands/SINTERSTORE.ts +++ b/packages/client/lib/commands/SINTERSTORE.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( destination: RedisCommandArgument, keys: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['SINTERSTORE', destination], keys); + return pushVariadicArguments(['SINTERSTORE', destination], keys); } export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SMEMBERS.ts b/packages/client/lib/commands/SMEMBERS.ts index 7950a4c073a..fdab118e86e 100644 --- a/packages/client/lib/commands/SMEMBERS.ts +++ b/packages/client/lib/commands/SMEMBERS.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SetReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['SMEMBERS', key]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => SetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SREM.ts b/packages/client/lib/commands/SREM.ts index 34aebdf02e3..f08e147dd84 100644 --- a/packages/client/lib/commands/SREM.ts +++ b/packages/client/lib/commands/SREM.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: RedisCommandArgument, members: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['SREM', key], members); + return pushVariadicArguments(['SREM', key], members); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/SSCAN.ts b/packages/client/lib/commands/SSCAN.ts index 9b3938f159b..fe648bff5ea 100644 --- a/packages/client/lib/commands/SSCAN.ts +++ b/packages/client/lib/commands/SSCAN.ts @@ -1,31 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; import { ScanOptions, pushScanArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, cursor: number, options?: ScanOptions -): RedisCommandArguments { - return pushScanArguments([ - 'SSCAN', - key, - ], cursor, options); -} - -type SScanRawReply = [string, Array]; - -interface SScanReply { - cursor: number; - members: Array; -} - -export function transformReply([cursor, members]: SScanRawReply): SScanReply { + ) { + return pushScanArguments(['SSCAN', key], cursor, options); + }, + transformReply([cursor, members]: [BlobStringReply, Array]) { return { - cursor: Number(cursor), - members + cursor: Number(cursor), + members }; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/STRLEN.ts b/packages/client/lib/commands/STRLEN.ts index de88340d8b6..594530ff6bf 100644 --- a/packages/client/lib/commands/STRLEN.ts +++ b/packages/client/lib/commands/STRLEN.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['STRLEN', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SUNION.ts b/packages/client/lib/commands/SUNION.ts index 52c112e6610..97d8b41d70a 100644 --- a/packages/client/lib/commands/SUNION.ts +++ b/packages/client/lib/commands/SUNION.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -8,7 +8,7 @@ export const IS_READ_ONLY = true; export function transformArguments( keys: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['SUNION'], keys); + return pushVariadicArguments(['SUNION'], keys); } export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SUNIONSTORE.ts b/packages/client/lib/commands/SUNIONSTORE.ts index 94df6771a04..27161ba0773 100644 --- a/packages/client/lib/commands/SUNIONSTORE.ts +++ b/packages/client/lib/commands/SUNIONSTORE.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( destination: RedisCommandArgument, keys: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['SUNIONSTORE', destination], keys); + return pushVariadicArguments(['SUNIONSTORE', destination], keys); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/TOUCH.ts b/packages/client/lib/commands/TOUCH.ts index e67dff8e932..c28f7a4629f 100644 --- a/packages/client/lib/commands/TOUCH.ts +++ b/packages/client/lib/commands/TOUCH.ts @@ -1,12 +1,12 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; export function transformArguments( key: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['TOUCH'], key); + return pushVariadicArguments(['TOUCH'], key); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/TTL.ts b/packages/client/lib/commands/TTL.ts index 29586f31fa8..65c3b7b026f 100644 --- a/packages/client/lib/commands/TTL.ts +++ b/packages/client/lib/commands/TTL.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['TTL', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/TYPE.ts b/packages/client/lib/commands/TYPE.ts index 10cd3f99b0e..09f6887492c 100644 --- a/packages/client/lib/commands/TYPE.ts +++ b/packages/client/lib/commands/TYPE.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['TYPE', key]; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/UNLINK.ts b/packages/client/lib/commands/UNLINK.ts index 53b0360e2df..4455d42bcf1 100644 --- a/packages/client/lib/commands/UNLINK.ts +++ b/packages/client/lib/commands/UNLINK.ts @@ -1,12 +1,12 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; export function transformArguments( key: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['UNLINK'], key); + return pushVariadicArguments(['UNLINK'], key); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts index ce42e7697bf..3e80adeb1dc 100644 --- a/packages/client/lib/commands/UNWATCH.ts +++ b/packages/client/lib/commands/UNWATCH.ts @@ -1,5 +1,9 @@ -export function transformArguments(): Array { - return ['UNWATCH']; -} +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['WATCH', key]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/WAIT.ts b/packages/client/lib/commands/WAIT.ts index dff51ed9680..da9df89ff0a 100644 --- a/packages/client/lib/commands/WAIT.ts +++ b/packages/client/lib/commands/WAIT.ts @@ -1,7 +1,9 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; -export function transformArguments(numberOfReplicas: number, timeout: number): Array { +export default { + IS_READ_ONLY: true, + transformArguments(numberOfReplicas: number, timeout: number) { return ['WAIT', numberOfReplicas.toString(), timeout.toString()]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/WATCH.ts b/packages/client/lib/commands/WATCH.ts index 58c6dfd1dad..9a7b16fd74e 100644 --- a/packages/client/lib/commands/WATCH.ts +++ b/packages/client/lib/commands/WATCH.ts @@ -1,10 +1,10 @@ import { RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; export function transformArguments(key: string | Array): RedisCommandArguments { - return pushVerdictArguments(['WATCH'], key); + return pushVariadicArguments(['WATCH'], key); } export declare function transformReply(): string; diff --git a/packages/client/lib/commands/XACK.ts b/packages/client/lib/commands/XACK.ts index 670d810fc00..1d35c8d13bd 100644 --- a/packages/client/lib/commands/XACK.ts +++ b/packages/client/lib/commands/XACK.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -8,7 +8,7 @@ export function transformArguments( group: RedisCommandArgument, id: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['XACK', key, group], id); + return pushVariadicArguments(['XACK', key, group], id); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts index bc38f9b9e95..43ad78cfb69 100644 --- a/packages/client/lib/commands/XCLAIM.ts +++ b/packages/client/lib/commands/XCLAIM.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -18,7 +18,7 @@ export function transformArguments( id: RedisCommandArgument | Array, options?: XClaimOptions ): RedisCommandArguments { - const args = pushVerdictArguments( + const args = pushVariadicArguments( ['XCLAIM', key, group, consumer, minIdleTime.toString()], id ); diff --git a/packages/client/lib/commands/XDEL.ts b/packages/client/lib/commands/XDEL.ts index 82b30d21092..80b429c4e11 100644 --- a/packages/client/lib/commands/XDEL.ts +++ b/packages/client/lib/commands/XDEL.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: RedisCommandArgument, id: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['XDEL', key], id); + return pushVariadicArguments(['XDEL', key], id); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index 9ac67d59cce..9372c9217ed 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,71 +1,76 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformNumberInfinityArgument, ZMember } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, DoubleReply, Command } from '../RESP/types'; +import { ZMember, transformNumberInfinityArgument, transformNumberInfinityReply } from './generic-transformers'; interface NX { - NX?: true; + NX?: boolean; } interface XX { - XX?: true; + XX?: boolean; } interface LT { - LT?: true; + LT?: boolean; } interface GT { - GT?: true; + GT?: boolean; } interface CH { - CH?: true; + CH?: boolean; } interface INCR { - INCR?: true; + INCR?: boolean; } -type ZAddOptions = (NX | (XX & LT & GT)) & CH & INCR; +export type ZAddOptions = (NX | (XX & LT & GT)) & CH & INCR; -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, members: ZMember | Array, options?: ZAddOptions -): RedisCommandArguments { + ) { const args = ['ZADD', key]; if ((options)?.NX) { - args.push('NX'); + args.push('NX'); } else { - if ((options)?.XX) { - args.push('XX'); - } + if ((options)?.XX) { + args.push('XX'); + } + + if ((options)?.GT) { + args.push('GT'); + } - if ((options)?.GT) { - args.push('GT'); - } else if ((options)?.LT) { - args.push('LT'); - } + if ((options)?.LT) { + args.push('LT'); + } } if ((options)?.CH) { - args.push('CH'); + args.push('CH'); } if ((options)?.INCR) { - args.push('INCR'); + args.push('INCR'); } for (const { score, value } of (Array.isArray(members) ? members : [members])) { - args.push( - transformNumberInfinityArgument(score), - value - ); + args.push( + transformNumberInfinityArgument(score), + value + ); } return args; -} - -export { transformNumberInfinityReply as transformReply } from './generic-transformers'; + }, + transformReply: { + 2: transformNumberInfinityReply, + 3: undefined as unknown as () => NumberReply | DoubleReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZCARD.ts b/packages/client/lib/commands/ZCARD.ts index f208c181369..c11cb69db3c 100644 --- a/packages/client/lib/commands/ZCARD.ts +++ b/packages/client/lib/commands/ZCARD.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['ZCARD', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZCOUNT.ts b/packages/client/lib/commands/ZCOUNT.ts index f9700cc9099..06bd4b915a8 100644 --- a/packages/client/lib/commands/ZCOUNT.ts +++ b/packages/client/lib/commands/ZCOUNT.ts @@ -1,21 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { transformStringNumberInfinityArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument | number, - max: RedisCommandArgument | number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + min: number | RedisArgument, + max: number | RedisArgument + ) { return [ - 'ZCOUNT', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) + 'ZCOUNT', + key, + transformStringNumberInfinityArgument(min), + transformStringNumberInfinityArgument(max) ]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZDIFF.ts b/packages/client/lib/commands/ZDIFF.ts index f3818a139f1..f16c8717cdb 100644 --- a/packages/client/lib/commands/ZDIFF.ts +++ b/packages/client/lib/commands/ZDIFF.ts @@ -1,14 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; - -export function transformArguments( - keys: Array | RedisCommandArgument -): RedisCommandArguments { - return pushVerdictArgument(['ZDIFF'], keys); -} - -export declare function transformReply(): Array; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(keys: RedisVariadicArgument) { + return pushVariadicArgument(['ZDIFF'], keys); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZDIFFSTORE.ts b/packages/client/lib/commands/ZDIFFSTORE.ts index 3b9af9511c5..e4614a1cb14 100644 --- a/packages/client/lib/commands/ZDIFFSTORE.ts +++ b/packages/client/lib/commands/ZDIFFSTORE.ts @@ -1,13 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - destination: RedisCommandArgument, - keys: Array | RedisCommandArgument -): RedisCommandArguments { - return pushVerdictArgument(['ZDIFFSTORE', destination], keys); -} - -export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + destination: RedisArgument, + inputKeys: RedisVariadicArgument + ) { + return pushVariadicArgument(['ZDIFFSTORE', destination], inputKeys); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts index 9caa13c9f8b..0fa1a6d271a 100644 --- a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts @@ -1,13 +1,19 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformZDiffArguments } from './ZDIFF'; +import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types'; +import ZDIFF from './ZDIFF'; +import { transformSortedSetWithScoresReply } from './generic-transformers'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZDIFF'; - -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformZDiffArguments(...args), - 'WITHSCORES' - ]; -} - -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(keys: Parameters[0]) { + const args = ZDIFF.transformArguments(keys); + args.push('WITHSCORES'); + return args; + }, + transformReply: { + 2: transformSortedSetWithScoresReply, + 3: (reply: ArrayReply<[BlobStringReply, NumberReply]>) => { + return reply.map(([value, score]) => ({ value, score })); + } + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts index 68d89351391..66b3dfa1f24 100644 --- a/packages/client/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -1,19 +1,22 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformNumberInfinityArgument } from './generic-transformers'; +import { RedisArgument, DoubleReply, Command } from '../RESP/types'; +import { transformNumberInfinityArgument, transformNumberInfinityReply } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, increment: number, - member: RedisCommandArgument -): RedisCommandArguments { + member: RedisArgument + ) { return [ - 'ZINCRBY', - key, - transformNumberInfinityArgument(increment), - member + 'ZINCRBY', + key, + transformNumberInfinityArgument(increment), + member ]; -} - -export { transformNumberInfinityReply as transformReply } from './generic-transformers'; + }, + transformReply: { + 2: transformNumberInfinityReply, + 3: undefined as unknown as () => DoubleReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTER.ts b/packages/client/lib/commands/ZINTER.ts index 88d7f801882..8c185c03c74 100644 --- a/packages/client/lib/commands/ZINTER.ts +++ b/packages/client/lib/commands/ZINTER.ts @@ -1,33 +1,75 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { transformNumberInfinityArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; +export type ZInterKeyAndWeight = { + key: RedisArgument; + weight: number; +}; -export const IS_READ_ONLY = true; +export type ZInterKeys = T | [T, ...Array]; -interface ZInterOptions { - WEIGHTS?: Array; - AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; +export interface ZInterOptions { + AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; } -export function transformArguments( - keys: Array | RedisCommandArgument, - options?: ZInterOptions -): RedisCommandArguments { - const args = pushVerdictArgument(['ZINTER'], keys); - - if (options?.WEIGHTS) { - args.push( - 'WEIGHTS', - ...options.WEIGHTS.map(weight => weight.toString()) - ); +export function pushZInterArguments( + args: Array, + keys: ZInterKeys | ZInterKeys, + options?: ZInterOptions +) { + if (Array.isArray(keys)) { + args.push(keys.length.toString()); + + if (keys.length) { + if (isPlainKeys(keys)) { + args = args.concat(keys); + } else { + const start = args.length; + args[start + keys.length] = 'WEIGHTS'; + for (let i = 0; i < keys.length; i++) { + const index = start + i; + args[index] = keys[i].key; + args[index + 1 + keys.length] = transformNumberInfinityArgument(keys[i].weight); + } + } } + } else { + args.push('1'); - if (options?.AGGREGATE) { - args.push('AGGREGATE', options.AGGREGATE); + if (isPlainKey(keys)) { + args.push(keys); + } else { + args.push( + keys.key, + 'WEIGHTS', + transformNumberInfinityArgument(keys.weight) + ); } + } + + if (options?.AGGREGATE) { + args.push('AGGREGATE', options.AGGREGATE); + } + + return args; +} + +function isPlainKey(key: RedisArgument | ZInterKeyAndWeight): key is RedisArgument { + return typeof key === 'string' || Buffer.isBuffer(key); +} - return args; +function isPlainKeys(keys: Array | Array): keys is Array { + return isPlainKey(keys[0]); } -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + keys: ZInterKeys | ZInterKeys, + options?: ZInterOptions + ) { + return pushZInterArguments(['ZINTER'], keys, options); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTERCARD.ts b/packages/client/lib/commands/ZINTERCARD.ts index ff45ab2aa01..9953d88eecc 100644 --- a/packages/client/lib/commands/ZINTERCARD.ts +++ b/packages/client/lib/commands/ZINTERCARD.ts @@ -1,21 +1,27 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; - -export const IS_READ_ONLY = true; +export interface ZInterCardOptions { + LIMIT?: number; +} -export function transformArguments( - keys: Array | RedisCommandArgument, - limit?: number -): RedisCommandArguments { - const args = pushVerdictArgument(['ZINTERCARD'], keys); +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + keys: RedisVariadicArgument, + options?: ZInterCardOptions['LIMIT'] | ZInterCardOptions + ) { + const args = pushVariadicArgument(['ZINTERCARD'], keys); - if (limit) { - args.push('LIMIT', limit.toString()); + // backwards compatibility + if (typeof options === 'number') { + args.push('LIMIT', options.toString()); + } else if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.toString()); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTERSTORE.ts b/packages/client/lib/commands/ZINTERSTORE.ts index 540f10ae2d8..9188b0d90f1 100644 --- a/packages/client/lib/commands/ZINTERSTORE.ts +++ b/packages/client/lib/commands/ZINTERSTORE.ts @@ -1,32 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -interface ZInterStoreOptions { - WEIGHTS?: Array; - AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; -} - -export function transformArguments( - destination: RedisCommandArgument, - keys: Array | RedisCommandArgument, - options?: ZInterStoreOptions -): RedisCommandArguments { - const args = pushVerdictArgument(['ZINTERSTORE', destination], keys); - - if (options?.WEIGHTS) { - args.push( - 'WEIGHTS', - ...options.WEIGHTS.map(weight => weight.toString()) - ); - } - - if (options?.AGGREGATE) { - args.push('AGGREGATE', options.AGGREGATE); - } - - return args; -} - -export declare function transformReply(): number; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { pushZInterArguments, ZInterKeyAndWeight, ZInterKeys, ZInterOptions } from './ZINTER'; + +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + destination: RedisArgument, + keys: ZInterKeys | ZInterKeys, + options?: ZInterOptions + ) { + return pushZInterArguments(['ZINTERSTORE', destination], keys, options); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTER_WITHSCORES.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.ts index c9416e9222a..07616251452 100644 --- a/packages/client/lib/commands/ZINTER_WITHSCORES.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.ts @@ -1,13 +1,38 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformZInterArguments } from './ZINTER'; +// import { RedisCommandArguments } from '.'; +// import { transformArguments as transformZInterArguments } from './ZINTER'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZINTER'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZINTER'; -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformZInterArguments(...args), - 'WITHSCORES' - ]; -} +// export function transformArguments(...args: Parameters): RedisCommandArguments { +// return [ +// ...transformZInterArguments(...args), +// 'WITHSCORES' +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; + + +// // transformSortedSetWithScoresReply + +import { ArrayReply, BlobStringReply, Command, DoubleReply } from '../RESP/types'; +import ZINTER from './ZINTER'; +import { transformSortedSetWithScoresReply } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: ZINTER.FIRST_KEY_INDEX, + IS_READ_ONLY: ZINTER.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZINTER.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; + }, + transformReply: { + 2: transformSortedSetWithScoresReply, + 3: (reply: ArrayReply<[BlobStringReply, DoubleReply]>) => { + return reply.map(([member, score]) => ({ + member, + score + })); + } + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZLEXCOUNT.ts b/packages/client/lib/commands/ZLEXCOUNT.ts index e2fbcdbb42b..26c9e0d70ac 100644 --- a/packages/client/lib/commands/ZLEXCOUNT.ts +++ b/packages/client/lib/commands/ZLEXCOUNT.ts @@ -1,20 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument, - max: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + min: RedisArgument, + max: RedisArgument + ) { return [ - 'ZLEXCOUNT', - key, - min, - max + 'ZLEXCOUNT', + key, + min, + max ]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts index 0baa46bbf0b..d430b1cbc48 100644 --- a/packages/client/lib/commands/ZMPOP.ts +++ b/packages/client/lib/commands/ZMPOP.ts @@ -1,34 +1,54 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { SortedSetSide, transformSortedSetMemberReply, transformZMPopArguments, ZMember, ZMPopOptions } from './generic-transformers'; +import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; +import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; +export interface ZMPopOptions { + COUNT?: number; +} + +export type ZMPopRawReply = NullReply | TuplesReply<[ + key: BlobStringReply, + elements: ArrayReply> +]>; -export function transformArguments( - keys: RedisCommandArgument | Array, +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + keys: RedisVariadicArgument, side: SortedSetSide, options?: ZMPopOptions -): RedisCommandArguments { - return transformZMPopArguments( - ['ZMPOP'], - keys, - side, - options - ); -} + ) { + const args = pushVariadicArgument(['ZMPOP'], keys); -type ZMPopRawReply = null | [ - key: string, - elements: Array<[RedisCommandArgument, RedisCommandArgument]> -]; + args.push(side); -type ZMPopReply = null | { - key: string, - elements: Array -}; + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } -export function transformReply(reply: ZMPopRawReply): ZMPopReply { - return reply === null ? null : { + return args; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply === null ? null : { key: reply[0], - elements: reply[1].map(transformSortedSetMemberReply) - }; -} + elements: reply[1].map(([member, score]) => ({ + member, + score: Number(score) + })) + }; + }, + 3: (reply: ZMPopRawReply) => { + return reply === null ? null : { + key: reply[0], + elements: reply[1].map(([member, score]) => ({ + member, + score + })) + }; + }, + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts index 6c8c9dace31..55f71e0d3af 100644 --- a/packages/client/lib/commands/ZMSCORE.ts +++ b/packages/client/lib/commands/ZMSCORE.ts @@ -1,15 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import { pushVariadicArgument, RedisVariadicArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVerdictArguments(['ZMSCORE', key], member); -} - -export { transformNumberInfinityNullArrayReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + member: RedisVariadicArgument + ) { + return pushVariadicArgument(['ZMSCORE', key], member); + }, + transformReply: { + 2: (reply: ArrayReply) => { + return reply.map(score => score === null ? null : Number(score)); + }, + 3: undefined as unknown as () => ArrayReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZREM.ts b/packages/client/lib/commands/ZREM.ts index 7ab92c4a78f..a5e1ff559cf 100644 --- a/packages/client/lib/commands/ZREM.ts +++ b/packages/client/lib/commands/ZREM.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArguments } from './generic-transformers'; +import { pushVariadicArguments } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -7,7 +7,7 @@ export function transformArguments( key: RedisCommandArgument, member: RedisCommandArgument | Array ): RedisCommandArguments { - return pushVerdictArguments(['ZREM', key], member); + return pushVariadicArguments(['ZREM', key], member); } export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index f6fa17c2d4e..2377b90aace 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -1,39 +1,34 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { ScanOptions, transformNumberInfinityReply, pushScanArguments, ZMember } from './generic-transformers'; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; +import { ScanOptions, ZMember, pushScanArguments, transformNumberInfinityReply } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; +export interface HScanEntry { + field: BlobStringReply; + value: BlobStringReply; +} -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, cursor: number, options?: ScanOptions -): RedisCommandArguments { - return pushScanArguments([ - 'ZSCAN', - key - ], cursor, options); -} - -type ZScanRawReply = [RedisCommandArgument, Array]; - -interface ZScanReply { - cursor: number; - members: Array; -} - -export function transformReply([cursor, rawMembers]: ZScanRawReply): ZScanReply { - const parsedMembers: Array = []; - for (let i = 0; i < rawMembers.length; i += 2) { - parsedMembers.push({ - value: rawMembers[i], - score: transformNumberInfinityReply(rawMembers[i + 1]) - }); + ) { + return pushScanArguments(['ZSCAN', key], cursor, options); + }, + transformReply([cursor, rawMembers]: [BlobStringReply, Array]) { + const members = []; + let i = 0; + while (i < rawMembers.length) { + members.push({ + value: rawMembers[i++], + score: transformNumberInfinityReply(rawMembers[i++]) + } satisfies ZMember); } return { - cursor: Number(cursor), - members: parsedMembers + cursor: Number(cursor), + members }; -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZUNION.ts b/packages/client/lib/commands/ZUNION.ts index f329348cc8b..3f57c5ba724 100644 --- a/packages/client/lib/commands/ZUNION.ts +++ b/packages/client/lib/commands/ZUNION.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { pushVariadicArgument } from './generic-transformers'; export const FIRST_KEY_INDEX = 2; @@ -14,7 +14,7 @@ export function transformArguments( keys: Array | RedisCommandArgument, options?: ZUnionOptions ): RedisCommandArguments { - const args = pushVerdictArgument(['ZUNION'], keys); + const args = pushVariadicArgument(['ZUNION'], keys); if (options?.WEIGHTS) { args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); diff --git a/packages/client/lib/commands/ZUNIONSTORE.ts b/packages/client/lib/commands/ZUNIONSTORE.ts index 2a42e21bc87..4795161d00b 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVerdictArgument } from './generic-transformers'; +import { pushVariadicArgument } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; @@ -13,7 +13,7 @@ export function transformArguments( keys: Array | RedisCommandArgument, options?: ZUnionOptions ): RedisCommandArguments { - const args = pushVerdictArgument(['ZUNIONSTORE', destination], keys); + const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); if (options?.WEIGHTS) { args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); diff --git a/packages/client/lib/commands/generic-transformers.spec.ts b/packages/client/lib/commands/generic-transformers.spec.ts index 301cab0a75c..0c64a2175fd 100644 --- a/packages/client/lib/commands/generic-transformers.spec.ts +++ b/packages/client/lib/commands/generic-transformers.spec.ts @@ -18,10 +18,10 @@ import { transformEXAT, transformPXAT, pushEvalArguments, - pushVerdictArguments, - pushVerdictNumberArguments, - pushVerdictArgument, - pushOptionalVerdictArgument, + pushVariadicArguments, + pushVariadicNumberArguments, + pushVariadicArgument, + pushOptionalVariadicArgument, transformCommandReply, CommandFlags, CommandCategories, @@ -564,72 +564,72 @@ describe('Generic Transformers', () => { }); }); - describe('pushVerdictArguments', () => { + describe('pushVariadicArguments', () => { it('string', () => { assert.deepEqual( - pushVerdictArguments([], 'string'), + pushVariadicArguments([], 'string'), ['string'] ); }); it('array', () => { assert.deepEqual( - pushVerdictArguments([], ['1', '2']), + pushVariadicArguments([], ['1', '2']), ['1', '2'] ); }); }); - describe('pushVerdictNumberArguments', () => { + describe('pushVariadicNumberArguments', () => { it('number', () => { assert.deepEqual( - pushVerdictNumberArguments([], 0), + pushVariadicNumberArguments([], 0), ['0'] ); }); it('array', () => { assert.deepEqual( - pushVerdictNumberArguments([], [0, 1]), + pushVariadicNumberArguments([], [0, 1]), ['0', '1'] ); }); }); - describe('pushVerdictArgument', () => { + describe('pushVariadicArgument', () => { it('string', () => { assert.deepEqual( - pushVerdictArgument([], 'string'), + pushVariadicArgument([], 'string'), ['1', 'string'] ); }); it('array', () => { assert.deepEqual( - pushVerdictArgument([], ['1', '2']), + pushVariadicArgument([], ['1', '2']), ['2', '1', '2'] ); }); }); - describe('pushOptionalVerdictArgument', () => { + describe('pushOptionalVariadicArgument', () => { it('undefined', () => { assert.deepEqual( - pushOptionalVerdictArgument([], 'name', undefined), + pushOptionalVariadicArgument([], 'name', undefined), [] ); }); it('string', () => { assert.deepEqual( - pushOptionalVerdictArgument([], 'name', 'string'), + pushOptionalVariadicArgument([], 'name', 'string'), ['name', '1', 'string'] ); }); it('array', () => { assert.deepEqual( - pushOptionalVerdictArgument([], 'name', ['1', '2']), + pushOptionalVariadicArgument([], 'name', ['1', '2']), ['name', '2', '1', '2'] ); }); diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 5048de9399a..dd89610718e 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,4 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ArrayReply, BlobStringReply, NullReply, RedisArgument } from '../RESP/types'; export function transformBooleanReply(reply: number): boolean { return reply === 1; @@ -33,7 +34,7 @@ export function pushScanArguments( return args; } -export function transformNumberInfinityReply(reply: RedisCommandArgument): number { +export function transformNumberInfinityReply(reply: BlobStringReply): number { switch (reply.toString()) { case '+inf': return Infinity; @@ -46,13 +47,13 @@ export function transformNumberInfinityReply(reply: RedisCommandArgument): numbe } } -export function transformNumberInfinityNullReply(reply: RedisCommandArgument | null): number | null { +export function transformNumberInfinityNullReply(reply: BlobStringReply | NullReply): number | null { if (reply === null) return null; return transformNumberInfinityReply(reply); } -export function transformNumberInfinityNullArrayReply(reply: Array): Array { +export function transformNumberInfinityNullArrayReply(reply: Array): Array { return reply.map(transformNumberInfinityNullReply); } @@ -76,8 +77,8 @@ export function transformStringNumberInfinityArgument(num: RedisCommandArgument } export function transformTuplesReply( - reply: Array -): Record { + reply: ArrayReply +): Record { const message = Object.create(null); for (let i = 0; i < reply.length; i += 2) { @@ -123,11 +124,11 @@ export function transformStreamsMessagesReply(reply: Array | null): Streams export interface ZMember { score: number; - value: RedisCommandArgument; + value: RedisArgument; } export function transformSortedSetMemberNullReply( - reply: [RedisCommandArgument, RedisCommandArgument] | [] + reply: [BlobStringReply, BlobStringReply] | [] ): ZMember | null { if (!reply.length) return null; @@ -135,7 +136,7 @@ export function transformSortedSetMemberNullReply( } export function transformSortedSetMemberReply( - reply: [RedisCommandArgument, RedisCommandArgument] + reply: [BlobStringReply, BlobStringReply] ): ZMember { return { value: reply[0], @@ -143,7 +144,7 @@ export function transformSortedSetMemberReply( }; } -export function transformSortedSetWithScoresReply(reply: Array): Array { +export function transformSortedSetWithScoresReply(reply: ArrayReply): Array { const members = []; for (let i = 0; i < reply.length; i += 2) { @@ -156,31 +157,10 @@ export function transformSortedSetWithScoresReply(reply: Array, - side: SortedSetSide, - options?: ZMPopOptions -): RedisCommandArguments { - pushVerdictArgument(args, keys); - - args.push(side); - - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } - - return args; -} - export type ListSide = 'LEFT' | 'RIGHT'; +export type SortedSetSide = 'MIN' | 'MAX'; + export interface LMPopOptions { COUNT?: number; } @@ -191,7 +171,7 @@ export function transformLMPopArguments( side: ListSide, options?: LMPopOptions ): RedisCommandArguments { - pushVerdictArgument(args, keys); + pushVariadicArgument(args, keys); args.push(side); @@ -425,7 +405,7 @@ export function pushEvalArguments(args: Array, options?: EvalOptions): A return args; } -export function pushVerdictArguments(args: RedisCommandArguments, value: RedisCommandArgument | Array): RedisCommandArguments { +export function pushVariadicArguments(args: RedisCommandArguments, value: RedisCommandArgument | Array): RedisCommandArguments { if (Array.isArray(value)) { // https://github.com/redis/node-redis/pull/2160 args = args.concat(value); @@ -436,7 +416,7 @@ export function pushVerdictArguments(args: RedisCommandArguments, value: RedisCo return args; } -export function pushVerdictNumberArguments( +export function pushVariadicNumberArguments( args: RedisCommandArguments, value: number | Array ): RedisCommandArguments { @@ -451,9 +431,11 @@ export function pushVerdictNumberArguments( return args; } -export function pushVerdictArgument( - args: RedisCommandArguments, - value: RedisCommandArgument | Array +export type RedisVariadicArgument = RedisArgument | Array; + +export function pushVariadicArgument( + args: Array, + value: RedisVariadicArgument ): RedisCommandArguments { if (Array.isArray(value)) { args.push(value.length.toString(), ...value); @@ -464,7 +446,7 @@ export function pushVerdictArgument( return args; } -export function pushOptionalVerdictArgument( +export function pushOptionalVariadicArgument( args: RedisCommandArguments, name: RedisCommandArgument, value: undefined | RedisCommandArgument | Array @@ -473,7 +455,7 @@ export function pushOptionalVerdictArgument( args.push(name); - return pushVerdictArgument(args, value); + return pushVariadicArgument(args, value); } export enum CommandFlags { diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 60f9720c8d1..db7ca279a7c 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -1,91 +1,332 @@ -import { ClientCommandOptions } from '../client'; -import { CommandOptions } from '../command-options'; -import { RedisScriptConfig, SHA1 } from '../lua-script'; +import ACL_CAT from './ACL_CAT'; +import ACL_DRYRUN from './ACL_DRYRUN'; +import ACL_GENPASS from './ACL_GENPASS'; +import ACL_GETUSER from './ACL_GETUSER'; +import ACL_LIST from './ACL_LIST'; +import ACL_LOAD from './ACL_LOAD'; +import ACL_LOG_RESET from './ACL_LOG_RESET'; +import ACL_LOG from './ACL_LOG'; +import ACL_SAVE from './ACL_SAVE'; +import ACL_SETUSER from './ACL_SETUSER'; +import ACL_USERS from './ACL_USERS'; +import ACL_WHOAMI from './ACL_WHOAMI'; +import APPEND from './APPEND'; +import ASKING from './ASKING'; +import AUTH from './AUTH'; +import BGREWRITEAOF from './BGREWRITEAOF'; +import BGSAVE from './BGSAVE'; +import BITCOUNT from './BITCOUNT'; +import BITFIELD_RO from './BITFIELD_RO'; +import BITFIELD from './BITFIELD'; +import BITOP from './BITOP'; +import BITPOS from './BITPOS'; +import BLMOVE from './BLMOVE'; +import BLMPOP from './BLMPOP'; +import BLPOP from './BLPOP'; +import BRPOP from './BRPOP'; +import BRPOPLPUSH from './BRPOPLPUSH'; +import CLIENT_CACHING from './CLIENT_CACHING'; +import CLIENT_GETNAME from './CLIENT_GETNAME'; +import CLIENT_GETREDIR from './CLIENT_GETREDIR'; +import CLIENT_ID from './CLIENT_ID'; +import CLIENT_INFO from './CLIENT_INFO'; +import CLIENT_KILL from './CLIENT_KILL'; +import CLIENT_LIST from './CLIENT_LIST'; +import CLIENT_NO_EVICT from './CLIENT_NO-EVICT'; +import CLIENT_PAUSE from './CLIENT_PAUSE'; +import CLIENT_SETNAME from './CLIENT_SETNAME'; +import CLUSTER_ADDSLOTS from './CLUSTER_ADDSLOTS'; +import CLUSTER_SLOTS from './CLUSTER_SLOTS'; +import CLUSTER_MEET from './CLUSTER_MEET'; +import CLUSTER_MYID from './CLUSTER_MYID'; +import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; +import DECR from './DECR'; +import DECRBY from './DECRBY'; +import GET from './GET'; +import GETDEL from './GETDEL'; +import GETEX from './GETEX'; +import GETRANGE from './GETRANGE'; +import GETSET from './GETSET'; +import FLUSHALL from './FLUSHALL'; +import HDEL from './HDEL'; +import HEXISTS from './HEXISTS'; +import HGET from './HGET'; +import HGETALL from './HGETALL'; +import HINCRBY from './HINCRBY'; +import HINCRBYFLOAT from './HINCRBYFLOAT'; +import HKEYS from './HKEYS'; +import HLEN from './HLEN' +import HMGET from './HMGET'; +import HRANDFIELD_COUNT_WITHVALUES from './HRANDFIELD_COUNT_WITHVALUES'; +import HRANDFIELD_COUNT from './HRANDFIELD_COUNT'; +import HRANDFIELD from './HRANDFIELD'; +import HSCAN from './HSCAN'; +import HSET from './HSET'; +import HSETNX from './HSETNX'; +import HSTRLEN from './HSTRLEN'; +import HVALS from './HVALS'; +import INCR from './INCR'; +import INCRBY from './INCRBY'; +import INCRBYFLOAT from './INCRBYFLOAT'; +import INFO from './INFO'; +// import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; +// import LCS_IDX from './LCS_IDX'; +import LCS_LEN from './LCS_LEN'; +import LCS from './LCS'; +import LINDEX from './LINDEX'; +import LINSERT from './LINSERT'; +import LLEN from './LLEN'; +import LMOVE from './LMOVE'; +import LMPOP from './LMPOP'; +import LPOP from './LPOP'; +import LPOS from './LPOS'; +import LPUSH from './LPUSH'; +import LPUSHX from './LPUSHX'; +import LRANGE from './LRANGE'; +import LREM from './LREM'; +import LSET from './LSET'; +import LTRIM from './LTRIM'; +import MGET from './MGET'; +import MSET from './MSET'; +import MSETNX from './MSETNX'; +import PFADD from './PFADD'; +import PFCOUNT from './PFCOUNT'; +import PFMERGE from './PFMERGE'; +import PING from './PING'; +import PSETEX from './PSETEX'; +import RPOP from './RPOP'; +import RPOPLPUSH from './RPOPLPUSH'; +import RPUSH from './RPUSH'; +import RPUSHX from './RPUSHX'; +import SCAN from './SCAN'; +import SET from './SET'; +import SETEX from './SETEX'; +import SETNX from './SETNX'; +import SETRANGE from './SETRANGE'; +import SMEMBERS from './SMEMBERS'; +import SSCAN from './SSCAN'; +import STRLEN from './STRLEN'; +import ZSCAN from './ZSCAN'; +import { Command } from '../RESP/types'; -export type RedisCommandRawReply = string | number | Buffer | null | undefined | Array; - -export type RedisCommandArgument = string | Buffer; - -export type RedisCommandArguments = Array & { preserve?: unknown }; - -export interface RedisCommand { - FIRST_KEY_INDEX?: number | ((...args: Array) => RedisCommandArgument | undefined); - IS_READ_ONLY?: boolean; - TRANSFORM_LEGACY_REPLY?: boolean; - transformArguments(this: void, ...args: Array): RedisCommandArguments; - transformReply?(this: void, reply: any, preserved?: any): any; -} - -export type RedisCommandReply = - C['transformReply'] extends (...args: any) => infer T ? T : RedisCommandRawReply; - -export type ConvertArgumentType = - Type extends RedisCommandArgument ? ( - Type extends (string & ToType) ? Type : ToType - ) : ( - Type extends Set ? Set> : ( - Type extends Map ? Map> : ( - Type extends Array ? Array> : ( - Type extends Date ? Type : ( - Type extends Record ? { - [Property in keyof Type]: ConvertArgumentType - } : Type - ) - ) - ) - ) - ); - -export type RedisCommandSignature< - Command extends RedisCommand, - Params extends Array = Parameters -> = >( - ...args: Params | [options: Options, ...rest: Params] -) => Promise< - ConvertArgumentType< - RedisCommandReply, - Options['returnBuffers'] extends true ? Buffer : string - > ->; - -export interface RedisCommands { - [command: string]: RedisCommand; -} - -export interface RedisModule { - [command: string]: RedisCommand; -} - -export interface RedisModules { - [module: string]: RedisModule; -} - -export interface RedisFunction extends RedisCommand { - NUMBER_OF_KEYS?: number; -} - -export interface RedisFunctionLibrary { - [fn: string]: RedisFunction; -} - -export interface RedisFunctions { - [library: string]: RedisFunctionLibrary; -} - -export type RedisScript = RedisScriptConfig & SHA1; - -export interface RedisScripts { - [script: string]: RedisScript; -} - -export interface RedisExtensions< - M extends RedisModules = RedisModules, - F extends RedisFunctions = RedisFunctions, - S extends RedisScripts = RedisScripts -> { - modules?: M; - functions?: F; - scripts?: S; -} - -export type ExcludeMappedString = string extends S ? never : S; +export default { + ACL_CAT, + aclCat: ACL_CAT, + ACL_DRYRUN, + aclDryRun: ACL_DRYRUN, + ACL_GENPASS, + aclGenPass: ACL_GENPASS, + ACL_GETUSER, + aclGetUser: ACL_GETUSER, + ACL_LIST, + aclList: ACL_LIST, + ACL_LOAD, + aclLoad: ACL_LOAD, + ACL_LOG_RESET, + aclLogReset: ACL_LOG_RESET, + ACL_LOG, + aclLog: ACL_LOG, + ACL_SAVE, + aclSave: ACL_SAVE, + ACL_SETUSER, + aclSetUser: ACL_SETUSER, + ACL_USERS, + aclUsers: ACL_USERS, + ACL_WHOAMI, + aclWhoAmI: ACL_WHOAMI, + APPEND, + append: APPEND, + ASKING, + asking: ASKING, + AUTH, + auth: AUTH, + BGREWRITEAOF, + bgRewriteAof: BGREWRITEAOF, + BGSAVE, + bgSave: BGSAVE, + BITCOUNT, + bitCount: BITCOUNT, + BITFIELD_RO, + bitFieldRo: BITFIELD_RO, + BITFIELD, + bitField: BITFIELD, + BITOP, + bitOp: BITOP, + BITPOS, + bitPos: BITPOS, + BLMOVE, + blMove: BLMOVE, + BLMPOP, + blmPop: BLMPOP, + BLPOP, + blPop: BLPOP, + BRPOP, + brPop: BRPOP, + BRPOPLPUSH, + brPopLPush: BRPOPLPUSH, + CLIENT_CACHING, + clientCaching: CLIENT_CACHING, + CLIENT_GETNAME, + clientGetName: CLIENT_GETNAME, + CLIENT_GETREDIR, + clientGetRedir: CLIENT_GETREDIR, + CLIENT_ID, + clientId: CLIENT_ID, + CLIENT_INFO, + clientInfo: CLIENT_INFO, + CLIENT_KILL, + clientKill: CLIENT_KILL, + CLIENT_LIST, + clientList: CLIENT_LIST, + 'CLIENT_NO-EVICT': CLIENT_NO_EVICT, + clientNoEvict: CLIENT_NO_EVICT, + CLIENT_PAUSE, + clientPause: CLIENT_PAUSE, + CLIENT_SETNAME, + clientSetName: CLIENT_SETNAME, + CLUSTER_ADDSLOTS, + clusterAddSlots: CLUSTER_ADDSLOTS, + CLUSTER_SLOTS, + clusterSlots: CLUSTER_SLOTS, + CLUSTER_MEET, + clusterMeet: CLUSTER_MEET, + CLUSTER_MYID, + clusterMyId: CLUSTER_MYID, + CLUSTER_REPLICATE, + clusterReplicate: CLUSTER_REPLICATE, + DECR, + decr: DECR, + DECRBY, + decrBy: DECRBY, + GET, + get: GET, + GETDEL, + getDel: GETDEL, + GETEX, + getEx: GETEX, + GETRANGE, + getRange: GETRANGE, + GETSET, + getSet: GETSET, + FLUSHALL, + flushAll: FLUSHALL, + HDEL, + hDel: HDEL, + HEXISTS, + hExists: HEXISTS, + HGET, + hGet: HGET, + HGETALL, + hGetAll: HGETALL, + HINCRBY, + hIncrBy: HINCRBY, + HINCRBYFLOAT, + hIncrByFloat: HINCRBYFLOAT, + HKEYS, + hKeys: HKEYS, + HLEN, + hLen: HLEN, + HMGET, + hMGet: HMGET, + HRANDFIELD_COUNT_WITHVALUES, + hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, + HRANDFIELD_COUNT, + hRandFieldCount: HRANDFIELD_COUNT, + HRANDFIELD, + hRandField: HRANDFIELD, + HSCAN, + hScan: HSCAN, + HSET, + hSet: HSET, + HSETNX, + hSetNx: HSETNX, + HSTRLEN, + hStrLen: HSTRLEN, + HVALS, + hVals: HVALS, + INCR, + incr: INCR, + INCRBY, + incrBy: INCRBY, + INCRBYFLOAT, + incrByFloat: INCRBYFLOAT, + INFO, + info: INFO, + // LCS_IDX_WITHMATCHLEN, + // LCS_IDX, + LCS_LEN, + lcsLen: LCS_LEN, + LCS, + lcs: LCS, + LINDEX, + lIndex: LINDEX, + LINSERT, + lInsert: LINSERT, + LLEN, + lLen: LLEN, + LMOVE, + lMove: LMOVE, + LMPOP, + lmPop: LMPOP, + LPOP, + lPop: LPOP, + LPOS, + lPos: LPOS, + LPUSH, + lPush: LPUSH, + LPUSHX, + lPushX: LPUSHX, + LRANGE, + lRange: LRANGE, + LREM, + lRem: LREM, + LSET, + lSet: LSET, + LTRIM, + lTrim: LTRIM, + MGET, + mGet: MGET, + MSET, + mSet: MSET, + MSETNX, + mSetNx: MSETNX, + PFADD, + pfAdd: PFADD, + PFCOUNT, + pfCount: PFCOUNT, + PFMERGE, + pfMerge: PFMERGE, + PING, + /** + * ping jsdoc + */ + ping: PING, + PSETEX, + pSetEx: PSETEX, + RPOP, + rPop: RPOP, + RPOPLPUSH, + rPopLPush: RPOPLPUSH, + RPUSH, + rPush: RPUSH, + RPUSHX, + rPushX: RPUSHX, + SCAN, + scan: SCAN, + SET, + set: SET, + SETEX, + setEx: SETEX, + SETNX, + setNx: SETNX, + SETRANGE, + setRange: SETRANGE, + SMEMBERS, + sMembers: SMEMBERS, + SSCAN, + sScan: SSCAN, + STRLEN, + strLen: STRLEN, + ZSCAN, + zScan: ZSCAN +} as const satisfies Record; diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index 30709703153..898d3833a52 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -63,3 +63,7 @@ export class ErrorReply extends Error { this.stack = undefined; } } + +export class SimpleError extends ErrorReply {} + +export class BlobError extends ErrorReply {} diff --git a/packages/client/lib/lua-script.ts b/packages/client/lib/lua-script.ts index da19417ec25..8d20735a5f0 100644 --- a/packages/client/lib/lua-script.ts +++ b/packages/client/lib/lua-script.ts @@ -1,22 +1,22 @@ import { createHash } from 'crypto'; -import { RedisCommand } from './commands'; +import { Command } from './RESP/types'; -export interface RedisScriptConfig extends RedisCommand { - SCRIPT: string; - NUMBER_OF_KEYS?: number; +export type RedisScriptConfig = Command & { + SCRIPT: string | Buffer; + NUMBER_OF_KEYS?: number; } export interface SHA1 { - SHA1: string; + SHA1: string; } export function defineScript(script: S): S & SHA1 { - return { - ...script, - SHA1: scriptSha1(script.SCRIPT) - }; + return { + ...script, + SHA1: scriptSha1(script.SCRIPT) + }; } -export function scriptSha1(script: string): string { - return createHash('sha1').update(script).digest('hex'); +export function scriptSha1(script: RedisScriptConfig['SCRIPT']): string { + return createHash('sha1').update(script).digest('hex'); } diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 08f23ffa454..2c3f7f7ee7b 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -1,87 +1,60 @@ -import { fCallArguments } from './commander'; -import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisFunction, RedisScript } from './commands'; +import { Command, CommandArguments, RedisScript, TransformReply } from './RESP/types'; import { WatchError } from './errors'; export interface RedisMultiQueuedCommand { - args: RedisCommandArguments; - transformReply?: RedisCommand['transformReply']; + args: CommandArguments; + transformReply?: TransformReply; } export default class RedisMultiCommand { - static generateChainId(): symbol { - return Symbol('RedisMultiCommand Chain Id'); + static generateChainId(): symbol { + return Symbol('RedisMultiCommand Chain Id'); + } + + readonly queue: Array = []; + + readonly scriptsInUse = new Set(); + + addCommand(args: CommandArguments, transformReply?: TransformReply) { + this.queue.push({ + args, + transformReply + }); + return this; + } + + addScript(script: RedisScript, args: CommandArguments, transformReply?: TransformReply) { + const redisArgs: CommandArguments = []; + if (this.scriptsInUse.has(script.SHA1)) { + redisArgs.push('EVALSHA', script.SHA1); + } else { + this.scriptsInUse.add(script.SHA1); + redisArgs.push('EVAL', script.SCRIPT); } - readonly queue: Array = []; - - readonly scriptsInUse = new Set(); - - addCommand(args: RedisCommandArguments, transformReply?: RedisCommand['transformReply']): void { - this.queue.push({ - args, - transformReply - }); + if (script.NUMBER_OF_KEYS !== undefined) { + redisArgs.push(script.NUMBER_OF_KEYS.toString()); } - addFunction(name: string, fn: RedisFunction, args: Array): RedisCommandArguments { - const transformedArguments = fCallArguments( - name, - fn, - fn.transformArguments(...args) - ); - this.queue.push({ - args: transformedArguments, - transformReply: fn.transformReply - }); - return transformedArguments; - } - - addScript(script: RedisScript, args: Array): RedisCommandArguments { - const transformedArguments: RedisCommandArguments = []; - if (this.scriptsInUse.has(script.SHA1)) { - transformedArguments.push( - 'EVALSHA', - script.SHA1 - ); - } else { - this.scriptsInUse.add(script.SHA1); - transformedArguments.push( - 'EVAL', - script.SCRIPT - ); - } - - if (script.NUMBER_OF_KEYS !== undefined) { - transformedArguments.push(script.NUMBER_OF_KEYS.toString()); - } + redisArgs.push(...args); + redisArgs.preserve = args.preserve; - const scriptArguments = script.transformArguments(...args); - transformedArguments.push(...scriptArguments); - if (scriptArguments.preserve) { - transformedArguments.preserve = scriptArguments.preserve; - } - - this.addCommand( - transformedArguments, - script.transformReply - ); - - return transformedArguments; + return this.addCommand(redisArgs, transformReply); + } + + handleExecReplies(rawReplies: Array): Array { + const execReply = rawReplies[rawReplies.length - 1] as (null | Array); + if (execReply === null) { + throw new WatchError(); } - handleExecReplies(rawReplies: Array): Array { - const execReply = rawReplies[rawReplies.length - 1] as (null | Array); - if (execReply === null) { - throw new WatchError(); - } + return this.transformReplies(execReply); + } - return this.transformReplies(execReply); - } - - transformReplies(rawReplies: Array): Array { - return rawReplies.map((reply, i) => { - const { transformReply, args } = this.queue[i]; - return transformReply ? transformReply(reply, args.preserve) : reply; - }); - } + transformReplies(rawReplies: Array): Array { + return rawReplies.map((reply, i) => { + const { transformReply, args } = this.queue[i]; + return transformReply ? transformReply(reply, args.preserve) : reply; + }); + } } diff --git a/packages/client/package.json b/packages/client/package.json index c342fce26fa..7cd7c758d2a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -8,7 +8,7 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/commands/PING.spec.ts' './lib/commands/APPEND.spec.ts'", "build": "tsc", "lint": "eslint ./*.ts ./lib/**/*.ts", "documentation": "typedoc" @@ -21,19 +21,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "@types/sinon": "^10.0.13", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.53.0", - "@typescript-eslint/parser": "^5.53.0", - "eslint": "^8.34.0", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", + "eslint": "^8.36.0", "nyc": "^15.1.0", - "release-it": "^15.6.0", - "sinon": "^15.0.1", + "release-it": "^15.9.3", + "sinon": "^15.0.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" }, "engines": { "node": ">=14" diff --git a/packages/client/test.mjs b/packages/client/test.mjs new file mode 100644 index 00000000000..f50279ece2b --- /dev/null +++ b/packages/client/test.mjs @@ -0,0 +1,338 @@ +import { setTimeout } from 'timers/promises'; +import { createClient, defineScript, createCluster } from './dist/index.js'; +import { TYPES } from './dist/lib/RESP/decoder.js'; + +async function client() { + console.log(`!!! CLIENT !!!`); + + const client = createClient({ + RESP, + isolationPoolOptions: { + max: 5 + }, + modules: { + /** + * module jsdoc + */ + module: { + /** + * module ping jsdoc + */ + ping: { + /** + * @param {string} [message] + */ + transformArguments(message) { + const args = ['PING']; + if (message) { + args.push(message); + } + + return args; + }, + /** + * @callback PingReply + * @returns {import('./lib/RESP/types').SimpleStringReply} + * + * @type {PingReply} + */ + transformReply: undefined + }, + /** + * module square jsdoc + */ + square: { + /** + * @param {number} number + */ + transformArguments(number) { + return ['FCALL_RO', 'square', '0', number.toString()]; + }, + /** + * @callback SquareResp2 + * @returns {import('./lib/RESP/types').BlobStringReply} + * + * @callback SquareResp3 + * @returns {import('./lib/RESP/types').DoubleReply} + * + * @type {{ 2: SquareResp2, 3: SquareResp3 }} + */ + transformReply: undefined + } + } + }, + functions: { + /** + * library jsdoc + */ + library: { + /** + * library square jsdoc + */ + square: { + IS_READ_ONLY: true, + NUMBER_OF_KEYS: 0, + /** + * @param {number} number + */ + transformArguments(number) { + return [number.toString()]; + }, + /** + * @callback SquareResp2 + * @returns {import('./lib/RESP/types').BlobStringReply} + * + * @callback SquareResp3 + * @returns {import('./lib/RESP/types').DoubleReply} + * + * @type {{ 2: SquareResp2, 3: SquareResp3 }} + */ + transformReply: undefined + } + } + }, + scripts: { + /** + * square jsdoc + */ + square: defineScript({ + SCRIPT: 'return { double = ARGV[1] * ARGV[1] };', + NUMBER_OF_KEYS: 0, + /** + * @param {number} number + */ + transformArguments(number) { + return [number.toString()]; + }, + + /** + * @callback SquareResp2 + * @returns {import('./lib/RESP/types').BlobStringReply} + * + * @callback SquareResp3 + * @returns {import('./lib/RESP/types').DoubleReply} + * + * @type {{ 2: SquareResp2, 3: SquareResp3 }} + */ + transformReply: undefined + }) + } + }); + + const multi = client.multi() + .get('a') + .set('a', 'b'); + + for (let i = 0; i< 10; i++) { + multi.incr('a'); + } + + const result = await multi.exec(); + + const bufferClient = client.withFlags({ + [TYPES.SIMPLE_STRING]: Buffer, + [TYPES.BLOB_STRING]: Buffer + }); + + client.on('error', err => console.error(err)); + + await client.connect(); + + client.ping() + + // console.log( + // 'SCAN', + // await client.scan(0), + // await bufferClient.scan(0) + // ); + + // const fn = + // `#!LUA name=math + // redis.register_function{ + // function_name = "square", + // callback = function(keys, args) return { double = args[1] * args[1] } end, + // flags = { "no-writes" } + // }`; + + // await client.sendCommand(['FLUSHALL']); + // await client.sendCommand(['FUNCTION', 'LOAD', 'REPLACE', fn]); + + // console.log( + // 'info:\n', + // await client.info(), + // 'info with flags:\n', + // await client.withFlags({ + // [TYPES.VERBATIM_STRING]: VerbatimString + // }).info(), + // ); + + // console.log( + // 'client.module.square (module):', + // await client.module.square(1), + // await client.withFlags({ + // [TYPES.DOUBLE]: String + // }).module.square(1) + // ); + + // console.log( + // 'client.library.square (function):', + // await client.library.square(2), + // await client.withFlags({ + // [TYPES.DOUBLE]: String + // }).library.square(2) + // ); + + // console.log( + // 'client.square (script):', + // await client.square(4), + // await client.withFlags({ + // [TYPES.DOUBLE]: String + // }).square(4) + // ); + + // console.log( + // 'MULTI', + // await client.multi() + // .ping() + // .module.ping() + // .library.square(2) + // .square(4) + // .exec() + // ); + + // console.log( + // 'SET key value', + // await client.set('key', 'value'), + // ); + + // console.log( + // 'GET key', + // await client.get('key'), + // ); + + // console.log( + // 'GET key (bufferClient)', + // await bufferClient.get('key'), + // ); + + // console.log( + // 'sendCommand DEL key', + // await client.sendCommand(['DEL', 'key']) + // ); + + // console.log( + // 'HSET key field value', + // await client.hSet('key', 'field', 'value') + // ); + + // console.log( + // 'HGET key field', + // await client.hGet('key', 'field') + // ); + + // console.log( + // 'HGETALL key', + // await client.hGetAll('key') + // ); + + // console.log( + // 'HGETALL key (bufferClient)', + // await bufferClient.hGetAll('key') + // ); + + // console.log( + // 'CLIENT ID', + // await client.sendCommand(['CLIENT', 'ID']), + // ); + + // await client.subscribe('channel', message => { + // console.log('channel', message); + // }); + + // let publisherClient; + // if (RESP !== 3) { + // publisherClient = client.duplicate(); + // publisherClient.on('error', err => console.error('PubSubClient error', err)); + + // await publisherClient.connect(); + // } + + // const TIMES = 3; + // console.log( + // `[PUBLISH channel ] [PING ] * ${TIMES}`, + // await Promise.all( + // Array.from({ length: 5 }).map((_, i) => + // Promise.all([ + // (publisherClient ?? client).sendCommand(['PUBLISH', 'channel', i.toString()]).catch(), + // client.ping(i.toString()), + // client.isolated().clientId(), + // client.executeIsolated(client => client.clientId()) + // ]) + // ) + // ) + // ); + + const entries = Array.from({ length: 100 }).map((_, i) => ['{a}' + i.toString(), i.toString()]) + + await client.mSet(entries); + for await (const key of client.scanIterator()) { + console.log('SCAN', key); + } + + await client.hSet('hash', entries.flat()); + for await (const entry of client.hScanIterator('hash')) { + console.log('HSCAN', entry) + } + + await Promise.all([ + // publisherClient?.disconnect(), + client.disconnect() + ]); +} + +async function cluster() { + console.log(`!!! CLUSTER !!!`); + + const cluster = createCluster({ + rootNodes: [{}], + RESP + }); + cluster.on('error', err => console.error(err)); + + await cluster.connect(); + + console.log( + 'SET key value', + await cluster.set('key', 'value') + ); + + console.log( + 'GET key', + await cluster.get('key') + ); + + await cluster.subscribe('channel', message => { + console.log('(cluster) channel', message); + }); + + const CLUSTER_TIMES = 3; + console.log( + `[PUBLISH channel ] [PING ] * ${CLUSTER_TIMES}`, + await Promise.all( + Array.from({ length: 5 }).map(async (_, i) => { + const client = await cluster.nodeClient(cluster.getRandomNode()); + return client.sendCommand(['PUBLISH', 'channel', i.toString()]); + }) + ) + ); + + // wait for messages + await setTimeout(1000); + + await cluster.disconnect(); +} + +const RESP = 3; + +await client(); +// await cluster(); diff --git a/packages/graph/package.json b/packages/graph/package.json index 40ce8b7c560..d7e0e7f3686 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -18,12 +18,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" } } diff --git a/packages/json/lib/commands/GET.ts b/packages/json/lib/commands/GET.ts index 21bad09568b..107f9dd9750 100644 --- a/packages/json/lib/commands/GET.ts +++ b/packages/json/lib/commands/GET.ts @@ -1,4 +1,4 @@ -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; export const FIRST_KEY_INDEX = 1; @@ -17,7 +17,7 @@ export function transformArguments(key: string, options?: GetOptions): RedisComm let args: RedisCommandArguments = ['JSON.GET', key]; if (options?.path) { - args = pushVerdictArguments(args, options.path); + args = pushVariadicArguments(args, options.path); } if (options?.INDENT) { diff --git a/packages/json/package.json b/packages/json/package.json index 6f4c468bfd4..738f937b73d 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -18,12 +18,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" } } diff --git a/packages/old/RESP3-old/decoder.ts b/packages/old/RESP3-old/decoder.ts new file mode 100644 index 00000000000..a6b3a78248f --- /dev/null +++ b/packages/old/RESP3-old/decoder.ts @@ -0,0 +1,423 @@ +// RESP3 specification +// https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md + +import BufferComposer from '../RESP/composers/buffer'; +import { Composer } from '../RESP/composers/interface'; +import StringComposer from '../RESP/composers/string'; +import { Flags, Reply, ReplyTypes, TransformReplyType } from './types'; +import { NestedDecoderInterface } from './nested-decoders/abstract'; + +const ASCII = { + '\r': 13, + 't': 116, + '0': 48, + '-': 45, + '.': 46, + '?': 63, + 'n': 110, + 'i': 105 +}; + +export const RESP_TYPES = { + NULL: 95, // _ + BOOLEAN: 35, // # + NUMBER: 58, // : + BIG_NUMBER: 40, // ( + DOUBLE: 44, // , + SIMPLE_STRING: 43, // + + BLOB_STRING: 36, // $ + // VERBATIM_STRING: 61, // = + // SIMPLE_ERROR: 45, // - + // BLOB_ERROR: 33, // ! + ARRAY: 42, + MAP: 37, // % + SET: 126, // ~ + // ATTRIBUTE: 124, // | + // PUSH: 62 // > +} as const; + +type RespTypes = typeof RESP_TYPES[keyof typeof RESP_TYPES]; + +interface RESP3DecoderConfig { + onReply(reply: Reply): unknown; +} + +type NestedState = NestedDecoderInterface; + +// interface NestedState< +// REMAINING extends number | undefined = number | undefined, +// REPLY extends NestedDecoderInterface = NestedDecoderInterface +// > { +// type?: RespTypes; +// remaining: REMAINING; +// reply: REPLY; +// } + +// Using TypeScript `private` and not the build-in `#` to avoid __classPrivateFieldGet and __classPrivateFieldSet + +export default class RESP3Decoder { + constructor(private config: RESP3DecoderConfig) {} + + private cursor = 0; + + private type?: RespTypes; + + write(chunk: Buffer, flags: Flags): void { + while (this.cursor < chunk.length) { + let reply = this.decode(chunk, flags); + if (reply !== undefined) { + this.config.onReply(reply); + } + } + + this.cursor -= chunk.length; + } + + private decode(chunk: Buffer, flags: Flags) { + // while (this.stack.length) { + // if (this.type !== undefined) { + // const item = this.decodeType(chunk, this.type, flags); + // if (item === undefined) return; + + // let toPush = item; + // do { + // toPush = this.stack[this.stack.length - 1].reply.push(item); + // } while (toPush); + + // } + + // if (reply !== undefined) { + // const toPush = this.stack.pop(); + // this.stack[this.stack.length].reply.push(reply); + // } + // } + if (this.type === undefined) { + const type = chunk[this.cursor] as RespTypes; + if (++this.cursor === chunk.length) { + this.type = type; + return; + } + const reply = this.decodeType(chunk, type, flags); + if (reply === undefined) { + this.type = type; + } else { + return reply; + } + } + + const reply = this.decodeType(chunk, this.type, flags); + if (reply !== undefined) { + this.type = undefined; + return reply; + } + } + + private decodeType(chunk: Buffer, type: T, flags: F) { + switch (type) { + case RESP_TYPES.NULL: + return this.decodeNull(); + + case RESP_TYPES.BOOLEAN: + return this.decodeBoolean(chunk); + + case RESP_TYPES.NUMBER: + return this.decodeNumber(chunk, flags); + + // case RESP_TYPES.BIG_NUMBER: + // return this.decodeBigNumber(chunk); + + case RESP_TYPES.DOUBLE: + return this.decodeDouble(chunk, flags); + + case RESP_TYPES.SIMPLE_STRING: + return this.decodeSimpleString(chunk, flags); + + case RESP_TYPES.MAP: + return this.decodeMap(chunk, flags); + } + } + + private decodeNull() { + this.cursor += 2; // skip CRLF + return null; + } + + private decodeBoolean(chunk: Buffer) { + const reply = chunk[this.cursor + 1] === ASCII.t; + this.cursor += 3; // skip value and CRLF + return reply; + } + + private decodeNumber(chunk: Buffer, flags: F) { + switch (flags[RESP_TYPES.NUMBER]) { + case Buffer: + return this.composeString(chunk, this.bufferComposer); + + case String: + return this.composeString(chunk, this.stringComposer); + + case Number: + default: + return this.decodeNumberAsNumber(chunk); + } + } + + private isNegativeNumber?: boolean; + + private number = 0; + + private decodeNumberAsNumber(chunk: Buffer) { + if (this.isNegativeNumber === undefined) { + this.isNegativeNumber = chunk[this.cursor] === ASCII['-']; + if (this.isNegativeNumber && ++this.cursor === chunk.length) return; + } + + do { + const byte = chunk[this.cursor]; + if (byte === ASCII['\r']) { + const number = this.isNegativeNumber ? -this.number : this.number; + this.isNegativeNumber = undefined; + this.number = 0; + this.cursor += 2; // skip CRLF + return number; + } + + this.number = this.number * 10 + byte - ASCII['0']; + } while (++this.cursor < chunk.length); + } + + private isNegativeDouble?: boolean; + + // Precalculated multipliers for decimal points to improve performance + // "A Number only keeps about 17 decimal places of precision" + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + private static DOUBLE_DECIMAL_MULTIPLIERS = [ + 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, + 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, + 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 + ]; + + private doubleDecimalIndex?: number; + + private double = 0; + + private decodeDouble(chunk: Buffer, flags: Flags) { + switch (flags[RESP_TYPES.NUMBER]) { + case Buffer: + return this.composeString(chunk, this.bufferComposer); + + case String: + return this.composeString(chunk, this.stringComposer); + + case Number: + default: + return this.decodeDoubleAsNumber(chunk); + } + } + + private decodeDoubleAsNumber(chunk: Buffer) { + if (this.isNegativeDouble === undefined) { + this.isNegativeDouble = chunk[this.cursor] === ASCII['-']; + if (this.isNegativeDouble && ++this.cursor === chunk.length) return; + } else if (this.doubleDecimalIndex !== undefined) { + return this.decodeDecimalDouble(chunk); + } + + if (this.double === 0) { + switch (chunk[this.cursor]) { + case ASCII.i: + this.cursor += 3; // skip to CRLF + return this.returnDouble(Infinity); + + case ASCII.n: + this.cursor += 3; // skip to CRLF + return this.returnDouble(NaN); + } + } + + do { + const byte = chunk[this.cursor]; + switch (byte) { + case ASCII['\r']: + return this.returnDouble(); + + case ASCII['.']: + this.doubleDecimalIndex = 0; + if (++this.cursor === chunk.length) return; + return this.decodeDecimalDouble(chunk); + + default: + this.double = this.double * 10 + byte - ASCII['0']; + } + } while (++this.cursor < chunk.length); + } + + private returnDouble(value = this.double) { + const double = this.isNegativeDouble ? -value : value; + this.isNegativeDouble = undefined; + this.doubleDecimalIndex = undefined; + this.double = 0; + this.cursor += 2; // skip CRLF + return double; + } + + private decodeDecimalDouble(chunk: Buffer): number | undefined { + do { + const byte = chunk[this.cursor]; + if (byte === ASCII['\r']) { + return this.returnDouble(); + } + + if (RESP3Decoder.DOUBLE_DECIMAL_MULTIPLIERS.length < this.doubleDecimalIndex!) { + const multiplier = RESP3Decoder.DOUBLE_DECIMAL_MULTIPLIERS[this.doubleDecimalIndex!++]; + this.double += (byte - ASCII['0']) * multiplier; + } + } while (++this.cursor < chunk.length); + } + + private bufferComposer = new BufferComposer(); + + private stringComposer = new StringComposer(); + + private decodeSimpleString(chunk: Buffer, flags: Flags) { + switch (flags[RESP_TYPES.SIMPLE_STRING]) { + case Buffer: + return this.composeString(chunk, this.bufferComposer); + + case String: + default: + return this.composeString(chunk, this.stringComposer); + } + } + + private composeString(chunk: Buffer, composer: Composer): T | undefined { + for (let i = this.cursor; i < chunk.length; i++) { + if (chunk[i] === ASCII['\r']) { + const reply = composer.end( + chunk.subarray(this.cursor, i) + ); + this.cursor = i + 2; + return reply; + } + } + + const toWrite = chunk.subarray(this.cursor); + composer.write(toWrite); + this.cursor = chunk.length; + } + + private initializingNested = false; + + private nestedStack: Array<{ + type: RespTypes | undefined, + size: number, + value: Reply | undefined + }> = []; + + private decodeNested(type: RespTypes, chunk: Buffer, flags: Flags, toKeep: number) { + if (this.nestedStack.length > toKeep) { + const frame = this.nestedStack[this.nestedStack.length - 1]; + if (frame.type === undefined) { + frame.type = chunk[this.cursor++] as RespTypes; + if (this.cursor === chunk.length) return; + } + + + } + if (this.initializingNested || this.nestedStack.length === toKeep) { + // TODO: https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-aggregated-data-types + if (chunk[this.cursor] === ASCII['?']) { + this.cursor += 3; // skip ? and CRLF + this.nestedStack.push({ + type: undefined, + size: NaN, + value: undefined + }); + } + const size = this.decodeNumberAsNumber(chunk); + if (size === undefined) { + this.initializingNested = true; + return; + } + + } + } + + // private mapKey?: Reply; + + // private decodeMap(chunk: Buffer, flags: Flags) { + // // const isNew = depth >= this.stack.length; + // // let state = this.stack[depth]; + // // if (state?.remaining === undefined) { + // // const size = this.decodeNumberAsNumber(chunk); + // // if (size === undefined) { + // // this.stack.push({ + // // type: RESP_TYPES.MAP, + // // remaining: undefined, + // // reply: undefined + // // }); + // // return; + // // } + // // if (size === 0) return {}; + // // state = { + // // type: RESP_TYPES.MAP, + // // remaining: size, + // // reply: {} + // // }; + // // } else { + // // state = this.stack[depth]; + // // } + // // // state = isNew ? this.stack[depth] : { + // // // type: RESP_TYPES.MAP, + // // // remaining: undefined, + // // // reply: undefined + // // // }; + + // switch (flags[RESP_TYPES.MAP]) { + // case Object: + // return this.decodeMapAsObject(chunk, flags, state, depth); // TODO + + // case Array: + // return; // TODO + + // case Map: + // default: + // return; // TODO + // } + // } + + // private decodeMapAsObject(chunk: Buffer, flags: Flags, state: NestedDecoderState, depth: number) { + // if (this.mapKey !== undefined) { + // const value = this. + // } + + // do { + // const key = this.decodeNewItem(chunk, flags); + // if (key === undefined) break; + // const value = this.decodeNewItem(chunk, flags); + // if (value === undefined) break; + // state.reply[`${key}`] = value; + + // if (--state.remaining! === 0) return state.reply; + // } while (this.cursor < chunk.length); + // } + + // private keepNested(chunk: Buffer, flags: Flags) { + // const reply = this.decodeType(chunk, this.stack[this.stack.length - 1], flags) + // } + + + reset() { + this.cursor = 0; + this.type = undefined; + this.isNegativeNumber = undefined; + this.number = 0; + this.isNegativeDouble = undefined; + this.doubleDecimalIndex = undefined; + this.double = 0; + this.bufferComposer.reset(); + this.stringComposer.reset(); + this.initializingNested = false; + this.nestedStack = []; + } +} \ No newline at end of file diff --git a/packages/old/RESP3-old/encoder.ts b/packages/old/RESP3-old/encoder.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/old/RESP3-old/nested-decoders/abstract.ts b/packages/old/RESP3-old/nested-decoders/abstract.ts new file mode 100644 index 00000000000..b3e5b5c304f --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/abstract.ts @@ -0,0 +1,6 @@ +import { Reply } from '../types'; + +export interface NestedDecoderInterface { + push(item: Reply): void | undefined | T; +} + diff --git a/packages/old/RESP3-old/nested-decoders/map-to-array.ts b/packages/old/RESP3-old/nested-decoders/map-to-array.ts new file mode 100644 index 00000000000..21c03567ade --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/map-to-array.ts @@ -0,0 +1,28 @@ +import { NestedDecoderInterface } from './abstract'; +import { Reply } from '../types'; + +type Type = Array<[Reply, Reply]>; + +export class MapToArray implements NestedDecoderInterface { + private array: Type; + + private remaining: number; + + constructor(size: number) { + this.array = new Array(size); + this.remaining = size; + } + + private key: Reply | undefined; + + push(item: Reply) { + if (this.key === undefined) { + this.key = item; + return; + } + + this.array[this.array.length - this.remaining--] = [this.key, item]; + this.key = undefined; + if (this.remaining === 0) return this.array; + } +} diff --git a/packages/old/RESP3-old/nested-decoders/to-array.ts b/packages/old/RESP3-old/nested-decoders/to-array.ts new file mode 100644 index 00000000000..ae4d2d7cc2f --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/to-array.ts @@ -0,0 +1,20 @@ +import { NestedDecoderInterface } from './abstract'; +import { Reply } from '../types'; + +type Type = Array; + +export class ToArray implements NestedDecoderInterface { + private array: Type; + + private remaining: number; + + constructor(size: number) { + this.array = new Array(size); + this.remaining = size; + } + + push(item: Reply) { + this.array[this.array.length - this.remaining--] = item; + if (this.remaining === 0) return this.array; + } +} diff --git a/packages/old/RESP3-old/nested-decoders/to-map.ts b/packages/old/RESP3-old/nested-decoders/to-map.ts new file mode 100644 index 00000000000..d689a04cb26 --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/to-map.ts @@ -0,0 +1,28 @@ +import { NestedDecoderInterface } from './abstract'; +import { Reply } from '../types'; + +type Type = Map; + +export class MapToArray implements NestedDecoderInterface { + private map: Type; + + private remaining: number; + + constructor(size: number) { + this.map = new Map(); + this.remaining = size; + } + + private key: Reply | undefined; + + push(item: Reply) { + if (this.key === undefined) { + this.key = item; + return; + } + + this.map.set(this.key, item); + this.key = undefined; + if (--this.remaining === 0) return this.map; + } +} diff --git a/packages/old/RESP3-old/nested-decoders/to-object.ts b/packages/old/RESP3-old/nested-decoders/to-object.ts new file mode 100644 index 00000000000..7fe47269795 --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/to-object.ts @@ -0,0 +1,28 @@ +import { NestedDecoderInterface } from './abstract'; +import { Reply } from '../types'; + +type Type = Record; + +export class MapToArray implements NestedDecoderInterface { + private object: Type; + + private remaining: number; + + constructor(size: number) { + this.object = {}; + this.remaining = size; + } + + private key: Reply | undefined; + + push(item: Reply) { + if (this.key === undefined) { + this.key = item; + return; + } + + this.object[this.key] = item; + this.key = undefined; + if (--this.remaining === 0) return this.object; + } +} diff --git a/packages/old/RESP3-old/nested-decoders/to-set.ts b/packages/old/RESP3-old/nested-decoders/to-set.ts new file mode 100644 index 00000000000..d44444c97c1 --- /dev/null +++ b/packages/old/RESP3-old/nested-decoders/to-set.ts @@ -0,0 +1,20 @@ +import { NestedDecoderInterface } from './abstract'; +import { Reply } from '../types'; + +type Type = Set; + +export class ToArray implements NestedDecoderInterface { + private set: Type; + + private remaining: number; + + constructor(size: number) { + this.set = new Set(); + this.remaining = size; + } + + push(item: Reply) { + this.set.add(item); + if (--this.remaining === 0) return this.set; + } +} diff --git a/packages/old/RESP3-old/types.ts b/packages/old/RESP3-old/types.ts new file mode 100644 index 00000000000..a15c851ce7f --- /dev/null +++ b/packages/old/RESP3-old/types.ts @@ -0,0 +1,101 @@ +import { RESP_TYPES } from './decoder'; + +type RESP_TYPES = { + [P in keyof typeof RESP_TYPES]: typeof RESP_TYPES[P]; +}; + +interface TypeMapping { + DEFAULT_TYPE: DEFAULT_TYPE; + TYPES: TYPES; +} + +interface TypesMapping { + [RESP_TYPES.NULL]: TypeMapping; + [RESP_TYPES.BOOLEAN]: TypeMapping; + [RESP_TYPES.NUMBER]: TypeMapping; + [RESP_TYPES.BIG_NUMBER]: TypeMapping; + [RESP_TYPES.DOUBLE]: TypeMapping; + [RESP_TYPES.SIMPLE_STRING]: TypeMapping; + [RESP_TYPES.BLOB_STRING]: TypeMapping; + [RESP_TYPES.ARRAY]: ArrayReplyTypeMapping; + [RESP_TYPES.MAP]: MapReplyTypeMapping; + [RESP_TYPES.SET]: SetReplyTypeMapping; +} + +type ArrayReplyTypeMapping = TypeMapping>; + +type ArrayReply = ReplyType>; + +type MapReplyTypeMapping = TypeMapping, { [key: string]: V; } | Array<[K, V]>>; + +type MapReply = ReplyType>; + +type SetReplyTypeMapping = TypeMapping, Array>; + +type SetReply = ReplyType>; + +type ReplyType< + RESP_TYPE extends RESP_TYPES[keyof RESP_TYPES], + TYPES extends TypeMapping +> = { + // TypeScript uses structural typing, `unique symbol` is the only way to make a type unique + // https://www.typescriptlang.org/docs/handbook/symbols.html#unique-symbol + // not using `[P in RESP_TYPE]` because it breaks inference in some cases + SYMBOL: { readonly _: unique symbol; }; + RESP_TYPE: RESP_TYPE; +} & TYPES; + +export type ReplyTypes = { + [P in keyof TypesMapping]: ReplyType; +}; + +type PrimitiveReplyTypes = ReplyTypes[Exclude]; + +type TT = TypeMapping>; + +export type Reply = string | TT; + +type Flag = (new (...args: Array) => T) | ((...args: Array) => T); + +export type Flags = { + [P in keyof TypesMapping]?: Flag; +}; + +type PickByFlag< + FLAT_TYPE, + TYPES extends TypeMapping +> = TYPES['DEFAULT_TYPE'] extends FLAT_TYPE ? TYPES['DEFAULT_TYPE'] : Extract; + +export type TransformReplyType< + FLAGS extends Flags, + REPLY +> = REPLY extends ReplyType ? ( + TransformReplyType ? PickByFlag : TYPES['DEFAULT_TYPE']> + ) : + REPLY extends Map ? Map, TransformReplyType> : + REPLY extends [infer T] ? [TransformReplyType] : + REPLY extends [infer T, ...infer REST] ? [TransformReplyType, ...TransformReplyType] : + REPLY extends Array ? Array> : + REPLY extends Record ? { + [K in keyof REPLY]: TransformReplyType + } : + REPLY extends Set ? Set> : REPLY; + +type a = TransformReplyType< + { + // [RESP_TYPES.MAP]: ArrayConstructor + [RESP_TYPES.DOUBLE]: StringConstructor, + // [RESP_TYPES.NUMBER]: BufferConstructor + }, + { + null: ReplyTypes[RESP_TYPES['NULL']], + boolean: ReplyTypes[RESP_TYPES['BOOLEAN']], + number: ReplyTypes[RESP_TYPES['NUMBER']], + bigNumber: ReplyTypes[RESP_TYPES['BIG_NUMBER']], + array: ArrayReply, + map: MapReply, + set: SetReply + } +>; + +type b = TransformReplyType ? PickByFlag> : number>; diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index c32d20b0b1c..fb831f54bc0 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -1,5 +1,5 @@ import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; import { Params, PropertyName, pushArgumentsWithLength, pushParamsArgs, pushSortByArguments, SortByProperty } from '.'; export enum AggregateSteps { @@ -170,7 +170,7 @@ export function pushAggregatehOptions( if (!step.properties) { args.push('0'); } else { - pushVerdictArgument(args, step.properties); + pushVariadicArgument(args, step.properties); } if (Array.isArray(step.REDUCE)) { diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index 21662c28d7d..32440ede38e 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -1,4 +1,4 @@ -import { pushOptionalVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { RedisSearchLanguages, PropertyName, RediSearchSchema, pushSchema } from '.'; interface CreateOptions { @@ -27,7 +27,7 @@ export function transformArguments(index: string, schema: RediSearchSchema, opti args.push('ON', options.ON); } - pushOptionalVerdictArgument(args, 'PREFIX', options?.PREFIX); + pushOptionalVariadicArgument(args, 'PREFIX', options?.PREFIX); if (options?.FILTER) { args.push('FILTER', options.FILTER); @@ -81,7 +81,7 @@ export function transformArguments(index: string, schema: RediSearchSchema, opti args.push('SKIPINITIALSCAN'); } - pushOptionalVerdictArgument(args, 'STOPWORDS', options?.STOPWORDS); + pushOptionalVariadicArgument(args, 'STOPWORDS', options?.STOPWORDS); args.push('SCHEMA'); pushSchema(args, schema); diff --git a/packages/search/lib/commands/DICTADD.ts b/packages/search/lib/commands/DICTADD.ts index 60af11fd41f..2a8d9c522bc 100644 --- a/packages/search/lib/commands/DICTADD.ts +++ b/packages/search/lib/commands/DICTADD.ts @@ -1,8 +1,8 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { - return pushVerdictArguments(['FT.DICTADD', dictionary], term); + return pushVariadicArguments(['FT.DICTADD', dictionary], term); } export declare function transformReply(): number; diff --git a/packages/search/lib/commands/DICTDEL.ts b/packages/search/lib/commands/DICTDEL.ts index a1b728f1926..8a8513f5595 100644 --- a/packages/search/lib/commands/DICTDEL.ts +++ b/packages/search/lib/commands/DICTDEL.ts @@ -1,8 +1,8 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { - return pushVerdictArguments(['FT.DICTDEL', dictionary], term); + return pushVariadicArguments(['FT.DICTDEL', dictionary], term); } export declare function transformReply(): number; diff --git a/packages/search/lib/commands/SYNUPDATE.ts b/packages/search/lib/commands/SYNUPDATE.ts index 3384ea59d94..80582759c47 100644 --- a/packages/search/lib/commands/SYNUPDATE.ts +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -1,4 +1,4 @@ -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; interface SynUpdateOptions { @@ -17,7 +17,7 @@ export function transformArguments( args.push('SKIPINITIALSCAN'); } - return pushVerdictArguments(args, terms); + return pushVariadicArguments(args, terms); } export declare function transformReply(): 'OK'; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index d56db7bdbbe..f3fb16d7021 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -32,7 +32,7 @@ import * as SYNDUMP from './SYNDUMP'; import * as SYNUPDATE from './SYNUPDATE'; import * as TAGVALS from './TAGVALS'; import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushOptionalVerdictArgument, pushVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { SearchOptions } from './SEARCH'; export default { @@ -411,9 +411,9 @@ export function pushSearchOptions( // args.push('WITHPAYLOADS'); // } - pushOptionalVerdictArgument(args, 'INKEYS', options?.INKEYS); - pushOptionalVerdictArgument(args, 'INFIELDS', options?.INFIELDS); - pushOptionalVerdictArgument(args, 'RETURN', options?.RETURN); + pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); + pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); + pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); if (options?.SUMMARIZE) { args.push('SUMMARIZE'); @@ -421,7 +421,7 @@ export function pushSearchOptions( if (typeof options.SUMMARIZE === 'object') { if (options.SUMMARIZE.FIELDS) { args.push('FIELDS'); - pushVerdictArgument(args, options.SUMMARIZE.FIELDS); + pushVariadicArgument(args, options.SUMMARIZE.FIELDS); } if (options.SUMMARIZE.FRAGS) { @@ -444,7 +444,7 @@ export function pushSearchOptions( if (typeof options.HIGHLIGHT === 'object') { if (options.HIGHLIGHT.FIELDS) { args.push('FIELDS'); - pushVerdictArgument(args, options.HIGHLIGHT.FIELDS); + pushVariadicArgument(args, options.HIGHLIGHT.FIELDS); } if (options.HIGHLIGHT.TAGS) { diff --git a/packages/search/package.json b/packages/search/package.json index 684bfe1ff00..43f50ade83c 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -18,12 +18,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" } } diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index a7e1c610eee..d750b7d5121 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -2,259 +2,263 @@ import { createConnection } from 'net'; import { once } from 'events'; import RedisClient from '@redis/client/dist/lib/client'; import { promiseTimeout } from '@redis/client/dist/lib/utils'; -import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; +// import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; import * as path from 'path'; import { promisify } from 'util'; import { exec } from 'child_process'; const execAsync = promisify(exec); interface ErrorWithCode extends Error { - code: string; + code: string; } async function isPortAvailable(port: number): Promise { - try { - const socket = createConnection({ port }); - await once(socket, 'connect'); - socket.end(); - } catch (err) { - if (err instanceof Error && (err as ErrorWithCode).code === 'ECONNREFUSED') { - return true; - } + try { + const socket = createConnection({ port }); + await once(socket, 'connect'); + socket.end(); + } catch (err) { + if (err instanceof Error && (err as ErrorWithCode).code === 'ECONNREFUSED') { + return true; } + } - return false; + return false; } -const portIterator = (async function*(): AsyncIterableIterator { - for (let i = 6379; i < 65535; i++) { - if (await isPortAvailable(i)) { - yield i; - } +const portIterator = (async function* (): AsyncIterableIterator { + for (let i = 6379; i < 65535; i++) { + if (await isPortAvailable(i)) { + yield i; } + } - throw new Error('All ports are in use'); + throw new Error('All ports are in use'); })(); export interface RedisServerDockerConfig { - image: string; - version: string; + image: string; + version: string; } export interface RedisServerDocker { - port: number; - dockerId: string; + port: number; + dockerId: string; } // ".." cause it'll be in `./dist` const DOCKER_FODLER_PATH = path.join(__dirname, '../docker'); async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array): Promise { - const port = (await portIterator.next()).value, - { stdout, stderr } = await execAsync( - 'docker run -d --network host $(' + - `docker build ${DOCKER_FODLER_PATH} -q ` + - `--build-arg IMAGE=${image}:${version} ` + - `--build-arg REDIS_ARGUMENTS="--save '' --port ${port.toString()} ${serverArguments.join(' ')}"` + - ')' - ); + const port = (await portIterator.next()).value, + { stdout, stderr } = await execAsync( + 'docker run -d --network host $(' + + `docker build ${DOCKER_FODLER_PATH} -q ` + + `--build-arg IMAGE=${image}:${version} ` + + `--build-arg REDIS_ARGUMENTS="--save '' --port ${port.toString()} ${serverArguments.join(' ')}"` + + ')' + ); - if (!stdout) { - throw new Error(`docker run error - ${stderr}`); - } + if (!stdout) { + throw new Error(`docker run error - ${stderr}`); + } - while (await isPortAvailable(port)) { - await promiseTimeout(50); - } + while (await isPortAvailable(port)) { + await promiseTimeout(50); + } - return { - port, - dockerId: stdout.trim() - }; + return { + port, + dockerId: stdout.trim() + }; } const RUNNING_SERVERS = new Map, ReturnType>(); export function spawnRedisServer(dockerConfig: RedisServerDockerConfig, serverArguments: Array): Promise { - const runningServer = RUNNING_SERVERS.get(serverArguments); - if (runningServer) { - return runningServer; - } - - const dockerPromise = spawnRedisServerDocker(dockerConfig, serverArguments); - RUNNING_SERVERS.set(serverArguments, dockerPromise); - return dockerPromise; + const runningServer = RUNNING_SERVERS.get(serverArguments); + if (runningServer) { + return runningServer; + } + + const dockerPromise = spawnRedisServerDocker(dockerConfig, serverArguments); + RUNNING_SERVERS.set(serverArguments, dockerPromise); + return dockerPromise; } async function dockerRemove(dockerId: string): Promise { - const { stderr } = await execAsync(`docker rm -f ${dockerId}`); - if (stderr) { - throw new Error(`docker rm error - ${stderr}`); - } + const { stderr } = await execAsync(`docker rm -f ${dockerId}`); + if (stderr) { + throw new Error(`docker rm error - ${stderr}`); + } } after(() => { - return Promise.all( - [...RUNNING_SERVERS.values()].map(async dockerPromise => - await dockerRemove((await dockerPromise).dockerId) - ) - ); + return Promise.all( + [...RUNNING_SERVERS.values()].map(async dockerPromise => + await dockerRemove((await dockerPromise).dockerId) + ) + ); }); export interface RedisClusterDockersConfig extends RedisServerDockerConfig { - numberOfMasters?: number; - numberOfReplicas?: number; + numberOfMasters?: number; + numberOfReplicas?: number; } async function spawnRedisClusterNodeDockers( - dockersConfig: RedisClusterDockersConfig, - serverArguments: Array, - fromSlot: number, - toSlot: number + dockersConfig: RedisClusterDockersConfig, + serverArguments: Array, + fromSlot: number, + toSlot: number ) { - const range: Array = []; - for (let i = fromSlot; i < toSlot; i++) { - range.push(i); - } - - const master = await spawnRedisClusterNodeDocker( - dockersConfig, - serverArguments - ); + const range: Array = []; + for (let i = fromSlot; i < toSlot; i++) { + range.push(i); + } + + const master = await spawnRedisClusterNodeDocker( + dockersConfig, + serverArguments + ); + + await master.client.clusterAddSlots(range); + + if (!dockersConfig.numberOfReplicas) return [master]; + + const replicasPromises: Array> = []; + for (let i = 0; i < (dockersConfig.numberOfReplicas ?? 0); i++) { + replicasPromises.push( + spawnRedisClusterNodeDocker(dockersConfig, [ + ...serverArguments, + '--cluster-enabled', + 'yes', + '--cluster-node-timeout', + '5000' + ]).then(async replica => { + await replica.client.clusterMeet('127.0.0.1', master.docker.port); + + while ((await replica.client.clusterSlots()).length === 0) { + await promiseTimeout(50); + } - await master.client.clusterAddSlots(range); - - if (!dockersConfig.numberOfReplicas) return [master]; - - const replicasPromises: Array> = []; - for (let i = 0; i < (dockersConfig.numberOfReplicas ?? 0); i++) { - replicasPromises.push( - spawnRedisClusterNodeDocker(dockersConfig, [ - ...serverArguments, - '--cluster-enabled', - 'yes', - '--cluster-node-timeout', - '5000' - ]).then(async replica => { - await replica.client.clusterMeet('127.0.0.1', master.docker.port); - - while ((await replica.client.clusterSlots()).length === 0) { - await promiseTimeout(50); - } - - await replica.client.clusterReplicate( - await master.client.clusterMyId() - ); - - return replica; - }) + await replica.client.clusterReplicate( + await master.client.clusterMyId() ); - } - return [ - master, - ...await Promise.all(replicasPromises) - ]; + return replica; + }) + ); + } + + return [ + master, + ...await Promise.all(replicasPromises) + ]; } async function spawnRedisClusterNodeDocker( - dockersConfig: RedisClusterDockersConfig, - serverArguments: Array + dockersConfig: RedisClusterDockersConfig, + serverArguments: Array ) { - const docker = await spawnRedisServerDocker(dockersConfig, [ - ...serverArguments, - '--cluster-enabled', - 'yes', - '--cluster-node-timeout', - '5000' - ]), - client = RedisClient.create({ - socket: { - port: docker.port - } - }); - - await client.connect(); - - return { - docker, - client - }; + const docker = await spawnRedisServerDocker(dockersConfig, [ + ...serverArguments, + '--cluster-enabled', + 'yes', + '--cluster-node-timeout', + '5000' + ]), + client = RedisClient.create({ + socket: { + port: docker.port + } + }); + + await client.connect(); + + return { + docker, + client + }; } const SLOTS = 16384; async function spawnRedisClusterDockers( - dockersConfig: RedisClusterDockersConfig, - serverArguments: Array + dockersConfig: RedisClusterDockersConfig, + serverArguments: Array ): Promise> { - const numberOfMasters = dockersConfig.numberOfMasters ?? 2, - slotsPerNode = Math.floor(SLOTS / numberOfMasters), - spawnPromises: Array> = []; - for (let i = 0; i < numberOfMasters; i++) { - const fromSlot = i * slotsPerNode, - toSlot = i === numberOfMasters - 1 ? SLOTS : fromSlot + slotsPerNode; - spawnPromises.push( - spawnRedisClusterNodeDockers( - dockersConfig, - serverArguments, - fromSlot, - toSlot - ) - ); - } + const numberOfMasters = dockersConfig.numberOfMasters ?? 2, + slotsPerNode = Math.floor(SLOTS / numberOfMasters), + spawnPromises: Array> = []; + for (let i = 0; i < numberOfMasters; i++) { + const fromSlot = i * slotsPerNode, + toSlot = i === numberOfMasters - 1 ? SLOTS : fromSlot + slotsPerNode; + spawnPromises.push( + spawnRedisClusterNodeDockers( + dockersConfig, + serverArguments, + fromSlot, + toSlot + ) + ); + } - const nodes = (await Promise.all(spawnPromises)).flat(), - meetPromises: Array> = []; - for (let i = 1; i < nodes.length; i++) { - meetPromises.push( - nodes[i].client.clusterMeet('127.0.0.1', nodes[0].docker.port) - ); - } + const nodes = (await Promise.all(spawnPromises)).flat(), + meetPromises: Array> = []; + for (let i = 1; i < nodes.length; i++) { + meetPromises.push( + nodes[i].client.clusterMeet('127.0.0.1', nodes[0].docker.port) + ); + } - await Promise.all(meetPromises); + await Promise.all(meetPromises); - await Promise.all( - nodes.map(async ({ client }) => { - while (totalNodes(await client.clusterSlots()) !== nodes.length) { - await promiseTimeout(50); - } - - return client.disconnect(); - }) - ); + await Promise.all( + nodes.map(async ({ client }) => { + while ( + totalNodes(await client.clusterSlots()) !== nodes.length || + !(await client.sendCommand(['CLUSTER', 'INFO'])).startsWith('cluster_state:ok') // TODO + ) { + await promiseTimeout(50); + } + + return client.disconnect(); + }) + ); - return nodes.map(({ docker }) => docker); + return nodes.map(({ docker }) => docker); } -function totalNodes(slots: ClusterSlotsReply) { - let total = slots.length; - for (const slot of slots) { - total += slot.replicas.length; - } +// TODO: type ClusterSlotsReply +function totalNodes(slots: any) { + let total = slots.length; + for (const slot of slots) { + total += slot.replicas.length; + } - return total; + return total; } const RUNNING_CLUSTERS = new Map, ReturnType>(); export function spawnRedisCluster(dockersConfig: RedisClusterDockersConfig, serverArguments: Array): Promise> { - const runningCluster = RUNNING_CLUSTERS.get(serverArguments); - if (runningCluster) { - return runningCluster; - } - - const dockersPromise = spawnRedisClusterDockers(dockersConfig, serverArguments); - RUNNING_CLUSTERS.set(serverArguments, dockersPromise); - return dockersPromise; + const runningCluster = RUNNING_CLUSTERS.get(serverArguments); + if (runningCluster) { + return runningCluster; + } + + const dockersPromise = spawnRedisClusterDockers(dockersConfig, serverArguments); + RUNNING_CLUSTERS.set(serverArguments, dockersPromise); + return dockersPromise; } after(() => { - return Promise.all( - [...RUNNING_CLUSTERS.values()].map(async dockersPromise => { - return Promise.all( - (await dockersPromise).map(({ dockerId }) => dockerRemove(dockerId)) - ); - }) - ); + return Promise.all( + [...RUNNING_CLUSTERS.values()].map(async dockersPromise => { + return Promise.all( + (await dockersPromise).map(({ dockerId }) => dockerRemove(dockerId)) + ); + }) + ); }); diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index b9195c5717a..7a783792ecd 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -1,226 +1,269 @@ -import { RedisModules, RedisFunctions, 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 { RedisSocketCommonOptions } from '@redis/client/lib/client/socket'; +// import { RedisModules, RedisFunctions, 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 { RedisSocketCommonOptions } from '@redis/client/lib/client/socket'; +import { + RedisModules, + RedisFunctions, + RedisScripts, + RespVersions, + createClient, + RedisClientOptions, + RedisClientType, + createCluster, + RedisClusterOptions, + RedisClusterType +} from '@redis/client'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; interface TestUtilsConfig { - dockerImageName: string; - dockerImageVersionArgument: string; - defaultDockerVersion?: string; + dockerImageName: string; + dockerImageVersionArgument: string; + defaultDockerVersion?: string; } interface CommonTestOptions { - minimumDockerVersion?: Array; + minimumDockerVersion?: Array; } interface ClientTestOptions< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions > extends CommonTestOptions { - serverArguments: Array; - clientOptions?: Partial, 'socket'> & { socket: RedisSocketCommonOptions }>; - disableClientSetup?: boolean; + serverArguments: Array; + clientOptions?: Partial>; + disableClientSetup?: boolean; } interface ClusterTestOptions< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions > extends CommonTestOptions { - serverArguments: Array; - clusterConfiguration?: Partial>; - numberOfMasters?: number; - numberOfReplicas?: number; + serverArguments: Array; + clusterConfiguration?: Partial>; + numberOfMasters?: number; + numberOfReplicas?: number; +} + +interface AllTestOptions< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> { + client: ClientTestOptions; + cluster: ClusterTestOptions; } interface Version { - string: string; - numbers: Array; + string: string; + numbers: Array; } export default class TestUtils { - static #parseVersionNumber(version: string): Array { - if (version === 'latest' || version === 'edge') return [Infinity]; - - const dashIndex = version.indexOf('-'); - return (dashIndex === -1 ? version : version.substring(0, dashIndex)) - .split('.') - .map(x => { - const value = Number(x); - if (Number.isNaN(value)) { - throw new TypeError(`${version} is not a valid redis version`); - } - - return value; - }); - } + static #parseVersionNumber(version: string): Array { + if (version === 'latest' || version === 'edge') return [Infinity]; - static #getVersion(argumentName: string, defaultVersion = 'latest'): Version { - return yargs(hideBin(process.argv)) - .option(argumentName, { - type: 'string', - default: defaultVersion - }) - .coerce(argumentName, (version: string) => { - return { - string: version, - numbers: TestUtils.#parseVersionNumber(version) - }; - }) - .demandOption(argumentName) - .parseSync()[argumentName]; - } + const dashIndex = version.indexOf('-'); + return (dashIndex === -1 ? version : version.substring(0, dashIndex)) + .split('.') + .map(x => { + const value = Number(x); + if (Number.isNaN(value)) { + throw new TypeError(`${version} is not a valid redis version`); + } - readonly #VERSION_NUMBERS: Array; - readonly #DOCKER_IMAGE: RedisServerDockerConfig; + return value; + }); + } - constructor(config: TestUtilsConfig) { - const { string, numbers } = TestUtils.#getVersion(config.dockerImageVersionArgument, config.defaultDockerVersion); - this.#VERSION_NUMBERS = numbers; - this.#DOCKER_IMAGE = { - image: config.dockerImageName, - version: string + static #getVersion(argumentName: string, defaultVersion = 'latest'): Version { + return yargs(hideBin(process.argv)) + .option(argumentName, { + type: 'string', + default: defaultVersion + }) + .coerce(argumentName, (version: string) => { + return { + string: version, + numbers: TestUtils.#parseVersionNumber(version) }; - } + }) + .demandOption(argumentName) + .parseSync()[argumentName]; + } - isVersionGreaterThan(minimumVersion: Array | undefined): boolean { - if (minimumVersion === undefined) return true; + readonly #VERSION_NUMBERS: Array; + readonly #DOCKER_IMAGE: RedisServerDockerConfig; - const lastIndex = Math.min(this.#VERSION_NUMBERS.length, minimumVersion.length) - 1; - for (let i = 0; i < lastIndex; i++) { - if (this.#VERSION_NUMBERS[i] > minimumVersion[i]) { - return true; - } else if (minimumVersion[i] > this.#VERSION_NUMBERS[i]) { - return false; - } - } + constructor(config: TestUtilsConfig) { + const { string, numbers } = TestUtils.#getVersion(config.dockerImageVersionArgument, config.defaultDockerVersion); + this.#VERSION_NUMBERS = numbers; + this.#DOCKER_IMAGE = { + image: config.dockerImageName, + version: string + }; + } + + isVersionGreaterThan(minimumVersion: Array | undefined): boolean { + if (minimumVersion === undefined) return true; - return this.#VERSION_NUMBERS[lastIndex] >= minimumVersion[lastIndex]; + const lastIndex = Math.min(this.#VERSION_NUMBERS.length, minimumVersion.length) - 1; + for (let i = 0; i < lastIndex; i++) { + if (this.#VERSION_NUMBERS[i] > minimumVersion[i]) { + return true; + } else if (minimumVersion[i] > this.#VERSION_NUMBERS[i]) { + return false; + } } - isVersionGreaterThanHook(minimumVersion: Array | undefined): void { - const isVersionGreaterThan = this.isVersionGreaterThan.bind(this); - before(function () { - if (!isVersionGreaterThan(minimumVersion)) { - return this.skip(); - } - }); + return this.#VERSION_NUMBERS[lastIndex] >= minimumVersion[lastIndex]; + } + + isVersionGreaterThanHook(minimumVersion: Array | undefined): void { + const isVersionGreaterThan = this.isVersionGreaterThan.bind(this); + before(function () { + if (!isVersionGreaterThan(minimumVersion)) { + return this.skip(); + } + }); + } + + testWithClient< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >( + title: string, + fn: (client: RedisClientType) => unknown, + options: ClientTestOptions + ): void { + let dockerPromise: ReturnType; + if (this.isVersionGreaterThan(options.minimumDockerVersion)) { + const dockerImage = this.#DOCKER_IMAGE; + before(function () { + this.timeout(30000); + + dockerPromise = spawnRedisServer(dockerImage, options.serverArguments); + return dockerPromise; + }); } - testWithClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >( - title: string, - fn: (client: RedisClientType) => unknown, - options: ClientTestOptions - ): void { - let dockerPromise: ReturnType; - if (this.isVersionGreaterThan(options.minimumDockerVersion)) { - const dockerImage = this.#DOCKER_IMAGE; - before(function () { - this.timeout(30000); - - dockerPromise = spawnRedisServer(dockerImage, options.serverArguments); - return dockerPromise; - }); + it(title, async function () { + if (!dockerPromise) return this.skip(); + + const client = createClient({ + ...options?.clientOptions, + socket: { + ...options?.clientOptions?.socket, + // TODO + // @ts-ignore + port: (await dockerPromise).port } + }); - it(title, async function() { - if (!dockerPromise) return this.skip(); + if (options.disableClientSetup) { + return fn(client); + } - const client = RedisClient.create({ - ...options?.clientOptions, - socket: { - ...options?.clientOptions?.socket, - port: (await dockerPromise).port - } - }); + await client.connect(); - if (options.disableClientSetup) { - return fn(client); - } + try { + await client.flushAll(); + await fn(client); + } finally { + if (client.isOpen) { + await client.flushAll(); + await client.disconnect(); + } + } + }); + } - await client.connect(); + static async #clusterFlushAll< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >(cluster: RedisClusterType): Promise { + return Promise.all( + cluster.masters.map(async ({ client }) => { + if (client) { + await (await client).flushAll(); + } + }) + ); + } - try { - await client.flushAll(); - await fn(client); - } finally { - if (client.isOpen) { - await client.flushAll(); - await client.disconnect(); - } - } - }); - } + testWithCluster< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >( + title: string, + fn: (cluster: RedisClusterType) => unknown, + options: ClusterTestOptions + ): void { + let dockersPromise: ReturnType; + if (this.isVersionGreaterThan(options.minimumDockerVersion)) { + const dockerImage = this.#DOCKER_IMAGE; + before(function () { + this.timeout(30000); - static async #clusterFlushAll< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(cluster: RedisClusterType): Promise { - return Promise.all( - cluster.masters.map(async ({ client }) => { - if (client) { - await (await client).flushAll(); - } - }) - ); + dockersPromise = spawnRedisCluster({ + ...dockerImage, + numberOfMasters: options?.numberOfMasters, + numberOfReplicas: options?.numberOfReplicas + }, options.serverArguments); + return dockersPromise; + }); } - testWithCluster< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >( - title: string, - fn: (cluster: RedisClusterType) => unknown, - options: ClusterTestOptions - ): void { - let dockersPromise: ReturnType; - if (this.isVersionGreaterThan(options.minimumDockerVersion)) { - const dockerImage = this.#DOCKER_IMAGE; - before(function () { - this.timeout(30000); - - dockersPromise = spawnRedisCluster({ - ...dockerImage, - numberOfMasters: options?.numberOfMasters, - numberOfReplicas: options?.numberOfReplicas - }, options.serverArguments); - return dockersPromise; - }); - } + it(title, async function () { + if (!dockersPromise) return this.skip(); - it(title, async function () { - if (!dockersPromise) return this.skip(); - - const dockers = await dockersPromise, - cluster = RedisCluster.create({ - rootNodes: dockers.map(({ port }) => ({ - socket: { - port - } - })), - minimizeConnections: true, - ...options.clusterConfiguration - }); - - await cluster.connect(); - - try { - await TestUtils.#clusterFlushAll(cluster); - await fn(cluster); - } finally { - await TestUtils.#clusterFlushAll(cluster); - await cluster.disconnect(); + const dockers = await dockersPromise, + cluster = createCluster({ + rootNodes: dockers.map(({ port }) => ({ + socket: { + port } + })), + minimizeConnections: true, + ...options.clusterConfiguration }); - } + + await cluster.connect(); + + try { + await TestUtils.#clusterFlushAll(cluster); + await fn(cluster); + } finally { + await TestUtils.#clusterFlushAll(cluster); + await cluster.disconnect(); + } + }); + } + + testAll< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >( + title: string, + fn: (client: RedisClientType | RedisClusterType) => unknown, + options: AllTestOptions + ) { + this.testWithClient(`client.${title}`, fn, options.client); + this.testWithCluster(`cluster.${title}`, fn, options.cluster); + } } diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index c82ca367301..a6e55abe0d5 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -12,13 +12,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "^18.14.1", - "@types/yargs": "^17.0.22", + "@types/node": "^18.15.10", + "@types/yargs": "^17.0.24", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typescript": "^4.9.5", + "typescript": "^5.0.2", "yargs": "^17.7.1" } } diff --git a/packages/time-series/lib/commands/QUERYINDEX.ts b/packages/time-series/lib/commands/QUERYINDEX.ts index 46eb5647040..b2285789185 100644 --- a/packages/time-series/lib/commands/QUERYINDEX.ts +++ b/packages/time-series/lib/commands/QUERYINDEX.ts @@ -1,11 +1,11 @@ import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { Filter } from '.'; export const IS_READ_ONLY = true; export function transformArguments(filter: Filter): RedisCommandArguments { - return pushVerdictArguments(['TS.QUERYINDEX'], filter); + return pushVariadicArguments(['TS.QUERYINDEX'], filter); } export declare function transformReply(): Array; diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index 19cd075ba49..8e36e21082b 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -20,7 +20,7 @@ import * as MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; import * as MREVRANGE from './MREVRANGE'; import * as MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export default { ADD, @@ -364,7 +364,7 @@ export type Filter = string | Array; export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array): RedisCommandArguments { args.push('FILTER'); - return pushVerdictArguments(args, filter); + return pushVariadicArguments(args, filter); } export interface MRangeOptions extends RangeOptions { @@ -390,7 +390,7 @@ export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabe args.push('WITHLABELS'); } else { args.push('SELECTED_LABELS'); - args = pushVerdictArguments(args, selectedLabels); + args = pushVariadicArguments(args, selectedLabels); } return args; diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 1d6a184e5fc..cea7180d1e5 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -18,12 +18,12 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.14.1", + "@types/node": "^18.15.10", "nyc": "^15.1.0", - "release-it": "^15.6.0", + "release-it": "^15.9.3", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.25", - "typescript": "^4.9.5" + "typedoc": "^0.23.28", + "typescript": "^5.0.2" } } diff --git a/req-res-parser/a.sh b/req-res-parser/a.sh new file mode 100644 index 00000000000..684505d1878 --- /dev/null +++ b/req-res-parser/a.sh @@ -0,0 +1,7 @@ +single="--single unit/type/incr --single unit/type/string --single unit/type/stream-cgroups --single unit/type/stream" + +single="--single unit/type/set" && +sudo ./runtest --log-req-res --force-resp3 --dont-clean $single && +cat ./tests/tmp/*/stdout.reqres > resp3.reqres && +sudo ./runtest --log-req-res --dont-clean $single && +cat ./tests/tmp/*/stdout.reqres > resp2.reqres \ No newline at end of file diff --git a/req-res-parser/req-res-parser.mjs b/req-res-parser/req-res-parser.mjs new file mode 100644 index 00000000000..43f8374d29e --- /dev/null +++ b/req-res-parser/req-res-parser.mjs @@ -0,0 +1,1018 @@ +import { readFile } from 'node:fs/promises'; +import { deepEqual } from 'node:assert/strict'; + +// https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md +export const TYPES = { + NULL: 95, // _ + BOOLEAN: 35, // # + NUMBER: 58, // : + BIG_NUMBER: 40, // ( + DOUBLE: 44, // , + SIMPLE_STRING: 43, // + + BLOB_STRING: 36, // $ + VERBATIM_STRING: 61, // = + SIMPLE_ERROR: 45, // - + BLOB_ERROR: 33, // ! + ARRAY: 42, // * + SET: 126, // ~ + MAP: 37, // % + ATTRIBUTE: 124, // | + PUSH: 62 // > +}; + +const ASCII = { + '\r': 13, + 't': 116, + '-': 45, + '0': 48, + '.': 46, + 'i': 105, + 'n': 110 +}; + +// this was written with performance in mind, so it's not very readable... sorry :( + +export class Decoder { + #onReply; + #onPush; + #getFlags; + + constructor({ + onReply, + onPush, + getFlags + }) { + this.#onReply = onReply; + this.#onPush = onPush; + this.#getFlags = getFlags; + } + + #cursor = 0; + + #continue; + + reset() { + this.#cursor = 0; + this.#continue = undefined; + } + + write(chunk) { + if (this.#cursor >= chunk.length || this.#continue?.(chunk)) { + this.#cursor -= chunk.length; + return; + } + + do { + const flags = this.#getFlags(), + type = chunk[this.#cursor]; + + if (++this.#cursor === chunk.length) { + this.#continue = this.#continueDecodeTypeValue.bind(this, type, flags); + break; + } + + this.#decodeTypeValue(type, flags, chunk); + } while (this.#cursor < chunk.length); + this.#cursor -= chunk.length; + } + + #continueDecodeTypeValue(type, flags, chunk) { + this.#continue = undefined; + this.#decodeTypeValue(type, flags, chunk); + return this.#cursor >= chunk.length; + } + + #decodeTypeValue(type, flags, chunk) { + if (type === TYPES.PUSH) { + this.#handleDecodedValue( + this.#onPush, + this.#decodeArray(flags, chunk) + ); + return; + } + + this.#handleDecodedValue( + this.#onReply, + this.#decodeReplyValue(type, flags, chunk) + ); + } + + #decodeReplyValue(type, flags, chunk) { + switch (type) { + case TYPES.NULL: + return this.#decodeNull(); + + case TYPES.BOOLEAN: + return this.#decodeBoolean(chunk); + + case TYPES.NUMBER: + return this.#decodeNumber(chunk); + + case TYPES.BIG_NUMBER: + return this.#decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk); + + case TYPES.DOUBLE: + return this.#decodeDouble(flags[TYPES.DOUBLE], chunk); + + case TYPES.SIMPLE_STRING: + return this.#decodeSimpleString(flags[TYPES.SIMPLE_STRING], chunk); + + case TYPES.BLOB_STRING: + return this.#decodeBlobString(flags[TYPES.BLOB_STRING], chunk); + + case TYPES.VERBATIM_STRING: + return this.#decodeBlobString(flags[TYPES.BLOB_STRING], chunk); + + case TYPES.SIMPLE_ERROR: + return this.#decodeSimpleError(chunk); + + case TYPES.BLOB_ERROR: + return this.#decodeBlobError(chunk); + + case TYPES.ARRAY: + return this.#decodeArray(flags, chunk); + + case TYPES.SET: + return this.#decodeSet(flags, chunk); + + case TYPES.MAP: + return this.#decodeMap(flags, chunk); + + case TYPES.ATTRIBUTE: + throw new Error('TODO: attribute'); + } + } + + #handleDecodedValue(cb, value) { + if (typeof value === 'function') { + this.#continue = this.#continueDecodeValue.bind(this, cb, value); + return true; + } + + cb(value); + } + + #continueDecodeValue(cb, valueCb, chunk) { + this.#continue = undefined; + return this.#handleDecodedValue(cb, valueCb(chunk), chunk) || + this.#cursor >= chunk.length; + } + + #decodeNull() { + this.#cursor += 2; // skip \r\n + return null; + } + + #decodeBoolean(chunk) { + const boolean = chunk[this.#cursor] === ASCII['t']; + this.#cursor += 3; // skip {t | f}\r\n + return boolean; + } + + #decodeNumber(chunk) { + const isNegative = chunk[this.#cursor] === ASCII['-']; + if (isNegative && ++this.#cursor === chunk.length) { + return this.#continueDecodeNumber.bind( + this, + isNegative, + this.#decodeUnsingedNumber.bind(this, 0) + ); + } + + const number = this.#decodeUnsingedNumber(0, chunk); + return typeof number === 'function' ? + this.#continueDecodeNumber.bind(this, isNegative, number) : + isNegative ? -number : number; + } + + #continueDecodeNumber(isNegative, numberCb, chunk) { + const number = numberCb(chunk); + return typeof number === 'function' ? + this.#continueDecodeNumber.bind(this, isNegative, number) : + isNegative ? -number : number; + } + + #decodeUnsingedNumber(number, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this.#cursor = cursor + 2; // skip \r\n + return number; + } + number = number * 10 + byte - ASCII['0']; + } while (++cursor < chunk.length); + + this.#cursor = cursor; + return this.#decodeUnsingedNumber.bind(this, number); + } + + #decodeBigNumber(flag, chunk) { + if (flag === String) { + return this.#decodeSimpleString(String, chunk); + } + + const isNegative = chunk[this.#cursor] === ASCII['-']; + if (isNegative && ++this.#cursor === chunk.length) { + return this.#continueDecodeBigNumber.bind( + this, + isNegative, + this.#decodeUnsingedBigNumber.bind(this, 0n) + ); + } + + const bigNumber = this.#decodeUnsingedBigNumber(0n, chunk); + return typeof bigNumber === 'function' ? + this.#continueDecodeNumber.bind(this, isNegative, bigNumber) : + isNegative ? -bigNumber : bigNumber; + } + + #continueDecodeBigNumber(isNegative, bigNumberCb, chunk) { + const bigNumber = bigNumberCb(chunk); + return typeof bigNumber === 'function' ? + this.#continueDecodeBigNumber.bind(this, isNegative, bigNumber) : + isNegative ? -bigNumber : bigNumber; + } + + #decodeUnsingedBigNumber(bigNumber, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this.#cursor = cursor + 2; // skip \r\n + return bigNumber; + } + bigNumber = bigNumber * 10n + BigInt(byte - ASCII['0']); + } while (++cursor < chunk.length); + + this.#cursor = cursor; + return this.#decodeUnsingedBigNumber.bind(this, bigNumber); + } + + #decodeDouble(flag, chunk) { + if (flag === String) { + return this.#decodeSimpleString(String, chunk); + } + + switch (chunk[this.#cursor]) { + case ASCII['n']: + this.#cursor += 5; // skip nan\r\n + return NaN; + + case ASCII['-']: + return ++this.#cursor === chunk.length ? + this.#decodeDoubleInteger.bind(this, true, 0, chunk) : + this.#decodeDoubleInteger(true, 0, chunk); + + default: + return this.#decodeDoubleInteger(false, 0, chunk); + } + } + + #decodeDoubleInteger(isNegative, integer, chunk) { + if (chunk[this.#cursor] === ASCII['i']) { + this.#cursor += 5; // skip inf\r\n + return isNegative ? -Infinity : Infinity; + } + + return this.#continueDecodeDoubleInteger(isNegative, integer, chunk); + } + + #continueDecodeDoubleInteger(isNegative, integer, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + switch (byte) { + case ASCII['.']: + this.#cursor = ++cursor; + return cursor < chunk.length ? + this.#decodeDoubleDecimal(isNegative, 0, integer, chunk) : + this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer); + + case ASCII['\r']: + this.#cursor = cursor + 2; // skip \r\n + return isNegative ? -integer : integer; + + default: + integer = integer * 10 + byte - ASCII['0']; + } + } while (++cursor < chunk.length); + + this.#cursor = cursor; + return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer); + } + + // Precalculated multipliers for decimal points to improve performance + // "A Number only keeps about 17 decimal places of precision" + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + static #DOUBLE_DECIMAL_MULTIPLIERS = [ + 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, + 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, + 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 + ]; + + #decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII['\r']) { + this.#cursor = cursor + 2; // skip \r\n + return isNegative ? -double : double; + } + + if (decimalIndex < Decoder.#DOUBLE_DECIMAL_MULTIPLIERS.length) { + double += (byte - ASCII['0']) * Decoder.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; + } + } while (++cursor < chunk.length); + + this.#cursor = cursor; + return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); + } + + #findCRLF(chunk, cursor) { + while (chunk[cursor] !== ASCII['\r']) { + if (++cursor === chunk.length) { + this.#cursor = chunk.length; + return -1; + } + } + + this.#cursor = cursor + 2; // skip \r\n + return cursor; + } + + #decodeSimpleString(flag, chunk) { + const start = this.#cursor, + crlfIndex = this.#findCRLF(chunk, start); + if (crlfIndex === -1) { + return this.#continueDecodeSimpleString.bind( + this, + [chunk.subarray(start)], + flag + ); + } + + const slice = chunk.subarray(start, crlfIndex); + return flag === Buffer ? + slice : + slice.toString(); + } + + #continueDecodeSimpleString(chunks, flag, chunk) { + const start = this.#cursor, + crlfIndex = this.#findCRLF(chunk, start); + if (crlfIndex === -1) { + chunks.push(chunk.subarray(start)); + return this.#continueDecodeSimpleString.bind(this, chunks, flag); + } + + chunks.push(chunk.subarray(start, crlfIndex)); + return flag === Buffer ? + Buffer.concat(chunks) : + chunks.join(''); + } + + #decodeBlobString(flag, chunk) { + // RESP 2 bulk string null + // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings + if (chunk[this.#cursor] === ASCII['-']) { + this.#cursor += 4; // skip -1\r\n + return null; + } + + const length = this.#decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this.#continueDecodeBlobStringLength.bind(this, length, flag); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length, flag); + } + + return this.#decodeBlobStringWithLength(length, flag, chunk); + } + + #continueDecodeBlobStringLength(lengthCb, flag, chunk) { + const length = lengthCb(chunk); + if (typeof length === 'function') { + return this.#continueDecodeBlobStringLength.bind(this, length, flag); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length, flag); + } + + return this.#decodeBlobStringWithLength(length, flag, chunk); + } + + #decodeBlobStringWithLength(length, flag, chunk) { + const end = this.#cursor + length; + if (end >= chunk.length) { + const slice = chunk.subarray(this.#cursor); + this.#cursor = chunk.length; + return this.#continueDecodeBlobStringWithLength.bind( + this, + length - slice.length, + [slice], + flag + ); + } + + const slice = chunk.subarray(this.#cursor, end); + this.#cursor = end + 2; // skip ${string}\r\n + return flag === Buffer ? + slice : + slice.toString(); + } + + #continueDecodeBlobStringWithLength(length, chunks, flag, chunk) { + const end = this.#cursor + length; + if (end >= chunk.length) { + const slice = chunk.slice(this.#cursor); + chunks.push(slice); + this.#cursor = chunk.length; + return this.#continueDecodeBlobStringWithLength.bind( + this, + length - slice.length, + chunks, + flag + ); + } + + chunks.push(chunk.subarray(this.#cursor, end)); + this.#cursor = end + 2; // skip ${string}\r\n + return flag === Buffer ? + Buffer.concat(chunks) : + chunks.join(''); + } + + #decodeSimpleError(chunk) { + const string = this.#decodeSimpleString(String, chunk); + return typeof string === 'function' ? + this.#continueDecodeSimpleError.bind(this, string) : + new Error(string); // TODO use custom error + } + + #continueDecodeSimpleError(stringCb, chunk) { + const string = stringCb(chunk); + return typeof string === 'function' ? + this.#continueDecodeSimpleError.bind(this, string) : + new Error(string); // TODO use custom error + } + + #decodeBlobError(chunk) { + const string = this.#decodeBlobString(String, chunk); + return typeof string === 'function' ? + this.#continueDecodeBlobError.bind(this, string) : + new Error(string); // TODO use custom error + } + + #continueDecodeBlobError(stringCb, chunk) { + const string = stringCb(chunk); + return typeof string === 'function' ? + this.#continueDecodeBlobError.bind(this, string) : + new Error(string); // TODO use custom error + } + + #decodeNestedType(flags, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? + this.#decodeReplyValue.bind(this, type, flags) : + this.#decodeReplyValue(type, flags, chunk); + } + + #decodeArray(flags, chunk) { + // RESP 2 null + // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays + if (chunk[this.#cursor] === ASCII['-']) { + this.#cursor += 4; // skip -1\r\n + return null; + } + + return this.#decodeArrayWithLength( + this.#decodeUnsingedNumber(0, chunk), + flags, + chunk + ); + } + + #decodeArrayWithLength(length, flags, chunk) { + return typeof length === 'function' ? + this.#continueDecodeArrayLength.bind(this, length, flags) : + this.#decodeArrayItems( + new Array(length), + 0, + flags, + chunk + ); + } + + #continueDecodeArrayLength(lengthCb, flags, chunk) { + return this.#decodeArrayWithLength( + lengthCb(chunk), + flags, + chunk + ); + } + + #decodeArrayItems(array, filled, flags, chunk) { + for (let i = filled; i < array.length; i++) { + if (this.#cursor >= chunk.length) { + return this.#decodeArrayItems.bind( + this, + array, + i, + flags + ); + } + + const item = this.#decodeNestedType(flags, chunk); + if (typeof item === 'function') { + return this.#continueDecodeArrayItems.bind( + this, + array, + i, + item, + flags + ); + } + + array[i] = item; + } + + return array; + } + + #continueDecodeArrayItems(array, filled, itemCb, flags, chunk) { + const item = itemCb(chunk); + if (typeof item === 'function') { + return this.#continueDecodeArrayItems.bind( + this, + array, + filled, + item, + flags + ); + } + + array[filled++] = item; + + return this.#decodeArrayItems(array, filled, flags, chunk); + } + + #decodeSet(flags, chunk) { + const length = this.#decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this.#continueDecodeSetLength.bind(this, length, flags); + } + + return this.#decodeSetItems( + length, + flags, + chunk + ); + } + + #continueDecodeSetLength(lengthCb, flags, chunk) { + const length = lengthCb(chunk); + return typeof length === 'function' ? + this.#continueDecodeSetLength.bind(this, length, flags) : + this.#decodeSetItems(length, flags, chunk); + } + + #decodeSetItems(length, flags, chunk) { + return flags[TYPES.SET] === Set ? + this.#decodeSetAsSet( + new Set(), + length, + flags, + chunk + ) : + this.#decodeArrayItems( + new Array(length), + 0, + flags, + chunk + ); + } + + #decodeSetAsSet(set, remaining, flags, chunk) { + // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeSetAsSet.bind( + this, + set, + remaining, + flags + ); + } + + const item = this.#decodeNestedType(flags, chunk); + if (typeof item === 'function') { + return this.#continueDecodeSetAsSet.bind( + this, + set, + remaining, + item, + flags + ); + } + + set.add(item); + --remaining; + } + + return set; + } + + #continueDecodeSetAsSet(set, remaining, itemCb, flags, chunk) { + const item = itemCb(chunk); + if (typeof item === 'function') { + return this.#continueDecodeSetAsSet.bind( + this, + set, + remaining, + item, + flags + ); + } + + set.add(item); + + return this.#decodeSetAsSet(set, remaining - 1, flags, chunk); + } + + #decodeMap(flags, chunk) { + const length = this.#decodeUnsingedNumber(0, chunk); + if (typeof length === 'function') { + return this.#continueDecodeMapLength.bind(this, length, flags); + } + + return this.#decodeMapItems( + length, + flags, + chunk + ); + } + + #continueDecodeMapLength(lengthCb, flags, chunk) { + const length = lengthCb(chunk); + return typeof length === 'function' ? + this.#continueDecodeMapLength.bind(this, length, flags) : + this.#decodeMapItems(length, flags, chunk); + } + + #decodeMapItems(length, flags, chunk) { + switch (flags[TYPES.MAP]) { + case Map: + return this.#decodeMapAsMap( + new Map(), + length, + flags, + chunk + ); + + case Array: + return this.#decodeArrayItems( + new Array(length * 2), + 0, + flags, + chunk + ); + + default: + return this.#decodeMapAsObject( + Object.create(null), + length, + flags, + chunk + ); + } + } + + #decodeMapAsMap(map, remaining, flags, chunk) { + // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsMap.bind( + this, + map, + remaining, + flags + ); + } + + const key = this.#decodeMapKey(flags, chunk); + if (typeof key === 'function') { + return this.#continueDecodeMapKey.bind( + this, + map, + remaining, + key, + flags + ); + } + + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind( + this, + map, + remaining, + key, + this.#decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this.#decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + --remaining; + } + + return map; + } + + #decodeMapKey(flags, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? + this.#decodeMapKeyValue.bind(this, type, flags) : + this.#decodeMapKeyValue(type, flags, chunk); + } + + #decodeMapKeyValue(type, flags, chunk) { + switch (type) { + // decode simple string map key as string (and not as buffer) + case TYPES.SIMPLE_STRING: + return this.#decodeSimpleString(String, chunk); + + // decode blob string map key as string (and not as buffer) + case TYPES.BLOB_STRING: + return this.#decodeBlobString(String, chunk); + + default: + return this.#decodeReplyValue(type, flags, chunk); + } + } + + #continueDecodeMapKey(map, remaining, keyCb, flags, chunk) { + const key = keyCb(chunk); + if (typeof key === 'function') { + return this.#continueDecodeMapKey.bind( + this, + map, + remaining, + key, + flags + ); + } + + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind( + this, + map, + remaining, + key, + this.#decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this.#decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); + } + + #continueDecodeMapValue(map, remaining, key, valueCb, flags, chunk) { + const value = valueCb(chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapValue.bind( + this, + map, + remaining, + key, + value, + flags + ); + } + + map.set(key, value); + + return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); + } + + #decodeMapAsObject(object, remaining, flags, chunk) { + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsObject.bind( + this, + object, + remaining, + flags + ); + } + + const key = this.#decodeMapKey(flags, chunk); + if (typeof key === 'function') { + return this.#continueDecodeMapAsObjectKey.bind( + this, + object, + remaining, + key, + flags + ); + } + + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + this.#decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this.#decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + --remaining; + } + + return object; + } + + #continueDecodeMapAsObjectKey(object, remaining, keyCb, flags, chunk) { + const key = keyCb(chunk); + if (typeof key === 'function') { + return this.#continueDecodeMapAsObjectKey.bind( + this, + object, + remaining, + key, + flags + ); + } + + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + this.#decodeNestedType.bind(this, flags), + flags + ); + } + + const value = this.#decodeNestedType(flags, chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + + return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); + } + + #continueDecodeMapAsObjectValue(object, remaining, key, valueCb, flags, chunk) { + const value = valueCb(chunk); + if (typeof value === 'function') { + return this.#continueDecodeMapAsObjectValue.bind( + this, + object, + remaining, + key, + value, + flags + ); + } + + object[key] = value; + + return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); + } +} + +async function parseFile(path) { + const log = await readFile(path); + + let i = 0; + + function readLine() { + const start = i; + while (log[i++] !== 10) {} + return log.subarray(start, i); + } + + function readArgs() { + const args = []; + while (true) { + readLine(); // skip size line + const buffer = readLine(); + const line = buffer.subarray(0, buffer.length - 2).toString(); + if (line === '__argv_end__') { + return args; + } else { + args.push(line); + } + } + } + + function readReply() { + let reply; + const decoder = new Decoder({ + onReply(r) { + reply = r; + }, + onPush(p) { + console.log('PUSH', p); + }, + getFlags() { + return {}; + } + }); + + const network = []; + while (reply === undefined) { + const toWrite = readLine(); + network.push(toWrite); + decoder.write(toWrite); + } + + return { + reply, + network: Buffer.concat(network) + }; + } + + const reqres = []; + while (i < log.length) { + const item = { + args: readArgs(), + ...readReply() + }; + reqres.push(item); + } + + return reqres; +} + +const [resp3, resp2] = await Promise.all([ + parseFile('/home/leibale/Workspace/redis/resp3.reqres'), + parseFile('/home/leibale/Workspace/redis/resp2.reqres') +]); + +console.log(resp2.length, resp3.length); +if (resp2.length !== resp3.length) throw 'invalid'; + +for (let i = 0; i < resp3.length; i++) { + try { + deepEqual( + resp3[i].reply, + resp2[i].reply + ); + } catch (err) { + console.log( + resp3[i], + '!=', + resp2[i] + ); + } +} From 40cfb94ca29c3b48b17dcab26860a7cdd08a2b0d Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 24 Apr 2023 12:11:45 -0400 Subject: [PATCH 008/325] WIP --- md/RESP2-to-RESP3.md | 1 - md/RESP3.md | 4 +- md/Redis-todo.md | 2 +- md/v5-new-features.md | 8 + packages/old/RESP3-old/decoder.ts | 423 ------------------ packages/old/RESP3-old/encoder.ts | 0 .../old/RESP3-old/nested-decoders/abstract.ts | 6 - .../RESP3-old/nested-decoders/map-to-array.ts | 28 -- .../old/RESP3-old/nested-decoders/to-array.ts | 20 - .../old/RESP3-old/nested-decoders/to-map.ts | 28 -- .../RESP3-old/nested-decoders/to-object.ts | 28 -- .../old/RESP3-old/nested-decoders/to-set.ts | 20 - packages/old/RESP3-old/types.ts | 101 ----- 13 files changed, 10 insertions(+), 659 deletions(-) delete mode 100644 md/RESP2-to-RESP3.md delete mode 100644 packages/old/RESP3-old/decoder.ts delete mode 100644 packages/old/RESP3-old/encoder.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/abstract.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/map-to-array.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/to-array.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/to-map.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/to-object.ts delete mode 100644 packages/old/RESP3-old/nested-decoders/to-set.ts delete mode 100644 packages/old/RESP3-old/types.ts diff --git a/md/RESP2-to-RESP3.md b/md/RESP2-to-RESP3.md deleted file mode 100644 index 6f34ae8f41f..00000000000 --- a/md/RESP2-to-RESP3.md +++ /dev/null @@ -1 +0,0 @@ -https://docs.google.com/document/d/1Bg4jxEYiWnbCl4Oa2GCk5xaWde7HLa6GcNGg1sFwDAY/edit# diff --git a/md/RESP3.md b/md/RESP3.md index 2c684be2b14..ed45ac8c87f 100644 --- a/md/RESP3.md +++ b/md/RESP3.md @@ -7,7 +7,7 @@ - Double (`,`) => `number | string` - Simple String (`+`) => `string | Buffer` - Blob String (`$`) => `string | Buffer` -- Verbatim String (`=`) => `string | Buffer | VerbatimString` +- Verbatim String (`=`) => `string | Buffer | VerbatimString` (TODO: `VerbatimString` typedoc link) - Simple Error (`-`) => `ErrorReply` - Blob Error (`!`) => `ErrorReply` - Array (`*`) => `Array` @@ -17,8 +17,6 @@ > NOTE: the first type is the default type -## Verbatim String - ## Map keys and Set members When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. diff --git a/md/Redis-todo.md b/md/Redis-todo.md index eab52a4ce15..ab10ed249e4 100644 --- a/md/Redis-todo.md +++ b/md/Redis-todo.md @@ -9,4 +9,4 @@ - `HINCRBYFLOAT` `Number` -> `Boolean`: -- `HSETNX` (deprecated) \ No newline at end of file +- `HSETNX` (deprecated) diff --git a/md/v5-new-features.md b/md/v5-new-features.md index b9ac5860833..56dd12b49c5 100644 --- a/md/v5-new-features.md +++ b/md/v5-new-features.md @@ -1,6 +1,14 @@ # RESP3 Support ```javascript +const client = createClient({ + RESP: 3 +}); + +client.on('error', err => console.error(err)); + +await client.connect(); + client.hGetAll('key'); // Record client.withFlags({ diff --git a/packages/old/RESP3-old/decoder.ts b/packages/old/RESP3-old/decoder.ts deleted file mode 100644 index a6b3a78248f..00000000000 --- a/packages/old/RESP3-old/decoder.ts +++ /dev/null @@ -1,423 +0,0 @@ -// RESP3 specification -// https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md - -import BufferComposer from '../RESP/composers/buffer'; -import { Composer } from '../RESP/composers/interface'; -import StringComposer from '../RESP/composers/string'; -import { Flags, Reply, ReplyTypes, TransformReplyType } from './types'; -import { NestedDecoderInterface } from './nested-decoders/abstract'; - -const ASCII = { - '\r': 13, - 't': 116, - '0': 48, - '-': 45, - '.': 46, - '?': 63, - 'n': 110, - 'i': 105 -}; - -export const RESP_TYPES = { - NULL: 95, // _ - BOOLEAN: 35, // # - NUMBER: 58, // : - BIG_NUMBER: 40, // ( - DOUBLE: 44, // , - SIMPLE_STRING: 43, // + - BLOB_STRING: 36, // $ - // VERBATIM_STRING: 61, // = - // SIMPLE_ERROR: 45, // - - // BLOB_ERROR: 33, // ! - ARRAY: 42, - MAP: 37, // % - SET: 126, // ~ - // ATTRIBUTE: 124, // | - // PUSH: 62 // > -} as const; - -type RespTypes = typeof RESP_TYPES[keyof typeof RESP_TYPES]; - -interface RESP3DecoderConfig { - onReply(reply: Reply): unknown; -} - -type NestedState = NestedDecoderInterface; - -// interface NestedState< -// REMAINING extends number | undefined = number | undefined, -// REPLY extends NestedDecoderInterface = NestedDecoderInterface -// > { -// type?: RespTypes; -// remaining: REMAINING; -// reply: REPLY; -// } - -// Using TypeScript `private` and not the build-in `#` to avoid __classPrivateFieldGet and __classPrivateFieldSet - -export default class RESP3Decoder { - constructor(private config: RESP3DecoderConfig) {} - - private cursor = 0; - - private type?: RespTypes; - - write(chunk: Buffer, flags: Flags): void { - while (this.cursor < chunk.length) { - let reply = this.decode(chunk, flags); - if (reply !== undefined) { - this.config.onReply(reply); - } - } - - this.cursor -= chunk.length; - } - - private decode(chunk: Buffer, flags: Flags) { - // while (this.stack.length) { - // if (this.type !== undefined) { - // const item = this.decodeType(chunk, this.type, flags); - // if (item === undefined) return; - - // let toPush = item; - // do { - // toPush = this.stack[this.stack.length - 1].reply.push(item); - // } while (toPush); - - // } - - // if (reply !== undefined) { - // const toPush = this.stack.pop(); - // this.stack[this.stack.length].reply.push(reply); - // } - // } - if (this.type === undefined) { - const type = chunk[this.cursor] as RespTypes; - if (++this.cursor === chunk.length) { - this.type = type; - return; - } - const reply = this.decodeType(chunk, type, flags); - if (reply === undefined) { - this.type = type; - } else { - return reply; - } - } - - const reply = this.decodeType(chunk, this.type, flags); - if (reply !== undefined) { - this.type = undefined; - return reply; - } - } - - private decodeType(chunk: Buffer, type: T, flags: F) { - switch (type) { - case RESP_TYPES.NULL: - return this.decodeNull(); - - case RESP_TYPES.BOOLEAN: - return this.decodeBoolean(chunk); - - case RESP_TYPES.NUMBER: - return this.decodeNumber(chunk, flags); - - // case RESP_TYPES.BIG_NUMBER: - // return this.decodeBigNumber(chunk); - - case RESP_TYPES.DOUBLE: - return this.decodeDouble(chunk, flags); - - case RESP_TYPES.SIMPLE_STRING: - return this.decodeSimpleString(chunk, flags); - - case RESP_TYPES.MAP: - return this.decodeMap(chunk, flags); - } - } - - private decodeNull() { - this.cursor += 2; // skip CRLF - return null; - } - - private decodeBoolean(chunk: Buffer) { - const reply = chunk[this.cursor + 1] === ASCII.t; - this.cursor += 3; // skip value and CRLF - return reply; - } - - private decodeNumber(chunk: Buffer, flags: F) { - switch (flags[RESP_TYPES.NUMBER]) { - case Buffer: - return this.composeString(chunk, this.bufferComposer); - - case String: - return this.composeString(chunk, this.stringComposer); - - case Number: - default: - return this.decodeNumberAsNumber(chunk); - } - } - - private isNegativeNumber?: boolean; - - private number = 0; - - private decodeNumberAsNumber(chunk: Buffer) { - if (this.isNegativeNumber === undefined) { - this.isNegativeNumber = chunk[this.cursor] === ASCII['-']; - if (this.isNegativeNumber && ++this.cursor === chunk.length) return; - } - - do { - const byte = chunk[this.cursor]; - if (byte === ASCII['\r']) { - const number = this.isNegativeNumber ? -this.number : this.number; - this.isNegativeNumber = undefined; - this.number = 0; - this.cursor += 2; // skip CRLF - return number; - } - - this.number = this.number * 10 + byte - ASCII['0']; - } while (++this.cursor < chunk.length); - } - - private isNegativeDouble?: boolean; - - // Precalculated multipliers for decimal points to improve performance - // "A Number only keeps about 17 decimal places of precision" - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number - private static DOUBLE_DECIMAL_MULTIPLIERS = [ - 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, - 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, - 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 - ]; - - private doubleDecimalIndex?: number; - - private double = 0; - - private decodeDouble(chunk: Buffer, flags: Flags) { - switch (flags[RESP_TYPES.NUMBER]) { - case Buffer: - return this.composeString(chunk, this.bufferComposer); - - case String: - return this.composeString(chunk, this.stringComposer); - - case Number: - default: - return this.decodeDoubleAsNumber(chunk); - } - } - - private decodeDoubleAsNumber(chunk: Buffer) { - if (this.isNegativeDouble === undefined) { - this.isNegativeDouble = chunk[this.cursor] === ASCII['-']; - if (this.isNegativeDouble && ++this.cursor === chunk.length) return; - } else if (this.doubleDecimalIndex !== undefined) { - return this.decodeDecimalDouble(chunk); - } - - if (this.double === 0) { - switch (chunk[this.cursor]) { - case ASCII.i: - this.cursor += 3; // skip to CRLF - return this.returnDouble(Infinity); - - case ASCII.n: - this.cursor += 3; // skip to CRLF - return this.returnDouble(NaN); - } - } - - do { - const byte = chunk[this.cursor]; - switch (byte) { - case ASCII['\r']: - return this.returnDouble(); - - case ASCII['.']: - this.doubleDecimalIndex = 0; - if (++this.cursor === chunk.length) return; - return this.decodeDecimalDouble(chunk); - - default: - this.double = this.double * 10 + byte - ASCII['0']; - } - } while (++this.cursor < chunk.length); - } - - private returnDouble(value = this.double) { - const double = this.isNegativeDouble ? -value : value; - this.isNegativeDouble = undefined; - this.doubleDecimalIndex = undefined; - this.double = 0; - this.cursor += 2; // skip CRLF - return double; - } - - private decodeDecimalDouble(chunk: Buffer): number | undefined { - do { - const byte = chunk[this.cursor]; - if (byte === ASCII['\r']) { - return this.returnDouble(); - } - - if (RESP3Decoder.DOUBLE_DECIMAL_MULTIPLIERS.length < this.doubleDecimalIndex!) { - const multiplier = RESP3Decoder.DOUBLE_DECIMAL_MULTIPLIERS[this.doubleDecimalIndex!++]; - this.double += (byte - ASCII['0']) * multiplier; - } - } while (++this.cursor < chunk.length); - } - - private bufferComposer = new BufferComposer(); - - private stringComposer = new StringComposer(); - - private decodeSimpleString(chunk: Buffer, flags: Flags) { - switch (flags[RESP_TYPES.SIMPLE_STRING]) { - case Buffer: - return this.composeString(chunk, this.bufferComposer); - - case String: - default: - return this.composeString(chunk, this.stringComposer); - } - } - - private composeString(chunk: Buffer, composer: Composer): T | undefined { - for (let i = this.cursor; i < chunk.length; i++) { - if (chunk[i] === ASCII['\r']) { - const reply = composer.end( - chunk.subarray(this.cursor, i) - ); - this.cursor = i + 2; - return reply; - } - } - - const toWrite = chunk.subarray(this.cursor); - composer.write(toWrite); - this.cursor = chunk.length; - } - - private initializingNested = false; - - private nestedStack: Array<{ - type: RespTypes | undefined, - size: number, - value: Reply | undefined - }> = []; - - private decodeNested(type: RespTypes, chunk: Buffer, flags: Flags, toKeep: number) { - if (this.nestedStack.length > toKeep) { - const frame = this.nestedStack[this.nestedStack.length - 1]; - if (frame.type === undefined) { - frame.type = chunk[this.cursor++] as RespTypes; - if (this.cursor === chunk.length) return; - } - - - } - if (this.initializingNested || this.nestedStack.length === toKeep) { - // TODO: https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-aggregated-data-types - if (chunk[this.cursor] === ASCII['?']) { - this.cursor += 3; // skip ? and CRLF - this.nestedStack.push({ - type: undefined, - size: NaN, - value: undefined - }); - } - const size = this.decodeNumberAsNumber(chunk); - if (size === undefined) { - this.initializingNested = true; - return; - } - - } - } - - // private mapKey?: Reply; - - // private decodeMap(chunk: Buffer, flags: Flags) { - // // const isNew = depth >= this.stack.length; - // // let state = this.stack[depth]; - // // if (state?.remaining === undefined) { - // // const size = this.decodeNumberAsNumber(chunk); - // // if (size === undefined) { - // // this.stack.push({ - // // type: RESP_TYPES.MAP, - // // remaining: undefined, - // // reply: undefined - // // }); - // // return; - // // } - // // if (size === 0) return {}; - // // state = { - // // type: RESP_TYPES.MAP, - // // remaining: size, - // // reply: {} - // // }; - // // } else { - // // state = this.stack[depth]; - // // } - // // // state = isNew ? this.stack[depth] : { - // // // type: RESP_TYPES.MAP, - // // // remaining: undefined, - // // // reply: undefined - // // // }; - - // switch (flags[RESP_TYPES.MAP]) { - // case Object: - // return this.decodeMapAsObject(chunk, flags, state, depth); // TODO - - // case Array: - // return; // TODO - - // case Map: - // default: - // return; // TODO - // } - // } - - // private decodeMapAsObject(chunk: Buffer, flags: Flags, state: NestedDecoderState, depth: number) { - // if (this.mapKey !== undefined) { - // const value = this. - // } - - // do { - // const key = this.decodeNewItem(chunk, flags); - // if (key === undefined) break; - // const value = this.decodeNewItem(chunk, flags); - // if (value === undefined) break; - // state.reply[`${key}`] = value; - - // if (--state.remaining! === 0) return state.reply; - // } while (this.cursor < chunk.length); - // } - - // private keepNested(chunk: Buffer, flags: Flags) { - // const reply = this.decodeType(chunk, this.stack[this.stack.length - 1], flags) - // } - - - reset() { - this.cursor = 0; - this.type = undefined; - this.isNegativeNumber = undefined; - this.number = 0; - this.isNegativeDouble = undefined; - this.doubleDecimalIndex = undefined; - this.double = 0; - this.bufferComposer.reset(); - this.stringComposer.reset(); - this.initializingNested = false; - this.nestedStack = []; - } -} \ No newline at end of file diff --git a/packages/old/RESP3-old/encoder.ts b/packages/old/RESP3-old/encoder.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/old/RESP3-old/nested-decoders/abstract.ts b/packages/old/RESP3-old/nested-decoders/abstract.ts deleted file mode 100644 index b3e5b5c304f..00000000000 --- a/packages/old/RESP3-old/nested-decoders/abstract.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Reply } from '../types'; - -export interface NestedDecoderInterface { - push(item: Reply): void | undefined | T; -} - diff --git a/packages/old/RESP3-old/nested-decoders/map-to-array.ts b/packages/old/RESP3-old/nested-decoders/map-to-array.ts deleted file mode 100644 index 21c03567ade..00000000000 --- a/packages/old/RESP3-old/nested-decoders/map-to-array.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NestedDecoderInterface } from './abstract'; -import { Reply } from '../types'; - -type Type = Array<[Reply, Reply]>; - -export class MapToArray implements NestedDecoderInterface { - private array: Type; - - private remaining: number; - - constructor(size: number) { - this.array = new Array(size); - this.remaining = size; - } - - private key: Reply | undefined; - - push(item: Reply) { - if (this.key === undefined) { - this.key = item; - return; - } - - this.array[this.array.length - this.remaining--] = [this.key, item]; - this.key = undefined; - if (this.remaining === 0) return this.array; - } -} diff --git a/packages/old/RESP3-old/nested-decoders/to-array.ts b/packages/old/RESP3-old/nested-decoders/to-array.ts deleted file mode 100644 index ae4d2d7cc2f..00000000000 --- a/packages/old/RESP3-old/nested-decoders/to-array.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NestedDecoderInterface } from './abstract'; -import { Reply } from '../types'; - -type Type = Array; - -export class ToArray implements NestedDecoderInterface { - private array: Type; - - private remaining: number; - - constructor(size: number) { - this.array = new Array(size); - this.remaining = size; - } - - push(item: Reply) { - this.array[this.array.length - this.remaining--] = item; - if (this.remaining === 0) return this.array; - } -} diff --git a/packages/old/RESP3-old/nested-decoders/to-map.ts b/packages/old/RESP3-old/nested-decoders/to-map.ts deleted file mode 100644 index d689a04cb26..00000000000 --- a/packages/old/RESP3-old/nested-decoders/to-map.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NestedDecoderInterface } from './abstract'; -import { Reply } from '../types'; - -type Type = Map; - -export class MapToArray implements NestedDecoderInterface { - private map: Type; - - private remaining: number; - - constructor(size: number) { - this.map = new Map(); - this.remaining = size; - } - - private key: Reply | undefined; - - push(item: Reply) { - if (this.key === undefined) { - this.key = item; - return; - } - - this.map.set(this.key, item); - this.key = undefined; - if (--this.remaining === 0) return this.map; - } -} diff --git a/packages/old/RESP3-old/nested-decoders/to-object.ts b/packages/old/RESP3-old/nested-decoders/to-object.ts deleted file mode 100644 index 7fe47269795..00000000000 --- a/packages/old/RESP3-old/nested-decoders/to-object.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NestedDecoderInterface } from './abstract'; -import { Reply } from '../types'; - -type Type = Record; - -export class MapToArray implements NestedDecoderInterface { - private object: Type; - - private remaining: number; - - constructor(size: number) { - this.object = {}; - this.remaining = size; - } - - private key: Reply | undefined; - - push(item: Reply) { - if (this.key === undefined) { - this.key = item; - return; - } - - this.object[this.key] = item; - this.key = undefined; - if (--this.remaining === 0) return this.object; - } -} diff --git a/packages/old/RESP3-old/nested-decoders/to-set.ts b/packages/old/RESP3-old/nested-decoders/to-set.ts deleted file mode 100644 index d44444c97c1..00000000000 --- a/packages/old/RESP3-old/nested-decoders/to-set.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NestedDecoderInterface } from './abstract'; -import { Reply } from '../types'; - -type Type = Set; - -export class ToArray implements NestedDecoderInterface { - private set: Type; - - private remaining: number; - - constructor(size: number) { - this.set = new Set(); - this.remaining = size; - } - - push(item: Reply) { - this.set.add(item); - if (--this.remaining === 0) return this.set; - } -} diff --git a/packages/old/RESP3-old/types.ts b/packages/old/RESP3-old/types.ts deleted file mode 100644 index a15c851ce7f..00000000000 --- a/packages/old/RESP3-old/types.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { RESP_TYPES } from './decoder'; - -type RESP_TYPES = { - [P in keyof typeof RESP_TYPES]: typeof RESP_TYPES[P]; -}; - -interface TypeMapping { - DEFAULT_TYPE: DEFAULT_TYPE; - TYPES: TYPES; -} - -interface TypesMapping { - [RESP_TYPES.NULL]: TypeMapping; - [RESP_TYPES.BOOLEAN]: TypeMapping; - [RESP_TYPES.NUMBER]: TypeMapping; - [RESP_TYPES.BIG_NUMBER]: TypeMapping; - [RESP_TYPES.DOUBLE]: TypeMapping; - [RESP_TYPES.SIMPLE_STRING]: TypeMapping; - [RESP_TYPES.BLOB_STRING]: TypeMapping; - [RESP_TYPES.ARRAY]: ArrayReplyTypeMapping; - [RESP_TYPES.MAP]: MapReplyTypeMapping; - [RESP_TYPES.SET]: SetReplyTypeMapping; -} - -type ArrayReplyTypeMapping = TypeMapping>; - -type ArrayReply = ReplyType>; - -type MapReplyTypeMapping = TypeMapping, { [key: string]: V; } | Array<[K, V]>>; - -type MapReply = ReplyType>; - -type SetReplyTypeMapping = TypeMapping, Array>; - -type SetReply = ReplyType>; - -type ReplyType< - RESP_TYPE extends RESP_TYPES[keyof RESP_TYPES], - TYPES extends TypeMapping -> = { - // TypeScript uses structural typing, `unique symbol` is the only way to make a type unique - // https://www.typescriptlang.org/docs/handbook/symbols.html#unique-symbol - // not using `[P in RESP_TYPE]` because it breaks inference in some cases - SYMBOL: { readonly _: unique symbol; }; - RESP_TYPE: RESP_TYPE; -} & TYPES; - -export type ReplyTypes = { - [P in keyof TypesMapping]: ReplyType; -}; - -type PrimitiveReplyTypes = ReplyTypes[Exclude]; - -type TT = TypeMapping>; - -export type Reply = string | TT; - -type Flag = (new (...args: Array) => T) | ((...args: Array) => T); - -export type Flags = { - [P in keyof TypesMapping]?: Flag; -}; - -type PickByFlag< - FLAT_TYPE, - TYPES extends TypeMapping -> = TYPES['DEFAULT_TYPE'] extends FLAT_TYPE ? TYPES['DEFAULT_TYPE'] : Extract; - -export type TransformReplyType< - FLAGS extends Flags, - REPLY -> = REPLY extends ReplyType ? ( - TransformReplyType ? PickByFlag : TYPES['DEFAULT_TYPE']> - ) : - REPLY extends Map ? Map, TransformReplyType> : - REPLY extends [infer T] ? [TransformReplyType] : - REPLY extends [infer T, ...infer REST] ? [TransformReplyType, ...TransformReplyType] : - REPLY extends Array ? Array> : - REPLY extends Record ? { - [K in keyof REPLY]: TransformReplyType - } : - REPLY extends Set ? Set> : REPLY; - -type a = TransformReplyType< - { - // [RESP_TYPES.MAP]: ArrayConstructor - [RESP_TYPES.DOUBLE]: StringConstructor, - // [RESP_TYPES.NUMBER]: BufferConstructor - }, - { - null: ReplyTypes[RESP_TYPES['NULL']], - boolean: ReplyTypes[RESP_TYPES['BOOLEAN']], - number: ReplyTypes[RESP_TYPES['NUMBER']], - bigNumber: ReplyTypes[RESP_TYPES['BIG_NUMBER']], - array: ArrayReply, - map: MapReply, - set: SetReply - } ->; - -type b = TransformReplyType ? PickByFlag> : number>; From 39bcac64846e206b59316add3c34d2aa1c1b74cc Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 24 Apr 2023 12:40:22 -0400 Subject: [PATCH 009/325] clean SET command --- README.md | 17 +++---- packages/client/lib/commands/SET.ts | 74 +++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 4fca8d405d4..80a34b75528 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,11 @@ Modifiers to commands are specified using a JavaScript object: ```typescript await client.set('key', 'value', { - EX: 10, - NX: true + expiration: { + type: 'EX', + value: 10 + }, + condition: 'NX' }); ``` @@ -108,10 +111,9 @@ await client.hVals('key'); // ['value1', 'value2'] ```typescript await client.hSet('key', 'field', Buffer.from('value')); // 'OK' -await client.hGetAll( - commandOptions({ returnBuffers: true }), - 'key' -); // { field: } +await client.withFlags({ + [TYPES.BLOB_STRING]: Buffer +}).hGetAll('key'); // { field: } ``` ### Unsupported Redis Commands @@ -151,8 +153,7 @@ This pattern works especially well for blocking commands—such as `BLPOP` and ` ```typescript import { commandOptions } from 'redis'; -const blPopPromise = client.blPop( - commandOptions({ isolated: true }), +const blPopPromise = client.isolated().blPop( 'key', 0 ); diff --git a/packages/client/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts index bb39bd89606..3def49d604f 100644 --- a/packages/client/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -1,27 +1,46 @@ import { RedisArgument, SimpleStringReply, BlobStringReply, NullReply, Command } from '../RESP/types'; -type MaximumOneOf = - K extends keyof T ? { [P in K]?: T[K] } & Partial, never>> : never; +interface SetOptions { + expiration?: { + type: 'EX' | 'PX' | 'EXAT' | 'PXAT'; + value: number; + } | { + type: 'KEEPTTL'; + } | 'KEEPTTL'; + /** + * @deprecated Use `expiration` { type: 'EX', value: number } instead + */ + EX?: number; + /** + * @deprecated Use `expiration` { type: 'PX', value: number } instead + */ + PX?: number; + /** + * @deprecated Use `expiration` { type: 'EXAT', value: number } instead + */ + EXAT?: number; + /** + * @deprecated Use `expiration` { type: 'PXAT', value: number } instead + */ + PXAT?: number; + /** + * @deprecated Use `expiration` 'KEEPTTL' instead + */ + KEEPTTL?: boolean; -type SetTTL = MaximumOneOf<{ - EX: number; - PX: number; - EXAT: number; - PXAT: number; - KEEPTTL: true; -}>; - -type SetGuards = MaximumOneOf<{ - NX: true; - XX: true; -}>; - -interface SetCommonOptions { - GET?: true; + condition?: 'NX' | 'XX'; + /** + * @deprecated Use `condition` 'NX' instead + */ + NX?: boolean; + /** + * @deprecated Use `condition` 'XX' instead + */ + XX?: boolean; + + GET?: boolean; } -export type SetOptions = SetTTL & SetGuards & SetCommonOptions; - export default { FIRST_KEY_INDEX: 1, transformArguments(key: RedisArgument, value: RedisArgument | number, options?: SetOptions) { @@ -31,7 +50,18 @@ export default { typeof value === 'number' ? value.toString() : value ]; - if (options?.EX !== undefined) { + if (options?.expiration) { + if (typeof options.expiration === 'string') { + args.push(options.expiration); + } else if (options.expiration.type === 'KEEPTTL') { + args.push('KEEPTTL'); + } else { + args.push( + options.expiration.type, + options.expiration.value.toString() + ); + } + } else if (options?.EX !== undefined) { args.push('EX', options.EX.toString()); } else if (options?.PX !== undefined) { args.push('PX', options.PX.toString()); @@ -43,7 +73,9 @@ export default { args.push('KEEPTTL'); } - if (options?.NX) { + if (options?.condition) { + args.push(options.condition); + } else if (options?.NX) { args.push('NX'); } else if (options?.XX) { args.push('XX'); From b272f18818a1ad117fbc1e1626a3801f9aefc678 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 24 Apr 2023 19:50:58 -0400 Subject: [PATCH 010/325] some more commands, multi.exec<'typed'> --- md/Redis-todo.md | 1 + md/v4-to-v5.md | 1 + packages/client/lib/client/multi-command.ts | 19 ++- .../client/lib/commands/FUNCTION_STATS.ts | 152 +++++++++--------- .../client/lib/commands/RESTORE-ASKING.ts | 13 +- packages/client/lib/commands/SAVE.ts | 13 +- packages/client/lib/commands/SCRIPT_DEBUG.ts | 13 +- packages/client/lib/commands/SCRIPT_EXISTS.ts | 13 +- packages/client/lib/commands/SCRIPT_FLUSH.ts | 15 +- packages/client/lib/commands/SCRIPT_KILL.ts | 13 +- packages/client/lib/commands/SCRIPT_LOAD.ts | 13 +- packages/client/lib/commands/SET.ts | 2 +- packages/client/lib/commands/SETBIT.ts | 19 +-- 13 files changed, 163 insertions(+), 124 deletions(-) diff --git a/md/Redis-todo.md b/md/Redis-todo.md index ab10ed249e4..9a61439b52e 100644 --- a/md/Redis-todo.md +++ b/md/Redis-todo.md @@ -10,3 +10,4 @@ `Number` -> `Boolean`: - `HSETNX` (deprecated) +- `SCRIPT EXISTS` diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index c04b54a3730..218141b4630 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -68,6 +68,7 @@ Some command arguments/replies have changed to align more closely to data types - `RENAMENX`: `boolean` -> `number` [^boolean-to-number] - `HSCAN`: `tuples` has been renamed to `entries` - `PFADD`: `boolean` -> `number` [^boolean-to-number] +- `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] [^enum-to-constants]: TODO diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index d1842e8e61a..b52190c10a3 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags } from '../RESP/types'; +import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; type CommandSignature< @@ -83,6 +83,11 @@ export type RedisClientMultiCommandType< WithScripts ); +type ReplyType< + REPLIES, + T = 'generic' +> = T extends 'typed' ? REPLIES : Array; + export type RedisClientMultiExecutor = ( queue: Array, selectedDB?: number, @@ -216,8 +221,8 @@ export default class RedisClientMultiCommand extends RedisMultiCom select = this.SELECT; - async exec(execAsPipeline = false): Promise { - if (execAsPipeline) return this.execAsPipeline(); + async exec(execAsPipeline = false) { + if (execAsPipeline) return this.execAsPipeline(); return this.handleExecReplies( await this.#executor( @@ -225,19 +230,19 @@ export default class RedisClientMultiCommand extends RedisMultiCom this.#selectedDB, RedisMultiCommand.generateChainId() ) - ) as REPLIES; + ) as ReplyType; } EXEC = this.exec; - async execAsPipeline(): Promise { - if (this.queue.length === 0) return [] as REPLIES; + async execAsPipeline() { + if (this.queue.length === 0) return [] as ReplyType; return this.transformReplies( await this.#executor( this.queue, this.#selectedDB ) - ) as REPLIES; + ) as ReplyType; } } diff --git a/packages/client/lib/commands/FUNCTION_STATS.ts b/packages/client/lib/commands/FUNCTION_STATS.ts index eacbcc19ad0..6175d7775ef 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.ts @@ -1,87 +1,87 @@ -// import { RedisCommandArguments } from '.'; +// // import { RedisCommandArguments } from '.'; -// export function transformArguments(): RedisCommandArguments { -// return ['FUNCTION', 'STATS']; -// } +// // export function transformArguments(): RedisCommandArguments { +// // return ['FUNCTION', 'STATS']; +// // } -// type FunctionStatsRawReply = [ -// 'running_script', -// null | [ -// 'name', -// string, -// 'command', -// string, -// 'duration_ms', -// number -// ], -// 'engines', -// Array // "flat tuples" (there is no way to type that) -// // ...[string, [ -// // 'libraries_count', -// // number, -// // 'functions_count', -// // number -// // ]] -// ]; +// // type FunctionStatsRawReply = [ +// // 'running_script', +// // null | [ +// // 'name', +// // string, +// // 'command', +// // string, +// // 'duration_ms', +// // number +// // ], +// // 'engines', +// // Array // "flat tuples" (there is no way to type that) +// // // ...[string, [ +// // // 'libraries_count', +// // // number, +// // // 'functions_count', +// // // number +// // // ]] +// // ]; -// interface FunctionStatsReply { -// runningScript: null | { -// name: string; -// command: string; -// durationMs: number; -// }; -// engines: Record; -// } +// // interface FunctionStatsReply { +// // runningScript: null | { +// // name: string; +// // command: string; +// // durationMs: number; +// // }; +// // engines: Record; +// // } -// export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { -// const engines = Object.create(null); -// for (let i = 0; i < reply[3].length; i++) { -// engines[reply[3][i]] = { -// librariesCount: reply[3][++i][1], -// functionsCount: reply[3][i][3] -// }; -// } +// // export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { +// // const engines = Object.create(null); +// // for (let i = 0; i < reply[3].length; i++) { +// // engines[reply[3][i]] = { +// // librariesCount: reply[3][++i][1], +// // functionsCount: reply[3][i][3] +// // }; +// // } -// return { -// runningScript: reply[1] === null ? null : { -// name: reply[1][1], -// command: reply[1][3], -// durationMs: reply[1][5] -// }, -// engines -// }; -// } +// // return { +// // runningScript: reply[1] === null ? null : { +// // name: reply[1][1], +// // command: reply[1][3], +// // durationMs: reply[1][5] +// // }, +// // engines +// // }; +// // } -// #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } +// // #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } -import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; +// import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; -type FunctionStatsReply = TuplesToMapReply<[ - [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ - [BlobStringReply<'name'>, BlobStringReply], - [BlobStringReply<'command'>, BlobStringReply], - [BlobStringReply<'duration_ms'>, NumberReply] - ]>], - [BlobStringReply<'engines'>, MapReply, NumberReply], - [BlobStringReply<'functions_count'>, NumberReply] - ]>>] -]>; +// type FunctionStatsReply = TuplesToMapReply<[ +// [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ +// [BlobStringReply<'name'>, BlobStringReply], +// [BlobStringReply<'command'>, BlobStringReply], +// [BlobStringReply<'duration_ms'>, NumberReply] +// ]>], +// [BlobStringReply<'engines'>, MapReply, NumberReply], +// [BlobStringReply<'functions_count'>, NumberReply] +// ]>>] +// ]>; -export default { - IS_READ_ONLY: true, - FIRST_KEY_INDEX: undefined, - transformArguments() { - return ['FUNCTION', 'STATS']; - }, - transformReply: { - 2: (reply) => { +// export default { +// IS_READ_ONLY: true, +// FIRST_KEY_INDEX: undefined, +// transformArguments() { +// return ['FUNCTION', 'STATS']; +// }, +// transformReply: { +// 2: (reply) => { - }, - 3: undefined as unknown as () => - } -} as const satisfies Command; +// }, +// 3: undefined as unknown as () => +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/RESTORE-ASKING.ts b/packages/client/lib/commands/RESTORE-ASKING.ts index d53d8541cd7..f9cb75ab3c5 100644 --- a/packages/client/lib/commands/RESTORE-ASKING.ts +++ b/packages/client/lib/commands/RESTORE-ASKING.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['RESTORE-ASKING']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['RESTORE-ASKING']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SAVE.ts b/packages/client/lib/commands/SAVE.ts index 3d75c29df90..53cb2486965 100644 --- a/packages/client/lib/commands/SAVE.ts +++ b/packages/client/lib/commands/SAVE.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['SAVE']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.ts b/packages/client/lib/commands/SCRIPT_DEBUG.ts index e9e1e909d59..8c0021382df 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.ts @@ -1,5 +1,10 @@ -export function transformArguments(mode: 'YES' | 'SYNC' | 'NO'): Array { - return ['SCRIPT', 'DEBUG', mode]; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(mode: 'YES' | 'SYNC' | 'NO') { + return ['SCRIPT', 'DEBUG', mode]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts index 72123806e85..4233f7dc223 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.ts @@ -1,8 +1,11 @@ -import { RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; import { pushVariadicArguments } from './generic-transformers'; -export function transformArguments(sha1: string | Array): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(sha1: RedisArgument | Array) { return pushVariadicArguments(['SCRIPT', 'EXISTS'], sha1); -} - -export { transformBooleanArrayReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.ts b/packages/client/lib/commands/SCRIPT_FLUSH.ts index 2c220e9e3d1..a6bfe7648cb 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.ts @@ -1,11 +1,16 @@ -export function transformArguments(mode?: 'ASYNC' | 'SYNC'): Array { +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(mode?: 'ASYNC' | 'SYNC') { const args = ['SCRIPT', 'FLUSH']; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_KILL.ts b/packages/client/lib/commands/SCRIPT_KILL.ts index c0a53da8681..96aa119b01f 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['SCRIPT', 'KILL']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['SCRIPT', 'KILL']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_LOAD.ts b/packages/client/lib/commands/SCRIPT_LOAD.ts index 7cb28c1ec7f..758a6835ac9 100644 --- a/packages/client/lib/commands/SCRIPT_LOAD.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.ts @@ -1,5 +1,10 @@ -export function transformArguments(script: string): Array { - return ['SCRIPT', 'LOAD', script]; -} +import { BlobStringReply, Command, RedisArgument } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(script: RedisArgument) { + return ['SCRIPT', 'LOAD', script]; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts index 3def49d604f..f0b1efd4f0b 100644 --- a/packages/client/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -1,6 +1,6 @@ import { RedisArgument, SimpleStringReply, BlobStringReply, NullReply, Command } from '../RESP/types'; -interface SetOptions { +export interface SetOptions { expiration?: { type: 'EX' | 'PX' | 'EXAT' | 'PXAT'; value: number; diff --git a/packages/client/lib/commands/SETBIT.ts b/packages/client/lib/commands/SETBIT.ts index 94f463330a8..20c69155b05 100644 --- a/packages/client/lib/commands/SETBIT.ts +++ b/packages/client/lib/commands/SETBIT.ts @@ -1,14 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { BitValue } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + IS_READ_ONLY: false, + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, offset: number, value: BitValue -): RedisCommandArguments { + ) { return ['SETBIT', key, offset.toString(), value.toString()]; -} - -export declare function transformReply(): BitValue; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From 567ae381b0b5e6ade455c19264b0433881de20f6 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 25 Apr 2023 09:48:11 -0400 Subject: [PATCH 011/325] "typed" multi --- md/v5-new-features.md | 17 ++++------- packages/client/lib/client/multi-command.ts | 33 ++++++++++++++------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/md/v5-new-features.md b/md/v5-new-features.md index 56dd12b49c5..bfac25315bd 100644 --- a/md/v5-new-features.md +++ b/md/v5-new-features.md @@ -21,20 +21,15 @@ client.withFlags({ }).hGetAll('key'); // Map ``` -# `Multi.exec<'typed'>` +# `multi.exec<'typed'>` / `multi.execTyped` -We have introduced the ability to perform a 'typed' `MULTI`/`EXEC` transaction. Rather than returning `Array`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible. - -Example: +We have introduced the ability to perform a "typed" `MULTI`/`EXEC` transaction. Rather than returning `Array`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible: ```javascript -client.multi() - .ping() - .exec(); // Array - -client.multi() - .ping() - .exec<'typed'>(); // [string] +const multi = client.multi().ping(); +await multi.exec(); // Array +await multi.exec<'typed'>(); // [string] +await multi.execTyped(); // [string] ``` # Request & Reply Policies diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index b52190c10a3..3503a34af2b 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -83,10 +83,14 @@ export type RedisClientMultiCommandType< WithScripts ); -type ReplyType< - REPLIES, - T = 'generic' -> = T extends 'typed' ? REPLIES : Array; +type MULTI_REPLY = { + GENERIC: 'generic'; + TYPED: 'typed'; +}; + +type MultiReply = MULTI_REPLY[keyof MULTI_REPLY]; + +type ReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; export type RedisClientMultiExecutor = ( queue: Array, @@ -144,8 +148,7 @@ export default class RedisClientMultiCommand extends RedisMultiCom M extends RedisModules = Record, F extends RedisFunctions = Record, S extends RedisScripts = Record, - RESP extends RespVersions = 2, - FLAGS extends Flags = {} + RESP extends RespVersions = 2 >(config?: CommanderConfig) { return attachConfig({ BaseClass: RedisClientMultiCommand, @@ -221,7 +224,7 @@ export default class RedisClientMultiCommand extends RedisMultiCom select = this.SELECT; - async exec(execAsPipeline = false) { + async exec(execAsPipeline = false) { if (execAsPipeline) return this.execAsPipeline(); return this.handleExecReplies( @@ -230,19 +233,27 @@ export default class RedisClientMultiCommand extends RedisMultiCom this.#selectedDB, RedisMultiCommand.generateChainId() ) - ) as ReplyType; + ) as ReplyType; } EXEC = this.exec; - async execAsPipeline() { - if (this.queue.length === 0) return [] as ReplyType; + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); + } + + async execAsPipeline() { + if (this.queue.length === 0) return [] as ReplyType; return this.transformReplies( await this.#executor( this.queue, this.#selectedDB ) - ) as ReplyType; + ) as ReplyType; + } + + execAsPipelineTyped() { + return this.execAsPipeline(); } } From e25bcff293d2b9e2708dc93346eddbce58756a7f Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 13:32:10 -0400 Subject: [PATCH 012/325] WIP --- md/Redis-todo.md | 1 + md/v4-to-v5.md | 16 + packages/client/lib/client/index.ts | 43 +- packages/client/lib/cluster/index.ts | 2 +- packages/client/lib/commands/BLMPOP.ts | 6 +- packages/client/lib/commands/BLPOP.ts | 6 +- packages/client/lib/commands/BRPOP.ts | 6 +- packages/client/lib/commands/BZMPOP.ts | 54 +- packages/client/lib/commands/BZPOPMAX.ts | 42 +- packages/client/lib/commands/BZPOPMIN.ts | 24 +- .../client/lib/commands/CLIENT_TRACKING.ts | 136 +-- .../lib/commands/CLIENT_TRACKINGINFO.ts | 48 +- packages/client/lib/commands/COMMAND.ts | 18 +- packages/client/lib/commands/COMMAND_COUNT.ts | 12 +- .../client/lib/commands/COMMAND_GETKEYS.ts | 12 +- .../lib/commands/COMMAND_GETKEYSANDFLAGS.ts | 38 +- packages/client/lib/commands/COMMAND_INFO.ts | 18 +- packages/client/lib/commands/COMMAND_LIST.ts | 46 +- packages/client/lib/commands/DEL.ts | 6 +- packages/client/lib/commands/EXISTS.ts | 6 +- .../client/lib/commands/FUNCTION_DELETE.ts | 2 +- packages/client/lib/commands/FUNCTION_DUMP.ts | 2 +- .../client/lib/commands/FUNCTION_FLUSH.ts | 2 +- packages/client/lib/commands/FUNCTION_KILL.ts | 2 +- packages/client/lib/commands/FUNCTION_LIST.ts | 24 +- .../lib/commands/FUNCTION_LIST_WITHCODE.ts | 44 +- packages/client/lib/commands/FUNCTION_LOAD.ts | 32 +- .../client/lib/commands/FUNCTION_RESTORE.ts | 24 +- packages/client/lib/commands/GEOADD.ts | 80 +- packages/client/lib/commands/GEODIST.ts | 27 +- packages/client/lib/commands/GEOHASH.ts | 27 +- packages/client/lib/commands/GEOPOS.ts | 40 +- packages/client/lib/commands/GEORADIUS.ts | 42 +- .../client/lib/commands/GEORADIUSBYMEMBER.ts | 42 +- .../lib/commands/GEORADIUSBYMEMBERSTORE.ts | 44 +- .../lib/commands/GEORADIUSBYMEMBER_RO.ts | 42 +- .../lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts | 48 +- .../lib/commands/GEORADIUSBYMEMBER_WITH.ts | 48 +- .../client/lib/commands/GEORADIUSSTORE.ts | 44 +- packages/client/lib/commands/GEORADIUS_RO.ts | 42 +- .../client/lib/commands/GEORADIUS_RO_WITH.ts | 48 +- .../client/lib/commands/GEORADIUS_WITH.ts | 48 +- packages/client/lib/commands/GEOSEARCH.ts | 26 +- .../client/lib/commands/GEOSEARCHSTORE.ts | 62 +- .../client/lib/commands/GEOSEARCH_WITH.ts | 34 +- packages/client/lib/commands/GETBIT.ts | 20 +- packages/client/lib/commands/HSCAN.ts | 4 +- packages/client/lib/commands/LATENCY_GRAPH.ts | 44 +- packages/client/lib/commands/LMPOP.ts | 6 +- packages/client/lib/commands/LOLWUT.ts | 2 +- packages/client/lib/commands/LPOP_COUNT.ts | 2 +- packages/client/lib/commands/LPUSH.ts | 4 +- packages/client/lib/commands/LPUSHX.ts | 4 +- packages/client/lib/commands/MODULE_LIST.ts | 2 +- packages/client/lib/commands/MODULE_LOAD.ts | 10 +- packages/client/lib/commands/MODULE_UNLOAD.ts | 2 +- packages/client/lib/commands/PFADD.ts | 9 +- packages/client/lib/commands/PFCOUNT.ts | 6 +- packages/client/lib/commands/PFMERGE.ts | 9 +- packages/client/lib/commands/PUBLISH.ts | 2 +- .../client/lib/commands/PUBSUB_CHANNELS.ts | 2 +- packages/client/lib/commands/PUBSUB_NUMPAT.ts | 2 +- packages/client/lib/commands/PUBSUB_NUMSUB.ts | 8 +- .../lib/commands/PUBSUB_SHARDCHANNELS.ts | 2 +- packages/client/lib/commands/READONLY.ts | 2 +- packages/client/lib/commands/READWRITE.ts | 2 +- packages/client/lib/commands/REPLICAOF.ts | 2 +- .../client/lib/commands/RESTORE-ASKING.ts | 2 +- packages/client/lib/commands/ROLE.ts | 2 +- packages/client/lib/commands/SAVE.ts | 2 +- packages/client/lib/commands/SCAN.spec.ts | 124 ++- packages/client/lib/commands/SCAN.ts | 30 +- packages/client/lib/commands/SCRIPT_DEBUG.ts | 2 +- packages/client/lib/commands/SCRIPT_EXISTS.ts | 8 +- packages/client/lib/commands/SCRIPT_FLUSH.ts | 2 +- packages/client/lib/commands/SCRIPT_KILL.ts | 2 +- packages/client/lib/commands/SCRIPT_LOAD.ts | 2 +- packages/client/lib/commands/SETBIT.ts | 2 +- packages/client/lib/commands/SINTERSTORE.ts | 23 +- packages/client/lib/commands/SISMEMBER.ts | 18 +- packages/client/lib/commands/SMISMEMBER.ts | 18 +- packages/client/lib/commands/SMOVE.ts | 20 +- packages/client/lib/commands/SORT.ts | 64 +- packages/client/lib/commands/SORT_RO.ts | 24 +- packages/client/lib/commands/SORT_STORE.ts | 24 +- packages/client/lib/commands/SPOP.ts | 26 +- packages/client/lib/commands/SPUBLISH.ts | 20 +- packages/client/lib/commands/SRANDMEMBER.ts | 15 +- .../client/lib/commands/SRANDMEMBER_COUNT.ts | 26 +- packages/client/lib/commands/SREM.ts | 20 +- packages/client/lib/commands/SSCAN.ts | 4 +- packages/client/lib/commands/SUNION.ts | 20 +- packages/client/lib/commands/SUNIONSTORE.ts | 20 +- packages/client/lib/commands/TOUCH.ts | 19 +- packages/client/lib/commands/UNLINK.ts | 19 +- packages/client/lib/commands/WATCH.ts | 17 +- packages/client/lib/commands/XACK.ts | 22 +- packages/client/lib/commands/XADD.ts | 104 +-- packages/client/lib/commands/XAUTOCLAIM.ts | 78 +- .../client/lib/commands/XAUTOCLAIM_JUSTID.ts | 40 +- packages/client/lib/commands/XCLAIM.ts | 96 +- packages/client/lib/commands/XCLAIM_JUSTID.ts | 20 +- packages/client/lib/commands/XDEL.ts | 20 +- packages/client/lib/commands/XGROUP_CREATE.ts | 36 +- .../lib/commands/XGROUP_CREATECONSUMER.ts | 20 +- .../client/lib/commands/XGROUP_DELCONSUMER.ts | 20 +- .../client/lib/commands/XGROUP_DESTROY.ts | 18 +- packages/client/lib/commands/XGROUP_SETID.ts | 20 +- .../client/lib/commands/XINFO_CONSUMERS.ts | 42 +- packages/client/lib/commands/XINFO_GROUPS.ts | 40 +- packages/client/lib/commands/XINFO_STREAM.ts | 102 +-- packages/client/lib/commands/XLEN.ts | 17 +- packages/client/lib/commands/XPENDING.ts | 76 +- .../client/lib/commands/XPENDING_RANGE.ts | 112 +-- packages/client/lib/commands/XRANGE.ts | 38 +- packages/client/lib/commands/XREAD.ts | 70 +- packages/client/lib/commands/XREADGROUP.ts | 114 +-- packages/client/lib/commands/XREVRANGE.ts | 38 +- packages/client/lib/commands/XSETID.ts | 42 +- packages/client/lib/commands/XTRIM.ts | 46 +- packages/client/lib/commands/ZADD.ts | 6 +- packages/client/lib/commands/ZCOUNT.ts | 6 +- packages/client/lib/commands/ZINCRBY.ts | 6 +- packages/client/lib/commands/ZINTER.ts | 6 +- packages/client/lib/commands/ZMPOP.ts | 103 ++- packages/client/lib/commands/ZPOPMAX.ts | 18 +- packages/client/lib/commands/ZPOPMAX_COUNT.ts | 26 +- packages/client/lib/commands/ZPOPMIN.ts | 18 +- packages/client/lib/commands/ZPOPMIN_COUNT.ts | 26 +- packages/client/lib/commands/ZRANDMEMBER.ts | 17 +- .../client/lib/commands/ZRANDMEMBER_COUNT.ts | 27 +- .../commands/ZRANDMEMBER_COUNT_WITHSCORES.ts | 25 +- packages/client/lib/commands/ZRANGE.ts | 67 +- packages/client/lib/commands/ZRANGEBYLEX.ts | 56 +- packages/client/lib/commands/ZRANGEBYSCORE.ts | 56 +- .../lib/commands/ZRANGEBYSCORE_WITHSCORES.ts | 30 +- packages/client/lib/commands/ZRANGESTORE.ts | 124 +-- .../client/lib/commands/ZRANGE_WITHSCORES.ts | 20 +- packages/client/lib/commands/ZRANK.ts | 20 +- packages/client/lib/commands/ZREM.ts | 23 +- .../client/lib/commands/ZREMRANGEBYLEX.ts | 32 +- .../client/lib/commands/ZREMRANGEBYRANK.ts | 20 +- .../client/lib/commands/ZREMRANGEBYSCORE.ts | 32 +- packages/client/lib/commands/ZREVRANK.ts | 20 +- packages/client/lib/commands/ZSCAN.ts | 7 +- packages/client/lib/commands/ZSCORE.ts | 23 +- packages/client/lib/commands/ZUNION.ts | 44 +- packages/client/lib/commands/ZUNIONSTORE.ts | 44 +- .../client/lib/commands/ZUNION_WITHSCORES.ts | 20 +- .../lib/commands/generic-transformers.ts | 852 +++++++++--------- packages/client/package.json | 2 +- 151 files changed, 2571 insertions(+), 2573 deletions(-) diff --git a/md/Redis-todo.md b/md/Redis-todo.md index 9a61439b52e..ec64adf9d28 100644 --- a/md/Redis-todo.md +++ b/md/Redis-todo.md @@ -7,6 +7,7 @@ `String` -> `Double`: - `INCRBYFLOAT` - `HINCRBYFLOAT` +- `GEODIST` `Number` -> `Boolean`: - `HSETNX` (deprecated) diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index 218141b4630..481bd95c696 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -45,6 +45,20 @@ Rather than using `client.quit()`, your code should use `client.close()` or `cli TODO difference between `close` and `disconnect`... +## Scan Iterators + +TODO + +Yields chunks instead of individual items: + +```javascript +for await (const chunk of client.scanIterator()) { + // `chunk` type is `Array` + // will allow multi keys operations + await client.del(chunk); +} +``` + ## Commands Some command arguments/replies have changed to align more closely to data types returned by Redis: @@ -69,6 +83,8 @@ Some command arguments/replies have changed to align more closely to data types - `HSCAN`: `tuples` has been renamed to `entries` - `PFADD`: `boolean` -> `number` [^boolean-to-number] - `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] +- `SISMEMBER`: `boolean` -> `number` [^boolean-to-number] +- `SMISMEMBER`: `Array` -> `Array` [^boolean-to-number] [^enum-to-constants]: TODO diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 7d5e18a4c1b..493d32de9d5 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -12,13 +12,8 @@ import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-co import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; -import { ReplyWithFlags, BlobStringReply } from '../RESP/types'; -import { ScanCommandOptions } from '../commands/SCAN'; -import { HScanEntry } from '../commands/HSCAN'; -import { ScanOptions, ZMember } from '../commands/generic-transformers'; - - - +import { ReplyWithFlags, CommandReply } from '../RESP/types'; +import SCAN, { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; export interface RedisClientOptions< M extends RedisModules = RedisModules, @@ -538,7 +533,7 @@ export default class RedisClient< value: V ) { const proxy = Object.create(this.self); - proxy.commandOptions = Object.create((this as ProxyClient).commandOptions ?? null); + proxy.commandOptions = Object.create((this as unknown as ProxyClient).commandOptions ?? null); proxy.commandOptions[key] = value; return proxy as RedisClientType< M, @@ -840,60 +835,52 @@ export default class RedisClient< async* scanIterator( this: RedisClientType, - options?: ScanCommandOptions & ScanIteratorOptions - ): AsyncIterable> { + options?: ScanOptions & ScanIteratorOptions + ): AsyncIterable['keys'], FLAGS>> { let cursor = options?.cursor ?? 0; do { const reply = await this.scan(cursor, options); cursor = reply.cursor; - for (const key of reply.keys) { - yield key; - } + yield reply.keys; } while (cursor !== 0); } async* hScanIterator( this: RedisClientType, key: RedisArgument, - options?: ScanOptions & ScanIteratorOptions - ): AsyncIterable> { + options?: ScanCommonOptions & ScanIteratorOptions + ) { let cursor = options?.cursor ?? 0; do { const reply = await this.hScan(key, cursor, options); cursor = reply.cursor; - for (const entry of reply.entries) { - yield entry; - } + yield reply.entries; } while (cursor !== 0); } async* sScanIterator( this: RedisClientType, key: RedisArgument, - options?: ScanOptions & ScanIteratorOptions - ): AsyncIterable> { + options?: ScanCommonOptions & ScanIteratorOptions + ) { let cursor = options?.cursor ?? 0; do { const reply = await this.sScan(key, cursor, options); cursor = reply.cursor; - for (const member of reply.members) { - yield member; - } + yield reply.members; } while (cursor !== 0); } async* zScanIterator( this: RedisClientType, key: RedisArgument, - options?: ScanOptions & ScanIteratorOptions - ): AsyncIterable> { + options?: ScanCommonOptions & ScanIteratorOptions + ) { let cursor = options?.cursor ?? 0; do { const reply = await this.zScan(key, cursor, options); cursor = reply.cursor; - for (const member of reply.members) { - yield member; - } + yield reply.members; } while (cursor !== 0); } diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 4e69452f7cd..96560fdaf05 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -326,7 +326,7 @@ export default class RedisCluster< value: V ) { const proxy = Object.create(this); - proxy.commandOptions = Object.create((this as ProxyCluster).commandOptions ?? null); + proxy.commandOptions = Object.create((this as unknown as ProxyCluster).commandOptions ?? null); proxy.commandOptions[key] = value; return proxy as RedisClusterType< M, diff --git a/packages/client/lib/commands/BLMPOP.ts b/packages/client/lib/commands/BLMPOP.ts index 32d249899b0..ec9ab56829b 100644 --- a/packages/client/lib/commands/BLMPOP.ts +++ b/packages/client/lib/commands/BLMPOP.ts @@ -1,5 +1,5 @@ -import { RedisArgument, Command } from '../RESP/types'; -import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; +import { Command } from '../RESP/types'; +import { transformLMPopArguments, LMPopOptions, ListSide, RedisVariadicArgument } from './generic-transformers'; import LMPOP from './LMPOP'; export default { @@ -7,7 +7,7 @@ export default { IS_READ_ONLY: false, transformArguments( timeout: number, - keys: RedisArgument | Array, + keys: RedisVariadicArgument, side: ListSide, options?: LMPopOptions ) { diff --git a/packages/client/lib/commands/BLPOP.ts b/packages/client/lib/commands/BLPOP.ts index feb0fd65127..e96617e21d4 100644 --- a/packages/client/lib/commands/BLPOP.ts +++ b/packages/client/lib/commands/BLPOP.ts @@ -1,11 +1,11 @@ -import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { BlobStringReply, NullReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments( - key: RedisArgument | Array, + key: RedisVariadicArgument, timeout: number ) { const args = pushVariadicArguments(['BRPOP'], key); diff --git a/packages/client/lib/commands/BRPOP.ts b/packages/client/lib/commands/BRPOP.ts index 64e8ed8404d..f9c8aaa5037 100644 --- a/packages/client/lib/commands/BRPOP.ts +++ b/packages/client/lib/commands/BRPOP.ts @@ -1,12 +1,12 @@ -import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; import BLPOP from './BLPOP'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments( - key: RedisArgument | Array, + key: RedisVariadicArgument, timeout: number ) { const args = pushVariadicArguments(['BRPOP'], key); diff --git a/packages/client/lib/commands/BZMPOP.ts b/packages/client/lib/commands/BZMPOP.ts index 936ccf800c8..b043d5fcf64 100644 --- a/packages/client/lib/commands/BZMPOP.ts +++ b/packages/client/lib/commands/BZMPOP.ts @@ -1,34 +1,34 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { SortedSetSide, transformZMPopArguments, ZMPopOptions } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { SortedSetSide, transformZMPopArguments, ZMPopOptions } from './generic-transformers'; -export const FIRST_KEY_INDEX = 3; +// export const FIRST_KEY_INDEX = 3; -export function transformArguments( - timeout: number, - keys: RedisCommandArgument | Array, - side: SortedSetSide, - options?: ZMPopOptions -): RedisCommandArguments { - return transformZMPopArguments( - ['BZMPOP', timeout.toString()], - keys, - side, - options - ); -} +// export function transformArguments( +// timeout: number, +// keys: RedisCommandArgument | Array, +// side: SortedSetSide, +// options?: ZMPopOptions +// ): RedisCommandArguments { +// return transformZMPopArguments( +// ['BZMPOP', timeout.toString()], +// keys, +// side, +// options +// ); +// } -export { transformReply } from './ZMPOP'; +// export { transformReply } from './ZMPOP'; -import { Command } from '../RESP/types'; -import ZMPOP from './ZMPOP'; +// import { Command } from '../RESP/types'; +// import ZMPOP from './ZMPOP'; -export default { - IS_READ_ONLY: false, - FIRST_KEY_INDEX: 3, - transformArguments() { - return ['BZMPOP']; - }, - transformReply: ZMPOP.transformReply -} as const satisfies Command; +// export default { +// FIRST_KEY_INDEX: 3, +// IS_READ_ONLY: false, +// transformArguments() { +// return ['BZMPOP']; +// }, +// transformReply: ZMPOP.transformReply +// } as const satisfies Command; diff --git a/packages/client/lib/commands/BZPOPMAX.ts b/packages/client/lib/commands/BZPOPMAX.ts index be92c194ef1..250bc982b45 100644 --- a/packages/client/lib/commands/BZPOPMAX.ts +++ b/packages/client/lib/commands/BZPOPMAX.ts @@ -1,29 +1,29 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments, transformNumberInfinityReply, ZMember } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments, transformDoubleReply, ZMember } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument | Array, - timeout: number -): RedisCommandArguments { - const args = pushVariadicArguments(['BZPOPMAX'], key); +// export function transformArguments( +// key: RedisCommandArgument | Array, +// timeout: number +// ): RedisCommandArguments { +// const args = pushVariadicArguments(['BZPOPMAX'], key); - args.push(timeout.toString()); +// args.push(timeout.toString()); - return args; -} +// return args; +// } -type ZMemberRawReply = [key: RedisCommandArgument, value: RedisCommandArgument, score: RedisCommandArgument] | null; +// type ZMemberRawReply = [key: RedisCommandArgument, value: RedisCommandArgument, score: RedisCommandArgument] | null; -type BZPopMaxReply = (ZMember & { key: RedisCommandArgument }) | null; +// type BZPopMaxReply = (ZMember & { key: RedisCommandArgument }) | null; -export function transformReply(reply: ZMemberRawReply): BZPopMaxReply | null { - if (!reply) return null; +// export function transformReply(reply: ZMemberRawReply): BZPopMaxReply | null { +// if (!reply) return null; - return { - key: reply[0], - value: reply[1], - score: transformNumberInfinityReply(reply[2]) - }; -} +// return { +// key: reply[0], +// value: reply[1], +// score: transformDoubleReply(reply[2]) +// }; +// } diff --git a/packages/client/lib/commands/BZPOPMIN.ts b/packages/client/lib/commands/BZPOPMIN.ts index 02d9f9215bf..967633697a4 100644 --- a/packages/client/lib/commands/BZPOPMIN.ts +++ b/packages/client/lib/commands/BZPOPMIN.ts @@ -1,17 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument | Array, - timeout: number -): RedisCommandArguments { - const args = pushVariadicArguments(['BZPOPMIN'], key); +// export function transformArguments( +// key: RedisCommandArgument | Array, +// timeout: number +// ): RedisCommandArguments { +// const args = pushVariadicArguments(['BZPOPMIN'], key); - args.push(timeout.toString()); +// args.push(timeout.toString()); - return args; -} +// return args; +// } -export { transformReply } from './BZPOPMAX'; +// export { transformReply } from './BZPOPMAX'; diff --git a/packages/client/lib/commands/CLIENT_TRACKING.ts b/packages/client/lib/commands/CLIENT_TRACKING.ts index c70702706e4..03926b5300f 100644 --- a/packages/client/lib/commands/CLIENT_TRACKING.ts +++ b/packages/client/lib/commands/CLIENT_TRACKING.ts @@ -1,83 +1,83 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -interface CommonOptions { - REDIRECT?: number; - NOLOOP?: boolean; -} +// interface CommonOptions { +// REDIRECT?: number; +// NOLOOP?: boolean; +// } -interface BroadcastOptions { - BCAST?: boolean; - PREFIX?: RedisCommandArgument | Array; -} +// interface BroadcastOptions { +// BCAST?: boolean; +// PREFIX?: RedisCommandArgument | Array; +// } -interface OptInOptions { - OPTIN?: boolean; -} +// interface OptInOptions { +// OPTIN?: boolean; +// } -interface OptOutOptions { - OPTOUT?: boolean; -} +// interface OptOutOptions { +// OPTOUT?: boolean; +// } -type ClientTrackingOptions = CommonOptions & ( - BroadcastOptions | - OptInOptions | - OptOutOptions -); +// type ClientTrackingOptions = CommonOptions & ( +// BroadcastOptions | +// OptInOptions | +// OptOutOptions +// ); -export function transformArguments( - mode: M, - options?: M extends true ? ClientTrackingOptions : undefined -): RedisCommandArguments { - const args: RedisCommandArguments = [ - 'CLIENT', - 'TRACKING', - mode ? 'ON' : 'OFF' - ]; +// export function transformArguments( +// mode: M, +// options?: M extends true ? ClientTrackingOptions : undefined +// ): RedisCommandArguments { +// const args: RedisCommandArguments = [ +// 'CLIENT', +// 'TRACKING', +// mode ? 'ON' : 'OFF' +// ]; - if (mode) { - if (options?.REDIRECT) { - args.push( - 'REDIRECT', - options.REDIRECT.toString() - ); - } +// if (mode) { +// if (options?.REDIRECT) { +// args.push( +// 'REDIRECT', +// options.REDIRECT.toString() +// ); +// } - if (isBroadcast(options)) { - args.push('BCAST'); +// if (isBroadcast(options)) { +// args.push('BCAST'); - if (options?.PREFIX) { - if (Array.isArray(options.PREFIX)) { - for (const prefix of options.PREFIX) { - args.push('PREFIX', prefix); - } - } else { - args.push('PREFIX', options.PREFIX); - } - } - } else if (isOptIn(options)) { - args.push('OPTIN'); - } else if (isOptOut(options)) { - args.push('OPTOUT'); - } +// if (options?.PREFIX) { +// if (Array.isArray(options.PREFIX)) { +// for (const prefix of options.PREFIX) { +// args.push('PREFIX', prefix); +// } +// } else { +// args.push('PREFIX', options.PREFIX); +// } +// } +// } else if (isOptIn(options)) { +// args.push('OPTIN'); +// } else if (isOptOut(options)) { +// args.push('OPTOUT'); +// } - if (options?.NOLOOP) { - args.push('NOLOOP'); - } - } +// if (options?.NOLOOP) { +// args.push('NOLOOP'); +// } +// } - return args; -} +// return args; +// } -function isBroadcast(options?: ClientTrackingOptions): options is BroadcastOptions { - return (options as BroadcastOptions)?.BCAST === true; -} +// function isBroadcast(options?: ClientTrackingOptions): options is BroadcastOptions { +// return (options as BroadcastOptions)?.BCAST === true; +// } -function isOptIn(options?: ClientTrackingOptions): options is OptInOptions { - return (options as OptInOptions)?.OPTIN === true; -} +// function isOptIn(options?: ClientTrackingOptions): options is OptInOptions { +// return (options as OptInOptions)?.OPTIN === true; +// } -function isOptOut(options?: ClientTrackingOptions): options is OptOutOptions { - return (options as OptOutOptions)?.OPTOUT === true; -} +// function isOptOut(options?: ClientTrackingOptions): options is OptOutOptions { +// return (options as OptOutOptions)?.OPTOUT === true; +// } -export declare function transformReply(): 'OK' | Buffer; +// export declare function transformReply(): 'OK' | Buffer; diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts index 7c883fc6997..fd897bb67c6 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts @@ -1,28 +1,28 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export function transformArguments(): RedisCommandArguments { - return ['CLIENT', 'TRACKINGINFO']; -} +// export function transformArguments(): RedisCommandArguments { +// return ['CLIENT', 'TRACKINGINFO']; +// } -type RawReply = [ - 'flags', - Array, - 'redirect', - number, - 'prefixes', - Array -]; +// type RawReply = [ +// 'flags', +// Array, +// 'redirect', +// number, +// 'prefixes', +// Array +// ]; -interface Reply { - flags: Set; - redirect: number; - prefixes: Array; -} +// interface Reply { +// flags: Set; +// redirect: number; +// prefixes: Array; +// } -export function transformReply(reply: RawReply): Reply { - return { - flags: new Set(reply[1]), - redirect: reply[3], - prefixes: reply[5] - }; -} +// export function transformReply(reply: RawReply): Reply { +// return { +// flags: new Set(reply[1]), +// redirect: reply[3], +// prefixes: reply[5] +// }; +// } diff --git a/packages/client/lib/commands/COMMAND.ts b/packages/client/lib/commands/COMMAND.ts index b6ee50b2f4c..a67ae1012df 100644 --- a/packages/client/lib/commands/COMMAND.ts +++ b/packages/client/lib/commands/COMMAND.ts @@ -1,12 +1,12 @@ -import { RedisCommandArguments } from '.'; -import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers'; +// import { RedisCommandArguments } from '.'; +// import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(): RedisCommandArguments { - return ['COMMAND']; -} +// export function transformArguments(): RedisCommandArguments { +// return ['COMMAND']; +// } -export function transformReply(reply: Array): Array { - return reply.map(transformCommandReply); -} +// export function transformReply(reply: Array): Array { +// return reply.map(transformCommandReply); +// } diff --git a/packages/client/lib/commands/COMMAND_COUNT.ts b/packages/client/lib/commands/COMMAND_COUNT.ts index 34c6a088da6..f1cd06702e8 100644 --- a/packages/client/lib/commands/COMMAND_COUNT.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.ts @@ -1,9 +1,9 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(): RedisCommandArguments { - return ['COMMAND', 'COUNT']; -} +// export function transformArguments(): RedisCommandArguments { +// return ['COMMAND', 'COUNT']; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/COMMAND_GETKEYS.ts b/packages/client/lib/commands/COMMAND_GETKEYS.ts index 6762fe4b58a..fb43798c1b3 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.ts @@ -1,9 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(args: Array): RedisCommandArguments { - return ['COMMAND', 'GETKEYS', ...args]; -} +// export function transformArguments(args: Array): RedisCommandArguments { +// return ['COMMAND', 'GETKEYS', ...args]; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts index 96b28186ccd..d1232d1999e 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts @@ -1,24 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(args: Array): RedisCommandArguments { - return ['COMMAND', 'GETKEYSANDFLAGS', ...args]; -} +// export function transformArguments(args: Array): RedisCommandArguments { +// return ['COMMAND', 'GETKEYSANDFLAGS', ...args]; +// } -type KeysAndFlagsRawReply = Array<[ - RedisCommandArgument, - RedisCommandArguments -]>; +// type KeysAndFlagsRawReply = Array<[ +// RedisCommandArgument, +// RedisCommandArguments +// ]>; -type KeysAndFlagsReply = Array<{ - key: RedisCommandArgument; - flags: RedisCommandArguments; -}>; +// type KeysAndFlagsReply = Array<{ +// key: RedisCommandArgument; +// flags: RedisCommandArguments; +// }>; -export function transformReply(reply: KeysAndFlagsRawReply): KeysAndFlagsReply { - return reply.map(([key, flags]) => ({ - key, - flags - })); -} +// export function transformReply(reply: KeysAndFlagsRawReply): KeysAndFlagsReply { +// return reply.map(([key, flags]) => ({ +// key, +// flags +// })); +// } diff --git a/packages/client/lib/commands/COMMAND_INFO.ts b/packages/client/lib/commands/COMMAND_INFO.ts index 6f84d0edaf9..9de86b3f790 100644 --- a/packages/client/lib/commands/COMMAND_INFO.ts +++ b/packages/client/lib/commands/COMMAND_INFO.ts @@ -1,12 +1,12 @@ -import { RedisCommandArguments } from '.'; -import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers'; +// import { RedisCommandArguments } from '.'; +// import { CommandRawReply, CommandReply, transformCommandReply } from './generic-transformers'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(commands: Array): RedisCommandArguments { - return ['COMMAND', 'INFO', ...commands]; -} +// export function transformArguments(commands: Array): RedisCommandArguments { +// return ['COMMAND', 'INFO', ...commands]; +// } -export function transformReply(reply: Array): Array { - return reply.map(command => command ? transformCommandReply(command) : null); -} +// export function transformReply(reply: Array): Array { +// return reply.map(command => command ? transformCommandReply(command) : null); +// } diff --git a/packages/client/lib/commands/COMMAND_LIST.ts b/packages/client/lib/commands/COMMAND_LIST.ts index a197bd1a4c6..eabf9856dd2 100644 --- a/packages/client/lib/commands/COMMAND_LIST.ts +++ b/packages/client/lib/commands/COMMAND_LIST.ts @@ -1,31 +1,31 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export enum FilterBy { - MODULE = 'MODULE', - ACLCAT = 'ACLCAT', - PATTERN = 'PATTERN' -} +// export enum FilterBy { +// MODULE = 'MODULE', +// ACLCAT = 'ACLCAT', +// PATTERN = 'PATTERN' +// } -interface Filter { - filterBy: FilterBy; - value: string; -} +// interface Filter { +// filterBy: FilterBy; +// value: string; +// } -export function transformArguments(filter?: Filter): RedisCommandArguments { - const args = ['COMMAND', 'LIST']; +// export function transformArguments(filter?: Filter): RedisCommandArguments { +// const args = ['COMMAND', 'LIST']; - if (filter) { - args.push( - 'FILTERBY', - filter.filterBy, - filter.value - ); - } +// if (filter) { +// args.push( +// 'FILTERBY', +// filter.filterBy, +// filter.value +// ); +// } - return args; -} +// return args; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/DEL.ts b/packages/client/lib/commands/DEL.ts index faba0712cdb..a9b10194279 100644 --- a/packages/client/lib/commands/DEL.ts +++ b/packages/client/lib/commands/DEL.ts @@ -1,9 +1,9 @@ -import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, - transformArguments(keys: RedisArgument | Array) { + transformArguments(keys: RedisVariadicArgument) { return pushVariadicArguments(['DEL'], keys); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/EXISTS.ts b/packages/client/lib/commands/EXISTS.ts index 2dfa5963d54..a077943b8d2 100644 --- a/packages/client/lib/commands/EXISTS.ts +++ b/packages/client/lib/commands/EXISTS.ts @@ -1,10 +1,10 @@ -import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(keys: RedisArgument | Array) { + transformArguments(keys: RedisVariadicArgument) { return pushVariadicArguments(['EXISTS'], keys); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/FUNCTION_DELETE.ts b/packages/client/lib/commands/FUNCTION_DELETE.ts index b614c5a9ecf..c0f8794d980 100644 --- a/packages/client/lib/commands/FUNCTION_DELETE.ts +++ b/packages/client/lib/commands/FUNCTION_DELETE.ts @@ -1,8 +1,8 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(library: RedisArgument) { return ['FUNCTION', 'DELETE', library]; }, diff --git a/packages/client/lib/commands/FUNCTION_DUMP.ts b/packages/client/lib/commands/FUNCTION_DUMP.ts index cd53312caf9..8f6ff047fa7 100644 --- a/packages/client/lib/commands/FUNCTION_DUMP.ts +++ b/packages/client/lib/commands/FUNCTION_DUMP.ts @@ -1,8 +1,8 @@ import { BlobStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['FUNCTION', 'DUMP']; }, diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.ts b/packages/client/lib/commands/FUNCTION_FLUSH.ts index b421181bf38..ab238a5eb5e 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.ts @@ -2,8 +2,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { RedisFlushModes } from './FLUSHALL'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(mode?: RedisFlushModes) { const args = ['FUNCTION', 'FLUSH']; diff --git a/packages/client/lib/commands/FUNCTION_KILL.ts b/packages/client/lib/commands/FUNCTION_KILL.ts index 2e89746d593..f452b0b80d9 100644 --- a/packages/client/lib/commands/FUNCTION_KILL.ts +++ b/packages/client/lib/commands/FUNCTION_KILL.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['FUNCTION', 'KILL']; }, diff --git a/packages/client/lib/commands/FUNCTION_LIST.ts b/packages/client/lib/commands/FUNCTION_LIST.ts index d6a39dc726d..c6075139156 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.ts @@ -1,16 +1,16 @@ -import { RedisCommandArguments } from '.'; -import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; +// import { RedisCommandArguments } from '.'; +// import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; -export function transformArguments(pattern?: string): RedisCommandArguments { - const args = ['FUNCTION', 'LIST']; +// export function transformArguments(pattern?: string): RedisCommandArguments { +// const args = ['FUNCTION', 'LIST']; - if (pattern) { - args.push(pattern); - } +// if (pattern) { +// args.push(pattern); +// } - return args; -} +// return args; +// } -export function transformReply(reply: Array): Array { - return reply.map(transformFunctionListItemReply); -} +// export function transformReply(reply: Array): Array { +// return reply.map(transformFunctionListItemReply); +// } diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts index 0d763301e87..41fdae90ad4 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts @@ -1,26 +1,26 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformFunctionListArguments } from './FUNCTION_LIST'; -import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; +// import { RedisCommandArguments } from '.'; +// import { transformArguments as transformFunctionListArguments } from './FUNCTION_LIST'; +// import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; -export function transformArguments(pattern?: string): RedisCommandArguments { - const args = transformFunctionListArguments(pattern); - args.push('WITHCODE'); - return args; -} +// export function transformArguments(pattern?: string): RedisCommandArguments { +// const args = transformFunctionListArguments(pattern); +// args.push('WITHCODE'); +// return args; +// } -type FunctionListWithCodeRawItemReply = [ - ...FunctionListRawItemReply, - 'library_code', - string -]; +// type FunctionListWithCodeRawItemReply = [ +// ...FunctionListRawItemReply, +// 'library_code', +// string +// ]; -interface FunctionListWithCodeItemReply extends FunctionListItemReply { - libraryCode: string; -} +// interface FunctionListWithCodeItemReply extends FunctionListItemReply { +// libraryCode: string; +// } -export function transformReply(reply: Array): Array { - return reply.map(library => ({ - ...transformFunctionListItemReply(library as unknown as FunctionListRawItemReply), - libraryCode: library[7] - })); -} +// export function transformReply(reply: Array): Array { +// return reply.map(library => ({ +// ...transformFunctionListItemReply(library as unknown as FunctionListRawItemReply), +// libraryCode: library[7] +// })); +// } diff --git a/packages/client/lib/commands/FUNCTION_LOAD.ts b/packages/client/lib/commands/FUNCTION_LOAD.ts index 7ab58d58598..c24ee0e9f81 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.ts @@ -1,22 +1,22 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -interface FunctionLoadOptions { - REPLACE?: boolean; -} +// interface FunctionLoadOptions { +// REPLACE?: boolean; +// } -export function transformArguments( - code: string, - options?: FunctionLoadOptions -): RedisCommandArguments { - const args = ['FUNCTION', 'LOAD']; +// export function transformArguments( +// code: string, +// options?: FunctionLoadOptions +// ): RedisCommandArguments { +// const args = ['FUNCTION', 'LOAD']; - if (options?.REPLACE) { - args.push('REPLACE'); - } +// if (options?.REPLACE) { +// args.push('REPLACE'); +// } - args.push(code); +// args.push(code); - return args; -} +// return args; +// } -export declare function transformReply(): string; +// export declare function transformReply(): string; diff --git a/packages/client/lib/commands/FUNCTION_RESTORE.ts b/packages/client/lib/commands/FUNCTION_RESTORE.ts index bc9c41e262d..92f87288c38 100644 --- a/packages/client/lib/commands/FUNCTION_RESTORE.ts +++ b/packages/client/lib/commands/FUNCTION_RESTORE.ts @@ -1,16 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export function transformArguments( - dump: RedisCommandArgument, - mode?: 'FLUSH' | 'APPEND' | 'REPLACE' -): RedisCommandArguments { - const args = ['FUNCTION', 'RESTORE', dump]; +// export function transformArguments( +// dump: RedisCommandArgument, +// mode?: 'FLUSH' | 'APPEND' | 'REPLACE' +// ): RedisCommandArguments { +// const args = ['FUNCTION', 'RESTORE', dump]; - if (mode) { - args.push(mode); - } +// if (mode) { +// args.push(mode); +// } - return args; -} +// return args; +// } -export declare function transformReply(): 'OK'; +// export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/GEOADD.ts b/packages/client/lib/commands/GEOADD.ts index daccb0842e0..2a34b5d5607 100644 --- a/packages/client/lib/commands/GEOADD.ts +++ b/packages/client/lib/commands/GEOADD.ts @@ -1,53 +1,65 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { CommandArguments, RedisArgument, NumberReply, Command } from '../RESP/types'; import { GeoCoordinates } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - interface GeoMember extends GeoCoordinates { - member: RedisCommandArgument; -} - -interface NX { - NX?: true; + member: RedisArgument; } -interface XX { - XX?: true; +interface GeoAddOptions { + condition: 'NX' | 'XX'; + /** + * @deprecated Use `{ condition: 'NX' }` instead. + */ + NX?: boolean; + /** + * @deprecated Use `{ condition: 'XX' }` instead. + */ + XX?: boolean; + CH?: boolean; } -type SetGuards = NX | XX; - -interface GeoAddCommonOptions { - CH?: true; -} - -type GeoAddOptions = SetGuards & GeoAddCommonOptions; - -export function transformArguments( - key: RedisCommandArgument, toAdd: GeoMember | Array, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + toAdd: GeoMember | Array, options?: GeoAddOptions -): RedisCommandArguments { + ) { const args = ['GEOADD', key]; - if ((options as NX)?.NX) { - args.push('NX'); - } else if ((options as XX)?.XX) { - args.push('XX'); + if (options?.condition) { + args.push(options.condition); + } else if (options?.NX) { + args.push('NX'); + } else if (options?.XX) { + args.push('XX'); } if (options?.CH) { - args.push('CH'); + args.push('CH'); } - for (const { longitude, latitude, member } of (Array.isArray(toAdd) ? toAdd : [toAdd])) { - args.push( - longitude.toString(), - latitude.toString(), - member - ); + if (Array.isArray(toAdd)) { + for (const member of toAdd) { + pushMember(args, member); + } + } else { + pushMember(args, toAdd); } return args; -} + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; -export declare function transformReply(): number; +function pushMember( + args: CommandArguments, + { longitude, latitude, member }: GeoMember +) { + args.push( + longitude.toString(), + latitude.toString(), + member + ); +} diff --git a/packages/client/lib/commands/GEODIST.ts b/packages/client/lib/commands/GEODIST.ts index 5dbf8ece9cc..da6dee1b774 100644 --- a/packages/client/lib/commands/GEODIST.ts +++ b/packages/client/lib/commands/GEODIST.ts @@ -1,16 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { GeoUnits } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member1: RedisCommandArgument, - member2: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + member1: RedisArgument, + member2: RedisArgument, unit?: GeoUnits -): RedisCommandArguments { + ) { const args = ['GEODIST', key, member1, member2]; if (unit) { @@ -18,8 +17,8 @@ export function transformArguments( } return args; -} - -export function transformReply(reply: RedisCommandArgument | null): number | null { + }, + transformReply(reply: BlobStringReply | NullReply) { return reply === null ? null : Number(reply); -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOHASH.ts b/packages/client/lib/commands/GEOHASH.ts index 12bc9368ebd..d8d2732e512 100644 --- a/packages/client/lib/commands/GEOHASH.ts +++ b/packages/client/lib/commands/GEOHASH.ts @@ -1,15 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument | Array -): RedisCommandArguments { +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + member: RedisVariadicArgument + ) { return pushVariadicArguments(['GEOHASH', key], member); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOPOS.ts b/packages/client/lib/commands/GEOPOS.ts index c2e0056155b..d9fb5d3a25d 100644 --- a/packages/client/lib/commands/GEOPOS.ts +++ b/packages/client/lib/commands/GEOPOS.ts @@ -1,27 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { ArrayReply, BlobStringReply, NullReply, Command, RedisArgument } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + member: RedisVariadicArgument + ) { return pushVariadicArguments(['GEOPOS', key], member); -} - -type GeoCoordinatesRawReply = Array<[RedisCommandArgument, RedisCommandArgument] | null>; - -interface GeoCoordinates { - longitude: RedisCommandArgument; - latitude: RedisCommandArgument; -} - -export function transformReply(reply: GeoCoordinatesRawReply): Array { - return reply.map(coordinates => coordinates === null ? null : { - longitude: coordinates[0], - latitude: coordinates[1] + }, + transformReply(reply: ArrayReply<[BlobStringReply, BlobStringReply] | NullReply>) { + return reply.map(item => item === null ? null : { + longitude: item[0], + latitude: item[1] }); -} + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS.ts b/packages/client/lib/commands/GEORADIUS.ts index f47cf508848..4b5af7a078e 100644 --- a/packages/client/lib/commands/GEORADIUS.ts +++ b/packages/client/lib/commands/GEORADIUS.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - coordinates: GeoCoordinates, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): RedisCommandArguments { - return pushGeoRadiusArguments( - ['GEORADIUS'], - key, - coordinates, - radius, - unit, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// coordinates: GeoCoordinates, +// radius: number, +// unit: GeoUnits, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// return pushGeoRadiusArguments( +// ['GEORADIUS'], +// key, +// coordinates, +// radius, +// unit, +// options +// ); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts index 96bb622fb85..ab6950ac8db 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - member: string, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): RedisCommandArguments { - return pushGeoRadiusArguments( - ['GEORADIUSBYMEMBER'], - key, - member, - radius, - unit, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// member: string, +// radius: number, +// unit: GeoUnits, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// return pushGeoRadiusArguments( +// ['GEORADIUSBYMEMBER'], +// key, +// member, +// radius, +// unit, +// options +// ); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts index 28f3c25fac9..ea1674cf3fc 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; -export function transformArguments( - key: RedisCommandArgument, - member: string, - radius: number, - unit: GeoUnits, - destination: RedisCommandArgument, - options?: GeoRadiusStoreOptions, -): RedisCommandArguments { - return pushGeoRadiusStoreArguments( - ['GEORADIUSBYMEMBER'], - key, - member, - radius, - unit, - destination, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// member: string, +// radius: number, +// unit: GeoUnits, +// destination: RedisCommandArgument, +// options?: GeoRadiusStoreOptions, +// ): RedisCommandArguments { +// return pushGeoRadiusStoreArguments( +// ['GEORADIUSBYMEMBER'], +// key, +// member, +// radius, +// unit, +// destination, +// options +// ); +// } -export declare function transformReply(): number +// export declare function transformReply(): number diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts index 63f29ae65b5..1ad9450ae38 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - member: string, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): RedisCommandArguments { - return pushGeoRadiusArguments( - ['GEORADIUSBYMEMBER_RO'], - key, - member, - radius, - unit, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// member: string, +// radius: number, +// unit: GeoUnits, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// return pushGeoRadiusArguments( +// ['GEORADIUSBYMEMBER_RO'], +// key, +// member, +// radius, +// unit, +// options +// ); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts index 6061be734b5..116bb9200fa 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -import { transformArguments as geoRadiusTransformArguments } from './GEORADIUSBYMEMBER_RO'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; +// import { transformArguments as geoRadiusTransformArguments } from './GEORADIUSBYMEMBER_RO'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER_RO'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER_RO'; -export function transformArguments( - key: RedisCommandArgument, - member: string, - radius: number, - unit: GeoUnits, - replyWith: Array, - options?: GeoSearchOptions -): RedisCommandArguments { - const args: RedisCommandArguments = geoRadiusTransformArguments( - key, - member, - radius, - unit, - options - ); +// export function transformArguments( +// key: RedisCommandArgument, +// member: string, +// radius: number, +// unit: GeoUnits, +// replyWith: Array, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = geoRadiusTransformArguments( +// key, +// member, +// radius, +// unit, +// options +// ); - args.push(...replyWith); +// args.push(...replyWith); - args.preserve = replyWith; +// args.preserve = replyWith; - return args; -} +// return args; +// } -export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts index 7d7dbe06a54..09bb5bbbb44 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -import { transformArguments as transformGeoRadiusArguments } from './GEORADIUSBYMEMBER'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; +// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUSBYMEMBER'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; -export function transformArguments( - key: RedisCommandArgument, - member: string, - radius: number, - unit: GeoUnits, - replyWith: Array, - options?: GeoSearchOptions -): RedisCommandArguments { - const args: RedisCommandArguments = transformGeoRadiusArguments( - key, - member, - radius, - unit, - options - ); +// export function transformArguments( +// key: RedisCommandArgument, +// member: string, +// radius: number, +// unit: GeoUnits, +// replyWith: Array, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = transformGeoRadiusArguments( +// key, +// member, +// radius, +// unit, +// options +// ); - args.push(...replyWith); +// args.push(...replyWith); - args.preserve = replyWith; +// args.preserve = replyWith; - return args; -} +// return args; +// } -export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/GEORADIUSSTORE.ts b/packages/client/lib/commands/GEORADIUSSTORE.ts index ad2317aa3af..03445259648 100644 --- a/packages/client/lib/commands/GEORADIUSSTORE.ts +++ b/packages/client/lib/commands/GEORADIUSSTORE.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoCoordinates, GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoCoordinates, GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; -export function transformArguments( - key: RedisCommandArgument, - coordinates: GeoCoordinates, - radius: number, - unit: GeoUnits, - destination: RedisCommandArgument, - options?: GeoRadiusStoreOptions, -): RedisCommandArguments { - return pushGeoRadiusStoreArguments( - ['GEORADIUS'], - key, - coordinates, - radius, - unit, - destination, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// coordinates: GeoCoordinates, +// radius: number, +// unit: GeoUnits, +// destination: RedisCommandArgument, +// options?: GeoRadiusStoreOptions, +// ): RedisCommandArguments { +// return pushGeoRadiusStoreArguments( +// ['GEORADIUS'], +// key, +// coordinates, +// radius, +// unit, +// destination, +// options +// ); +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/GEORADIUS_RO.ts b/packages/client/lib/commands/GEORADIUS_RO.ts index ac378a5150b..d9c01007ed9 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - coordinates: GeoCoordinates, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): RedisCommandArguments { - return pushGeoRadiusArguments( - ['GEORADIUS_RO'], - key, - coordinates, - radius, - unit, - options - ); -} +// export function transformArguments( +// key: RedisCommandArgument, +// coordinates: GeoCoordinates, +// radius: number, +// unit: GeoUnits, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// return pushGeoRadiusArguments( +// ['GEORADIUS_RO'], +// key, +// coordinates, +// radius, +// unit, +// options +// ); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts index 424e5fcd998..156f5cfa9f4 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -import { transformArguments as transformGeoRadiusRoArguments } from './GEORADIUS_RO'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; +// import { transformArguments as transformGeoRadiusRoArguments } from './GEORADIUS_RO'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS_RO'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS_RO'; -export function transformArguments( - key: RedisCommandArgument, - coordinates: GeoCoordinates, - radius: number, - unit: GeoUnits, - replyWith: Array, - options?: GeoSearchOptions -): RedisCommandArguments { - const args: RedisCommandArguments = transformGeoRadiusRoArguments( - key, - coordinates, - radius, - unit, - options - ); +// export function transformArguments( +// key: RedisCommandArgument, +// coordinates: GeoCoordinates, +// radius: number, +// unit: GeoUnits, +// replyWith: Array, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = transformGeoRadiusRoArguments( +// key, +// coordinates, +// radius, +// unit, +// options +// ); - args.push(...replyWith); +// args.push(...replyWith); - args.preserve = replyWith; +// args.preserve = replyWith; - return args; -} +// return args; +// } -export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/GEORADIUS_WITH.ts b/packages/client/lib/commands/GEORADIUS_WITH.ts index dc3f4288f01..d41132ce2d6 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -import { transformArguments as transformGeoRadiusArguments } from './GEORADIUS'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; +// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUS'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; -export function transformArguments( - key: RedisCommandArgument, - coordinates: GeoCoordinates, - radius: number, - unit: GeoUnits, - replyWith: Array, - options?: GeoSearchOptions -): RedisCommandArguments { - const args: RedisCommandArguments = transformGeoRadiusArguments( - key, - coordinates, - radius, - unit, - options - ); +// export function transformArguments( +// key: RedisCommandArgument, +// coordinates: GeoCoordinates, +// radius: number, +// unit: GeoUnits, +// replyWith: Array, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = transformGeoRadiusArguments( +// key, +// coordinates, +// radius, +// unit, +// options +// ); - args.push(...replyWith); +// args.push(...replyWith); - args.preserve = replyWith; +// args.preserve = replyWith; - return args; -} +// return args; +// } -export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/GEOSEARCH.ts b/packages/client/lib/commands/GEOSEARCH.ts index a02a21391f6..31a65ee8dce 100644 --- a/packages/client/lib/commands/GEOSEARCH.ts +++ b/packages/client/lib/commands/GEOSEARCH.ts @@ -1,17 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - from: GeoSearchFrom, - by: GeoSearchBy, - options?: GeoSearchOptions -): RedisCommandArguments { - return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); -} +// export function transformArguments( +// key: RedisCommandArgument, +// from: GeoSearchFrom, +// by: GeoSearchBy, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.ts b/packages/client/lib/commands/GEOSEARCHSTORE.ts index 7a91450cd9e..a8cdb82d71b 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.ts @@ -1,38 +1,38 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; -interface GeoSearchStoreOptions extends GeoSearchOptions { - STOREDIST?: true; -} +// interface GeoSearchStoreOptions extends GeoSearchOptions { +// STOREDIST?: true; +// } -export function transformArguments( - destination: RedisCommandArgument, - source: RedisCommandArgument, - from: GeoSearchFrom, - by: GeoSearchBy, - options?: GeoSearchStoreOptions -): RedisCommandArguments { - const args = pushGeoSearchArguments( - ['GEOSEARCHSTORE', destination], - source, - from, - by, - options - ); +// export function transformArguments( +// destination: RedisCommandArgument, +// source: RedisCommandArgument, +// from: GeoSearchFrom, +// by: GeoSearchBy, +// options?: GeoSearchStoreOptions +// ): RedisCommandArguments { +// const args = pushGeoSearchArguments( +// ['GEOSEARCHSTORE', destination], +// source, +// from, +// by, +// options +// ); - if (options?.STOREDIST) { - args.push('STOREDIST'); - } +// if (options?.STOREDIST) { +// args.push('STOREDIST'); +// } - return args; -} +// return args; +// } -export function transformReply(reply: number): number { - if (typeof reply !== 'number') { - throw new TypeError(`https://github.com/redis/redis/issues/9261`); - } +// export function transformReply(reply: number): number { +// if (typeof reply !== 'number') { +// throw new TypeError(`https://github.com/redis/redis/issues/9261`); +// } - return reply; -} +// return reply; +// } diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts index d7a5f456a94..e706b08b9e8 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.ts @@ -1,23 +1,23 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions } from './generic-transformers'; -import { transformArguments as geoSearchTransformArguments } from './GEOSEARCH'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions } from './generic-transformers'; +// import { transformArguments as geoSearchTransformArguments } from './GEOSEARCH'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; -export function transformArguments( - key: RedisCommandArgument, - from: GeoSearchFrom, - by: GeoSearchBy, - replyWith: Array, - options?: GeoSearchOptions -): RedisCommandArguments { - const args: RedisCommandArguments = geoSearchTransformArguments(key, from, by, options); +// export function transformArguments( +// key: RedisCommandArgument, +// from: GeoSearchFrom, +// by: GeoSearchBy, +// replyWith: Array, +// options?: GeoSearchOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = geoSearchTransformArguments(key, from, by, options); - args.push(...replyWith); +// args.push(...replyWith); - args.preserve = replyWith; +// args.preserve = replyWith; - return args; -} +// return args; +// } -export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/GETBIT.ts b/packages/client/lib/commands/GETBIT.ts index 67f67f39b19..d8ece8f523a 100644 --- a/packages/client/lib/commands/GETBIT.ts +++ b/packages/client/lib/commands/GETBIT.ts @@ -1,15 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; import { BitValue } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - offset: number -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, offset: number) { return ['GETBIT', key, offset.toString()]; -} - -export declare function transformReply(): BitValue; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/HSCAN.ts b/packages/client/lib/commands/HSCAN.ts index a23063e34f8..2391424eb21 100644 --- a/packages/client/lib/commands/HSCAN.ts +++ b/packages/client/lib/commands/HSCAN.ts @@ -1,5 +1,5 @@ import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -import { ScanOptions, pushScanArguments } from './generic-transformers'; +import { ScanCommonOptions, pushScanArguments } from './SCAN'; export interface HScanEntry { field: BlobStringReply; @@ -12,7 +12,7 @@ export default { transformArguments( key: RedisArgument, cursor: number, - options?: ScanOptions + options?: ScanCommonOptions ) { return pushScanArguments(['HSCAN', key], cursor, options); }, diff --git a/packages/client/lib/commands/LATENCY_GRAPH.ts b/packages/client/lib/commands/LATENCY_GRAPH.ts index e4e078b90f2..a789a79075a 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.ts @@ -1,25 +1,25 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export type EventType = - 'active-defrag-cycle' - | 'aof-fsync-always' - | 'aof-stat' - | 'aof-rewrite-diff-write' - | 'aof-rename' - | 'aof-write' - | 'aof-write-active-child' - | 'aof-write-alone' - | 'aof-write-pending-fsync' - | 'command' - | 'expire-cycle' - | 'eviction-cycle' - | 'eviction-del' - | 'fast-command' - | 'fork' - | 'rdb-unlink-temp-file'; +// export type EventType = +// 'active-defrag-cycle' +// | 'aof-fsync-always' +// | 'aof-stat' +// | 'aof-rewrite-diff-write' +// | 'aof-rename' +// | 'aof-write' +// | 'aof-write-active-child' +// | 'aof-write-alone' +// | 'aof-write-pending-fsync' +// | 'command' +// | 'expire-cycle' +// | 'eviction-cycle' +// | 'eviction-del' +// | 'fast-command' +// | 'fork' +// | 'rdb-unlink-temp-file'; -export function transformArguments(event: EventType): RedisCommandArguments { - return ['LATENCY', 'GRAPH', event]; -} +// export function transformArguments(event: EventType): RedisCommandArguments { +// return ['LATENCY', 'GRAPH', event]; +// } -export declare function transformReply(): string; +// export declare function transformReply(): string; diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts index d52245251b4..5cefc296302 100644 --- a/packages/client/lib/commands/LMPOP.ts +++ b/packages/client/lib/commands/LMPOP.ts @@ -1,10 +1,10 @@ -import { RedisArgument, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; -import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; +import { NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; +import { transformLMPopArguments, LMPopOptions, ListSide, RedisVariadicArgument } from './generic-transformers'; export default { FIRST_KEY_INDEX: 2, transformArguments( - keys: RedisArgument | Array, + keys: RedisVariadicArgument, side: ListSide, options?: LMPopOptions ) { diff --git a/packages/client/lib/commands/LOLWUT.ts b/packages/client/lib/commands/LOLWUT.ts index 8536711d322..7a6c8329d69 100644 --- a/packages/client/lib/commands/LOLWUT.ts +++ b/packages/client/lib/commands/LOLWUT.ts @@ -1,8 +1,8 @@ import { BlobStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(version?: number, ...optionalArguments: Array) { const args = ['LOLWUT']; diff --git a/packages/client/lib/commands/LPOP_COUNT.ts b/packages/client/lib/commands/LPOP_COUNT.ts index 6cbc8564abb..a1536e78dcb 100644 --- a/packages/client/lib/commands/LPOP_COUNT.ts +++ b/packages/client/lib/commands/LPOP_COUNT.ts @@ -1,8 +1,8 @@ import { RedisArgument, NullReply, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: false, FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, transformArguments(key: RedisArgument, count: number) { return ['LPOP', key, count.toString()]; }, diff --git a/packages/client/lib/commands/LPUSH.ts b/packages/client/lib/commands/LPUSH.ts index 72d4d7b6768..714db2ae9a9 100644 --- a/packages/client/lib/commands/LPUSH.ts +++ b/packages/client/lib/commands/LPUSH.ts @@ -1,9 +1,9 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, - transformArguments(key: RedisArgument, elements: RedisArgument | Array) { + transformArguments(key: RedisArgument, elements: RedisVariadicArgument) { return pushVariadicArguments(['LPUSH', key], elements); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/LPUSHX.ts b/packages/client/lib/commands/LPUSHX.ts index 1265c56a262..d6dceda6d02 100644 --- a/packages/client/lib/commands/LPUSHX.ts +++ b/packages/client/lib/commands/LPUSHX.ts @@ -1,9 +1,9 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, - transformArguments(key: RedisArgument, elements: RedisArgument | Array) { + transformArguments(key: RedisArgument, elements: RedisVariadicArgument) { return pushVariadicArguments(['LPUSHX', key], elements); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/MODULE_LIST.ts b/packages/client/lib/commands/MODULE_LIST.ts index 56a61095282..5ab297faecc 100644 --- a/packages/client/lib/commands/MODULE_LIST.ts +++ b/packages/client/lib/commands/MODULE_LIST.ts @@ -6,8 +6,8 @@ export type ModuleListReply = ArrayReply>; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['MODULE', 'LIST']; }, diff --git a/packages/client/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts index ed0520adf48..3fab206eeff 100644 --- a/packages/client/lib/commands/MODULE_LOAD.ts +++ b/packages/client/lib/commands/MODULE_LOAD.ts @@ -2,10 +2,16 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { pushVariadicArguments } from './generic-transformers'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(path: RedisArgument, moduleArguments?: Array) { - return pushVariadicArguments(['MODULE', 'LOAD', path], moduleArguments); + const args = ['MODULE', 'LOAD', path]; + + if (moduleArguments) { + return args.concat(moduleArguments); + } + + return args; }, transformReply: undefined as unknown as () => SimpleStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_UNLOAD.ts b/packages/client/lib/commands/MODULE_UNLOAD.ts index 4f47abbdead..8d1e64800a9 100644 --- a/packages/client/lib/commands/MODULE_UNLOAD.ts +++ b/packages/client/lib/commands/MODULE_UNLOAD.ts @@ -1,8 +1,8 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(name: RedisArgument) { return ['MODULE', 'UNLOAD', name]; }, diff --git a/packages/client/lib/commands/PFADD.ts b/packages/client/lib/commands/PFADD.ts index bdde0648f35..41bf2adfe5e 100644 --- a/packages/client/lib/commands/PFADD.ts +++ b/packages/client/lib/commands/PFADD.ts @@ -1,11 +1,14 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(key: RedisArgument, element?: RedisArgument | Array) { - return pushVariadicArguments(['PFADD', key], element); + transformArguments(key: RedisArgument, element?: RedisVariadicArgument) { + const args = ['PFADD', key]; + if (!element) return args; + + return pushVariadicArguments(args, element); }, transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/client/lib/commands/PFCOUNT.ts b/packages/client/lib/commands/PFCOUNT.ts index d2370d32283..5b46eb00d92 100644 --- a/packages/client/lib/commands/PFCOUNT.ts +++ b/packages/client/lib/commands/PFCOUNT.ts @@ -1,10 +1,10 @@ -import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(key?: RedisArgument | Array) { + transformArguments(key: RedisVariadicArgument) { return pushVariadicArguments(['PFCOUNT'], key); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/PFMERGE.ts b/packages/client/lib/commands/PFMERGE.ts index 5735e51bba6..eeeeb5173db 100644 --- a/packages/client/lib/commands/PFMERGE.ts +++ b/packages/client/lib/commands/PFMERGE.ts @@ -1,13 +1,16 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, transformArguments( destination: RedisArgument, - source?: RedisArgument | Array + source?: RedisVariadicArgument ) { - return pushVariadicArguments(['PFMERGE', destination], source); + const args = ['PFMERGE', destination]; + if (!source) return args; + + return pushVariadicArguments(args, source); }, transformReply: undefined as unknown as () => SimpleStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/PUBLISH.ts b/packages/client/lib/commands/PUBLISH.ts index 1038dea52fd..1566651d9f1 100644 --- a/packages/client/lib/commands/PUBLISH.ts +++ b/packages/client/lib/commands/PUBLISH.ts @@ -1,8 +1,8 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(channel: RedisArgument, message: RedisArgument) { return ['PUBLISH', channel, message]; }, diff --git a/packages/client/lib/commands/PUBSUB_CHANNELS.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.ts index c828ebefce9..4bf7abd75dc 100644 --- a/packages/client/lib/commands/PUBSUB_CHANNELS.ts +++ b/packages/client/lib/commands/PUBSUB_CHANNELS.ts @@ -1,8 +1,8 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(pattern?: RedisArgument) { const args: Array = ['PUBSUB', 'CHANNELS']; diff --git a/packages/client/lib/commands/PUBSUB_NUMPAT.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.ts index b800b719dc1..e8a0738dc72 100644 --- a/packages/client/lib/commands/PUBSUB_NUMPAT.ts +++ b/packages/client/lib/commands/PUBSUB_NUMPAT.ts @@ -1,8 +1,8 @@ import { NumberReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['PUBSUB', 'NUMPAT']; }, diff --git a/packages/client/lib/commands/PUBSUB_NUMSUB.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.ts index f0da89069d1..aaa6cf749c0 100644 --- a/packages/client/lib/commands/PUBSUB_NUMSUB.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.ts @@ -1,10 +1,10 @@ -import { RedisArgument, ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, - transformArguments(channels?: RedisArgument | Array) { + IS_READ_ONLY: true, + transformArguments(channels?: RedisVariadicArgument) { const args = ['PUBSUB', 'NUMSUB']; if (channels) return pushVariadicArguments(args, channels); diff --git a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts index 8acf29c15b4..1403d67fa22 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts @@ -1,8 +1,8 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(pattern?: RedisArgument) { const args: Array = ['PUBSUB', 'bb']; diff --git a/packages/client/lib/commands/READONLY.ts b/packages/client/lib/commands/READONLY.ts index 094ff1cc02c..bb15834550e 100644 --- a/packages/client/lib/commands/READONLY.ts +++ b/packages/client/lib/commands/READONLY.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['READONLY']; }, diff --git a/packages/client/lib/commands/READWRITE.ts b/packages/client/lib/commands/READWRITE.ts index b370ec74170..fe70e15d4c8 100644 --- a/packages/client/lib/commands/READWRITE.ts +++ b/packages/client/lib/commands/READWRITE.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['READWRITE']; }, diff --git a/packages/client/lib/commands/REPLICAOF.ts b/packages/client/lib/commands/REPLICAOF.ts index 4024e94bc49..4e2f69f7265 100644 --- a/packages/client/lib/commands/REPLICAOF.ts +++ b/packages/client/lib/commands/REPLICAOF.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(host: string, port: number) { return ['REPLICAOF', host, port.toString()]; }, diff --git a/packages/client/lib/commands/RESTORE-ASKING.ts b/packages/client/lib/commands/RESTORE-ASKING.ts index f9cb75ab3c5..14f6dcbeab3 100644 --- a/packages/client/lib/commands/RESTORE-ASKING.ts +++ b/packages/client/lib/commands/RESTORE-ASKING.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['RESTORE-ASKING']; }, diff --git a/packages/client/lib/commands/ROLE.ts b/packages/client/lib/commands/ROLE.ts index 49196cb279d..2cab0a783ed 100644 --- a/packages/client/lib/commands/ROLE.ts +++ b/packages/client/lib/commands/ROLE.ts @@ -22,8 +22,8 @@ type SentinelRole = [ type Role = MasterRole | SlaveRole | SentinelRole; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['ROLE']; }, diff --git a/packages/client/lib/commands/SAVE.ts b/packages/client/lib/commands/SAVE.ts index 53cb2486965..ee6cccd35a0 100644 --- a/packages/client/lib/commands/SAVE.ts +++ b/packages/client/lib/commands/SAVE.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['SAVE']; }, diff --git a/packages/client/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts index 7657b744e02..b2c10af0af1 100644 --- a/packages/client/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -1,84 +1,62 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './SCAN'; +import SCAN from './SCAN'; describe('SCAN', () => { - describe('transformArguments', () => { - it('cusror only', () => { - assert.deepEqual( - transformArguments(0), - ['SCAN', '0'] - ); - }); - - it('with MATCH', () => { - assert.deepEqual( - transformArguments(0, { - MATCH: 'pattern' - }), - ['SCAN', '0', 'MATCH', 'pattern'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments(0, { - COUNT: 1 - }), - ['SCAN', '0', 'COUNT', '1'] - ); - }); - - it('with TYPE', () => { - assert.deepEqual( - transformArguments(0, { - TYPE: 'stream' - }), - ['SCAN', '0', 'TYPE', 'stream'] - ); - }); + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + SCAN.transformArguments(0), + ['SCAN', '0'] + ); + }); - it('with MATCH & COUNT & TYPE', () => { - assert.deepEqual( - transformArguments(0, { - MATCH: 'pattern', - COUNT: 1, - TYPE: 'stream' - }), - ['SCAN', '0', 'MATCH', 'pattern', 'COUNT', '1', 'TYPE', 'stream'] - ); - }); + it('with MATCH', () => { + assert.deepEqual( + SCAN.transformArguments(0, { + MATCH: 'pattern' + }), + ['SCAN', '0', 'MATCH', 'pattern'] + ); }); - describe('transformReply', () => { - it('without keys', () => { - assert.deepEqual( - transformReply(['0', []]), - { - cursor: 0, - keys: [] - } - ); - }); + it('with COUNT', () => { + assert.deepEqual( + SCAN.transformArguments(0, { + COUNT: 1 + }), + ['SCAN', '0', 'COUNT', '1'] + ); + }); - it('with keys', () => { - assert.deepEqual( - transformReply(['0', ['key']]), - { - cursor: 0, - keys: ['key'] - } - ); - }); + it('with TYPE', () => { + assert.deepEqual( + SCAN.transformArguments(0, { + TYPE: 'stream' + }), + ['SCAN', '0', 'TYPE', 'stream'] + ); }); - testUtils.testWithClient('client.scan', async client => { - assert.deepEqual( - await client.scan(0), - { - cursor: 0, - keys: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + it('with MATCH & COUNT & TYPE', () => { + assert.deepEqual( + SCAN.transformArguments(0, { + MATCH: 'pattern', + COUNT: 1, + TYPE: 'stream' + }), + ['SCAN', '0', 'MATCH', 'pattern', 'COUNT', '1', 'TYPE', 'stream'] + ); + }); + }); + + testUtils.testWithClient('client.scan', async client => { + assert.deepEqual( + await client.scan(0), + { + cursor: 0, + keys: [] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index b1660ddbbcd..710a7b09be2 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -1,13 +1,35 @@ -import { RedisArgument, BlobStringReply, ArrayReply, Command } from '../RESP/types'; -import { ScanOptions, pushScanArguments } from './generic-transformers'; +import { CommandArguments, RedisArgument, BlobStringReply, ArrayReply, Command } from '../RESP/types'; -export interface ScanCommandOptions extends ScanOptions { +export interface ScanCommonOptions { + MATCH?: string; + COUNT?: number; +} + +export function pushScanArguments( + args: CommandArguments, + cursor: number, + options?: ScanOptions +): CommandArguments { + args.push(cursor.toString()); + + if (options?.MATCH) { + args.push('MATCH', options.MATCH); + } + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} + +export interface ScanOptions extends ScanCommonOptions { TYPE?: RedisArgument; } export default { IS_READ_ONLY: true, - transformArguments(cursor: number, options?: ScanCommandOptions) { + transformArguments(cursor: number, options?: ScanOptions) { const args = pushScanArguments(['SCAN'], cursor, options); if (options?.TYPE) { diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.ts b/packages/client/lib/commands/SCRIPT_DEBUG.ts index 8c0021382df..b4bc1cfa8e0 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(mode: 'YES' | 'SYNC' | 'NO') { return ['SCRIPT', 'DEBUG', mode]; }, diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts index 4233f7dc223..ab0a293d8de 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.ts @@ -1,10 +1,10 @@ -import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { ArrayReply, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, - transformArguments(sha1: RedisArgument | Array) { + IS_READ_ONLY: true, + transformArguments(sha1: RedisVariadicArgument) { return pushVariadicArguments(['SCRIPT', 'EXISTS'], sha1); }, transformReply: undefined as unknown as () => ArrayReply diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.ts b/packages/client/lib/commands/SCRIPT_FLUSH.ts index a6bfe7648cb..6a224cdaa85 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(mode?: 'ASYNC' | 'SYNC') { const args = ['SCRIPT', 'FLUSH']; diff --git a/packages/client/lib/commands/SCRIPT_KILL.ts b/packages/client/lib/commands/SCRIPT_KILL.ts index 96aa119b01f..973bf51660d 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.ts @@ -1,8 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['SCRIPT', 'KILL']; }, diff --git a/packages/client/lib/commands/SCRIPT_LOAD.ts b/packages/client/lib/commands/SCRIPT_LOAD.ts index 758a6835ac9..90028b13a5f 100644 --- a/packages/client/lib/commands/SCRIPT_LOAD.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.ts @@ -1,8 +1,8 @@ import { BlobStringReply, Command, RedisArgument } from '../RESP/types'; export default { - IS_READ_ONLY: true, FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(script: RedisArgument) { return ['SCRIPT', 'LOAD', script]; }, diff --git a/packages/client/lib/commands/SETBIT.ts b/packages/client/lib/commands/SETBIT.ts index 20c69155b05..5b3ec6173dc 100644 --- a/packages/client/lib/commands/SETBIT.ts +++ b/packages/client/lib/commands/SETBIT.ts @@ -2,8 +2,8 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { BitValue } from './generic-transformers'; export default { - IS_READ_ONLY: false, FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, transformArguments( key: RedisArgument, offset: number, diff --git a/packages/client/lib/commands/SINTERSTORE.ts b/packages/client/lib/commands/SINTERSTORE.ts index 8ab9c0065e6..744e0b18456 100644 --- a/packages/client/lib/commands/SINTERSTORE.ts +++ b/packages/client/lib/commands/SINTERSTORE.ts @@ -1,13 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - destination: RedisCommandArgument, - keys: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + keys: RedisVariadicArgument + ) { return pushVariadicArguments(['SINTERSTORE', destination], keys); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SISMEMBER.ts b/packages/client/lib/commands/SISMEMBER.ts index 4d40c63250e..0687d19de30 100644 --- a/packages/client/lib/commands/SISMEMBER.ts +++ b/packages/client/lib/commands/SISMEMBER.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, member: RedisArgument) { return ['SISMEMBER', key, member]; -} - -export { transformBooleanReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SMISMEMBER.ts b/packages/client/lib/commands/SMISMEMBER.ts index 175120bdfb9..bdf48d45ab4 100644 --- a/packages/client/lib/commands/SMISMEMBER.ts +++ b/packages/client/lib/commands/SMISMEMBER.ts @@ -1,12 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - members: Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, members: Array) { return ['SMISMEMBER', key, ...members]; -} - -export { transformBooleanArrayReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SMOVE.ts b/packages/client/lib/commands/SMOVE.ts index 83c4027dbd5..d6759c62122 100644 --- a/packages/client/lib/commands/SMOVE.ts +++ b/packages/client/lib/commands/SMOVE.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - source: RedisCommandArgument, - destination: RedisCommandArgument, - member: RedisCommandArgument -): RedisCommandArguments { - return ['SMOVE', source, destination, member]; -} +// export function transformArguments( +// source: RedisCommandArgument, +// destination: RedisCommandArgument, +// member: RedisCommandArgument +// ): RedisCommandArguments { +// return ['SMOVE', source, destination, member]; +// } -export { transformBooleanReply as transformReply } from './generic-transformers'; +// export { transformBooleanReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/SORT.ts b/packages/client/lib/commands/SORT.ts index 15e95bde677..e04466cdf67 100644 --- a/packages/client/lib/commands/SORT.ts +++ b/packages/client/lib/commands/SORT.ts @@ -1,13 +1,59 @@ -import { RedisCommandArguments } from '.'; -import { pushSortArguments, SortOptions } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; +export interface SortOptions { + BY?: string; + LIMIT?: { + offset: number; + count: number; + }, + GET?: string | Array; + DIRECTION?: 'ASC' | 'DESC'; + ALPHA?: true; +} + +export function transformSortArguments( + command: RedisArgument, + options?: SortOptions +) { + const args = [command]; + + if (options?.BY) { + args.push('BY', options.BY); + } + + if (options?.LIMIT) { + args.push( + 'LIMIT', + options.LIMIT.offset.toString(), + options.LIMIT.count.toString() + ); + } -export function transformArguments( - key: string, - options?: SortOptions -): RedisCommandArguments { - return pushSortArguments(['SORT', key], options); + if (options?.GET) { + if (typeof options.GET === 'string') { + args.push('GET', options.GET); + } else { + for (const pattern of options.GET) { + args.push('GET', pattern); + } + } + } + + if (options?.DIRECTION) { + args.push(options.DIRECTION); + } + + if (options?.ALPHA) { + args.push('ALPHA'); + } + + return args; } -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: transformSortArguments.bind(undefined, 'SORT'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; + diff --git a/packages/client/lib/commands/SORT_RO.ts b/packages/client/lib/commands/SORT_RO.ts index 4af7acd80d7..459a0bbc03d 100644 --- a/packages/client/lib/commands/SORT_RO.ts +++ b/packages/client/lib/commands/SORT_RO.ts @@ -1,15 +1,9 @@ -import { RedisCommandArguments } from '.'; -import { pushSortArguments, SortOptions } from "./generic-transformers"; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - options?: SortOptions -): RedisCommandArguments { - return pushSortArguments(['SORT_RO', key], options); -} - -export declare function transformReply(): Array; +import { Command } from '../RESP/types'; +import SORT, { transformSortArguments } from './SORT'; + +export default { + FIRST_KEY_INDEX: SORT.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformSortArguments.bind(undefined, 'SORT_RO'), + transformReply: SORT.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SORT_STORE.ts b/packages/client/lib/commands/SORT_STORE.ts index 9acaf023175..5af19d50cba 100644 --- a/packages/client/lib/commands/SORT_STORE.ts +++ b/packages/client/lib/commands/SORT_STORE.ts @@ -1,17 +1,17 @@ -import { RedisCommandArguments } from '.'; -import { SortOptions } from './generic-transformers'; -import { transformArguments as transformSortArguments } from './SORT'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { SortOptions, transformSortArguments } from './SORT'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - source: string, - destination: string, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + source: RedisArgument, + destination: RedisArgument, options?: SortOptions -): RedisCommandArguments { + ) { const args = transformSortArguments(source, options); args.push('STORE', destination); return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SPOP.ts b/packages/client/lib/commands/SPOP.ts index 38ce8573f3f..3566cd13dc5 100644 --- a/packages/client/lib/commands/SPOP.ts +++ b/packages/client/lib/commands/SPOP.ts @@ -1,18 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - count?: number -): RedisCommandArguments { - const args = ['SPOP', key]; +// export function transformArguments( +// key: RedisCommandArgument, +// count?: number +// ): RedisCommandArguments { +// const args = ['SPOP', key]; - if (typeof count === 'number') { - args.push(count.toString()); - } +// if (typeof count === 'number') { +// args.push(count.toString()); +// } - return args; -} +// return args; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SPUBLISH.ts b/packages/client/lib/commands/SPUBLISH.ts index 42a7ab49072..19d84b03c6f 100644 --- a/packages/client/lib/commands/SPUBLISH.ts +++ b/packages/client/lib/commands/SPUBLISH.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const IS_READ_ONLY = true; - -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - channel: RedisCommandArgument, - message: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(channel: RedisArgument, message: RedisArgument) { return ['SPUBLISH', channel, message]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SRANDMEMBER.ts b/packages/client/lib/commands/SRANDMEMBER.ts index d84e61993e5..6a2373ae927 100644 --- a/packages/client/lib/commands/SRANDMEMBER.ts +++ b/packages/client/lib/commands/SRANDMEMBER.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['SRANDMEMBER', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SRANDMEMBER_COUNT.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.ts index d265d89e9a6..54c3e96f238 100644 --- a/packages/client/lib/commands/SRANDMEMBER_COUNT.ts +++ b/packages/client/lib/commands/SRANDMEMBER_COUNT.ts @@ -1,16 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformSRandMemberArguments } from './SRANDMEMBER'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformArguments as transformSRandMemberArguments } from './SRANDMEMBER'; -export { FIRST_KEY_INDEX } from './SRANDMEMBER'; +// export { FIRST_KEY_INDEX } from './SRANDMEMBER'; -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformSRandMemberArguments(key), - count.toString() - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// count: number +// ): RedisCommandArguments { +// return [ +// ...transformSRandMemberArguments(key), +// count.toString() +// ]; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SREM.ts b/packages/client/lib/commands/SREM.ts index f08e147dd84..daa95493d02 100644 --- a/packages/client/lib/commands/SREM.ts +++ b/packages/client/lib/commands/SREM.ts @@ -1,13 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - members: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, members: RedisVariadicArgument) { return pushVariadicArguments(['SREM', key], members); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SSCAN.ts b/packages/client/lib/commands/SSCAN.ts index fe648bff5ea..c36bc52ca1e 100644 --- a/packages/client/lib/commands/SSCAN.ts +++ b/packages/client/lib/commands/SSCAN.ts @@ -1,5 +1,5 @@ import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -import { ScanOptions, pushScanArguments } from './generic-transformers'; +import { ScanCommonOptions, pushScanArguments } from './SCAN'; export default { FIRST_KEY_INDEX: 1, @@ -7,7 +7,7 @@ export default { transformArguments( key: RedisArgument, cursor: number, - options?: ScanOptions + options?: ScanCommonOptions ) { return pushScanArguments(['SSCAN', key], cursor, options); }, diff --git a/packages/client/lib/commands/SUNION.ts b/packages/client/lib/commands/SUNION.ts index 97d8b41d70a..f9e7172acbb 100644 --- a/packages/client/lib/commands/SUNION.ts +++ b/packages/client/lib/commands/SUNION.ts @@ -1,14 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVariadicArguments(['SUNION'], keys); -} +// export function transformArguments( +// keys: RedisCommandArgument | Array +// ): RedisCommandArguments { +// return pushVariadicArguments(['SUNION'], keys); +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SUNIONSTORE.ts b/packages/client/lib/commands/SUNIONSTORE.ts index 27161ba0773..1d5ee097caf 100644 --- a/packages/client/lib/commands/SUNIONSTORE.ts +++ b/packages/client/lib/commands/SUNIONSTORE.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - destination: RedisCommandArgument, - keys: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVariadicArguments(['SUNIONSTORE', destination], keys); -} +// export function transformArguments( +// destination: RedisCommandArgument, +// keys: RedisCommandArgument | Array +// ): RedisCommandArguments { +// return pushVariadicArguments(['SUNIONSTORE', destination], keys); +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/TOUCH.ts b/packages/client/lib/commands/TOUCH.ts index c28f7a4629f..c1c19402f8b 100644 --- a/packages/client/lib/commands/TOUCH.ts +++ b/packages/client/lib/commands/TOUCH.ts @@ -1,12 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisVariadicArgument) { return pushVariadicArguments(['TOUCH'], key); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/UNLINK.ts b/packages/client/lib/commands/UNLINK.ts index 4455d42bcf1..2346573f397 100644 --- a/packages/client/lib/commands/UNLINK.ts +++ b/packages/client/lib/commands/UNLINK.ts @@ -1,12 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisVariadicArgument) { return pushVariadicArguments(['UNLINK'], key); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/WATCH.ts b/packages/client/lib/commands/WATCH.ts index 9a7b16fd74e..b4fd86b37ab 100644 --- a/packages/client/lib/commands/WATCH.ts +++ b/packages/client/lib/commands/WATCH.ts @@ -1,10 +1,11 @@ -import { RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { SimpleStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string | Array): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisVariadicArgument) { return pushVariadicArguments(['WATCH'], key); -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XACK.ts b/packages/client/lib/commands/XACK.ts index 1d35c8d13bd..4d54df00d1e 100644 --- a/packages/client/lib/commands/XACK.ts +++ b/packages/client/lib/commands/XACK.ts @@ -1,14 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - id: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVariadicArguments(['XACK', key, group], id); -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// id: RedisCommandArgument | Array +// ): RedisCommandArguments { +// return pushVariadicArguments(['XACK', key, group], id); +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/XADD.ts b/packages/client/lib/commands/XADD.ts index e7a1b6804ff..16d7286ca70 100644 --- a/packages/client/lib/commands/XADD.ts +++ b/packages/client/lib/commands/XADD.ts @@ -1,52 +1,52 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; - -interface XAddOptions { - NOMKSTREAM?: true; - TRIM?: { - strategy?: 'MAXLEN' | 'MINID'; - strategyModifier?: '=' | '~'; - threshold: number; - limit?: number; - }; -} - -export function transformArguments( - key: RedisCommandArgument, - id: RedisCommandArgument, - message: Record, - options?: XAddOptions -): RedisCommandArguments { - const args = ['XADD', key]; - - if (options?.NOMKSTREAM) { - args.push('NOMKSTREAM'); - } - - if (options?.TRIM) { - if (options.TRIM.strategy) { - args.push(options.TRIM.strategy); - } - - if (options.TRIM.strategyModifier) { - args.push(options.TRIM.strategyModifier); - } - - args.push(options.TRIM.threshold.toString()); - - if (options.TRIM.limit) { - args.push('LIMIT', options.TRIM.limit.toString()); - } - } - - args.push(id); - - for (const [key, value] of Object.entries(message)) { - args.push(key, value); - } - - return args; -} - -export declare function transformReply(): string; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; + +// export const FIRST_KEY_INDEX = 1; + +// interface XAddOptions { +// NOMKSTREAM?: true; +// TRIM?: { +// strategy?: 'MAXLEN' | 'MINID'; +// strategyModifier?: '=' | '~'; +// threshold: number; +// limit?: number; +// }; +// } + +// export function transformArguments( +// key: RedisCommandArgument, +// id: RedisCommandArgument, +// message: Record, +// options?: XAddOptions +// ): RedisCommandArguments { +// const args = ['XADD', key]; + +// if (options?.NOMKSTREAM) { +// args.push('NOMKSTREAM'); +// } + +// if (options?.TRIM) { +// if (options.TRIM.strategy) { +// args.push(options.TRIM.strategy); +// } + +// if (options.TRIM.strategyModifier) { +// args.push(options.TRIM.strategyModifier); +// } + +// args.push(options.TRIM.threshold.toString()); + +// if (options.TRIM.limit) { +// args.push('LIMIT', options.TRIM.limit.toString()); +// } +// } + +// args.push(id); + +// for (const [key, value] of Object.entries(message)) { +// args.push(key, value); +// } + +// return args; +// } + +// export declare function transformReply(): string; diff --git a/packages/client/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts index 4bf46057bac..c32c3baf8d9 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.ts @@ -1,39 +1,39 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { StreamMessagesReply, transformStreamMessagesReply } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export interface XAutoClaimOptions { - COUNT?: number; -} - -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - consumer: RedisCommandArgument, - minIdleTime: number, - start: string, - options?: XAutoClaimOptions -): RedisCommandArguments { - const args = ['XAUTOCLAIM', key, group, consumer, minIdleTime.toString(), start]; - - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } - - return args; -} - -type XAutoClaimRawReply = [RedisCommandArgument, Array]; - -interface XAutoClaimReply { - nextId: RedisCommandArgument; - messages: StreamMessagesReply; -} - -export function transformReply(reply: XAutoClaimRawReply): XAutoClaimReply { - return { - nextId: reply[0], - messages: transformStreamMessagesReply(reply[1]) - }; -} +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { StreamMessagesReply, transformStreamMessagesReply } from './generic-transformers'; + +// export const FIRST_KEY_INDEX = 1; + +// export interface XAutoClaimOptions { +// COUNT?: number; +// } + +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// consumer: RedisCommandArgument, +// minIdleTime: number, +// start: string, +// options?: XAutoClaimOptions +// ): RedisCommandArguments { +// const args = ['XAUTOCLAIM', key, group, consumer, minIdleTime.toString(), start]; + +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } + +// return args; +// } + +// type XAutoClaimRawReply = [RedisCommandArgument, Array]; + +// interface XAutoClaimReply { +// nextId: RedisCommandArgument; +// messages: StreamMessagesReply; +// } + +// export function transformReply(reply: XAutoClaimRawReply): XAutoClaimReply { +// return { +// nextId: reply[0], +// messages: transformStreamMessagesReply(reply[1]) +// }; +// } diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts index a30ac1579e7..3f6374d9850 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformXAutoClaimArguments } from './XAUTOCLAIM'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformArguments as transformXAutoClaimArguments } from './XAUTOCLAIM'; -export { FIRST_KEY_INDEX } from './XAUTOCLAIM'; +// export { FIRST_KEY_INDEX } from './XAUTOCLAIM'; -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformXAutoClaimArguments(...args), - 'JUSTID' - ]; -} +// export function transformArguments(...args: Parameters): RedisCommandArguments { +// return [ +// ...transformXAutoClaimArguments(...args), +// 'JUSTID' +// ]; +// } -type XAutoClaimJustIdRawReply = [RedisCommandArgument, Array]; +// type XAutoClaimJustIdRawReply = [RedisCommandArgument, Array]; -interface XAutoClaimJustIdReply { - nextId: RedisCommandArgument; - messages: Array; -} +// interface XAutoClaimJustIdReply { +// nextId: RedisCommandArgument; +// messages: Array; +// } -export function transformReply(reply: XAutoClaimJustIdRawReply): XAutoClaimJustIdReply { - return { - nextId: reply[0], - messages: reply[1] - }; -} +// export function transformReply(reply: XAutoClaimJustIdRawReply): XAutoClaimJustIdReply { +// return { +// nextId: reply[0], +// messages: reply[1] +// }; +// } diff --git a/packages/client/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts index 43ad78cfb69..6c1328441aa 100644 --- a/packages/client/lib/commands/XCLAIM.ts +++ b/packages/client/lib/commands/XCLAIM.ts @@ -1,48 +1,48 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export interface XClaimOptions { - IDLE?: number; - TIME?: number | Date; - RETRYCOUNT?: number; - FORCE?: true; -} - -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - consumer: RedisCommandArgument, - minIdleTime: number, - id: RedisCommandArgument | Array, - options?: XClaimOptions -): RedisCommandArguments { - const args = pushVariadicArguments( - ['XCLAIM', key, group, consumer, minIdleTime.toString()], - id - ); - - if (options?.IDLE) { - args.push('IDLE', options.IDLE.toString()); - } - - if (options?.TIME) { - args.push( - 'TIME', - (typeof options.TIME === 'number' ? options.TIME : options.TIME.getTime()).toString() - ); - } - - if (options?.RETRYCOUNT) { - args.push('RETRYCOUNT', options.RETRYCOUNT.toString()); - } - - if (options?.FORCE) { - args.push('FORCE'); - } - - return args; -} - -export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; + +// export const FIRST_KEY_INDEX = 1; + +// export interface XClaimOptions { +// IDLE?: number; +// TIME?: number | Date; +// RETRYCOUNT?: number; +// FORCE?: true; +// } + +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// consumer: RedisCommandArgument, +// minIdleTime: number, +// id: RedisCommandArgument | Array, +// options?: XClaimOptions +// ): RedisCommandArguments { +// const args = pushVariadicArguments( +// ['XCLAIM', key, group, consumer, minIdleTime.toString()], +// id +// ); + +// if (options?.IDLE) { +// args.push('IDLE', options.IDLE.toString()); +// } + +// if (options?.TIME) { +// args.push( +// 'TIME', +// (typeof options.TIME === 'number' ? options.TIME : options.TIME.getTime()).toString() +// ); +// } + +// if (options?.RETRYCOUNT) { +// args.push('RETRYCOUNT', options.RETRYCOUNT.toString()); +// } + +// if (options?.FORCE) { +// args.push('FORCE'); +// } + +// return args; +// } + +// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XCLAIM_JUSTID.ts b/packages/client/lib/commands/XCLAIM_JUSTID.ts index 50d0d5a0366..7c011e692fc 100644 --- a/packages/client/lib/commands/XCLAIM_JUSTID.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformXClaimArguments } from './XCLAIM'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformArguments as transformXClaimArguments } from './XCLAIM'; -export { FIRST_KEY_INDEX } from './XCLAIM'; +// export { FIRST_KEY_INDEX } from './XCLAIM'; -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformXClaimArguments(...args), - 'JUSTID' - ]; -} +// export function transformArguments(...args: Parameters): RedisCommandArguments { +// return [ +// ...transformXClaimArguments(...args), +// 'JUSTID' +// ]; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/XDEL.ts b/packages/client/lib/commands/XDEL.ts index 80b429c4e11..dab033fe572 100644 --- a/packages/client/lib/commands/XDEL.ts +++ b/packages/client/lib/commands/XDEL.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - id: RedisCommandArgument | Array -): RedisCommandArguments { - return pushVariadicArguments(['XDEL', key], id); -} +// export function transformArguments( +// key: RedisCommandArgument, +// id: RedisCommandArgument | Array +// ): RedisCommandArguments { +// return pushVariadicArguments(['XDEL', key], id); +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/XGROUP_CREATE.ts b/packages/client/lib/commands/XGROUP_CREATE.ts index 8cfd4e262e4..def2bf39eb3 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.ts @@ -1,24 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -interface XGroupCreateOptions { - MKSTREAM?: true; -} +// interface XGroupCreateOptions { +// MKSTREAM?: true; +// } -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - id: RedisCommandArgument, - options?: XGroupCreateOptions -): RedisCommandArguments { - const args = ['XGROUP', 'CREATE', key, group, id]; +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// id: RedisCommandArgument, +// options?: XGroupCreateOptions +// ): RedisCommandArguments { +// const args = ['XGROUP', 'CREATE', key, group, id]; - if (options?.MKSTREAM) { - args.push('MKSTREAM'); - } +// if (options?.MKSTREAM) { +// args.push('MKSTREAM'); +// } - return args; -} +// return args; +// } -export declare function transformReply(): RedisCommandArgument; +// export declare function transformReply(): RedisCommandArgument; diff --git a/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts index 2b816a6b480..8fb9ad2ad3a 100644 --- a/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - consumer: RedisCommandArgument -): RedisCommandArguments { - return ['XGROUP', 'CREATECONSUMER', key, group, consumer]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// consumer: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XGROUP', 'CREATECONSUMER', key, group, consumer]; +// } -export { transformBooleanReply as transformReply } from './generic-transformers'; +// export { transformBooleanReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts index 4e4fc096d07..ad54beaf9dc 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - consumer: RedisCommandArgument -): RedisCommandArguments { - return ['XGROUP', 'DELCONSUMER', key, group, consumer]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// consumer: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XGROUP', 'DELCONSUMER', key, group, consumer]; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/XGROUP_DESTROY.ts b/packages/client/lib/commands/XGROUP_DESTROY.ts index 85910c02471..077afba4dc7 100644 --- a/packages/client/lib/commands/XGROUP_DESTROY.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.ts @@ -1,12 +1,12 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument -): RedisCommandArguments { - return ['XGROUP', 'DESTROY', key, group]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XGROUP', 'DESTROY', key, group]; +// } -export { transformBooleanReply as transformReply } from './generic-transformers'; +// export { transformBooleanReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XGROUP_SETID.ts b/packages/client/lib/commands/XGROUP_SETID.ts index e732fc8d7bf..65e1e257fb1 100644 --- a/packages/client/lib/commands/XGROUP_SETID.ts +++ b/packages/client/lib/commands/XGROUP_SETID.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - id: RedisCommandArgument -): RedisCommandArguments { - return ['XGROUP', 'SETID', key, group, id]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// id: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XGROUP', 'SETID', key, group, id]; +// } -export declare function transformReply(): RedisCommandArgument; +// export declare function transformReply(): RedisCommandArgument; diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.ts b/packages/client/lib/commands/XINFO_CONSUMERS.ts index 05e3a26b172..a9c5cb75e42 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.ts @@ -1,26 +1,26 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument -): RedisCommandArguments { - return ['XINFO', 'CONSUMERS', key, group]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XINFO', 'CONSUMERS', key, group]; +// } -type XInfoConsumersReply = Array<{ - name: RedisCommandArgument; - pending: number; - idle: number; -}>; +// type XInfoConsumersReply = Array<{ +// name: RedisCommandArgument; +// pending: number; +// idle: number; +// }>; -export function transformReply(rawReply: Array): XInfoConsumersReply { - return rawReply.map(consumer => ({ - name: consumer[1], - pending: consumer[3], - idle: consumer[5] - })); -} +// export function transformReply(rawReply: Array): XInfoConsumersReply { +// return rawReply.map(consumer => ({ +// name: consumer[1], +// pending: consumer[3], +// idle: consumer[5] +// })); +// } diff --git a/packages/client/lib/commands/XINFO_GROUPS.ts b/packages/client/lib/commands/XINFO_GROUPS.ts index dcf504c8ce7..4dac9eed857 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.ts @@ -1,25 +1,25 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return ['XINFO', 'GROUPS', key]; -} +// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +// return ['XINFO', 'GROUPS', key]; +// } -type XInfoGroupsReply = Array<{ - name: RedisCommandArgument; - consumers: number; - pending: number; - lastDeliveredId: RedisCommandArgument; -}>; +// type XInfoGroupsReply = Array<{ +// name: RedisCommandArgument; +// consumers: number; +// pending: number; +// lastDeliveredId: RedisCommandArgument; +// }>; -export function transformReply(rawReply: Array): XInfoGroupsReply { - return rawReply.map(group => ({ - name: group[1], - consumers: group[3], - pending: group[5], - lastDeliveredId: group[7] - })); -} +// export function transformReply(rawReply: Array): XInfoGroupsReply { +// return rawReply.map(group => ({ +// name: group[1], +// consumers: group[3], +// pending: group[5], +// lastDeliveredId: group[7] +// })); +// } diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index e9de25be8cb..32fb83fe0a8 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -1,64 +1,64 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { StreamMessageReply, transformTuplesReply } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { StreamMessageReply, transformTuplesReply } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return ['XINFO', 'STREAM', key]; -} +// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +// return ['XINFO', 'STREAM', key]; +// } -interface XInfoStreamReply { - length: number; - radixTreeKeys: number; - radixTreeNodes: number; - groups: number; - lastGeneratedId: RedisCommandArgument; - firstEntry: StreamMessageReply | null; - lastEntry: StreamMessageReply | null; -} +// interface XInfoStreamReply { +// length: number; +// radixTreeKeys: number; +// radixTreeNodes: number; +// groups: number; +// lastGeneratedId: RedisCommandArgument; +// firstEntry: StreamMessageReply | null; +// lastEntry: StreamMessageReply | null; +// } -export function transformReply(rawReply: Array): XInfoStreamReply { - const parsedReply: Partial = {}; +// export function transformReply(rawReply: Array): XInfoStreamReply { +// const parsedReply: Partial = {}; - for (let i = 0; i < rawReply.length; i+= 2) { - switch (rawReply[i]) { - case 'length': - parsedReply.length = rawReply[i + 1]; - break; +// for (let i = 0; i < rawReply.length; i+= 2) { +// switch (rawReply[i]) { +// case 'length': +// parsedReply.length = rawReply[i + 1]; +// break; - case 'radix-tree-keys': - parsedReply.radixTreeKeys = rawReply[i + 1]; - break; +// case 'radix-tree-keys': +// parsedReply.radixTreeKeys = rawReply[i + 1]; +// break; - case 'radix-tree-nodes': - parsedReply.radixTreeNodes = rawReply[i + 1]; - break; +// case 'radix-tree-nodes': +// parsedReply.radixTreeNodes = rawReply[i + 1]; +// break; - case 'groups': - parsedReply.groups = rawReply[i + 1]; - break; +// case 'groups': +// parsedReply.groups = rawReply[i + 1]; +// break; - case 'last-generated-id': - parsedReply.lastGeneratedId = rawReply[i + 1]; - break; +// case 'last-generated-id': +// parsedReply.lastGeneratedId = rawReply[i + 1]; +// break; - case 'first-entry': - parsedReply.firstEntry = rawReply[i + 1] ? { - id: rawReply[i + 1][0], - message: transformTuplesReply(rawReply[i + 1][1]) - } : null; - break; +// case 'first-entry': +// parsedReply.firstEntry = rawReply[i + 1] ? { +// id: rawReply[i + 1][0], +// message: transformTuplesReply(rawReply[i + 1][1]) +// } : null; +// break; - case 'last-entry': - parsedReply.lastEntry = rawReply[i + 1] ? { - id: rawReply[i + 1][0], - message: transformTuplesReply(rawReply[i + 1][1]) - } : null; - break; - } - } +// case 'last-entry': +// parsedReply.lastEntry = rawReply[i + 1] ? { +// id: rawReply[i + 1][0], +// message: transformTuplesReply(rawReply[i + 1][1]) +// } : null; +// break; +// } +// } - return parsedReply as XInfoStreamReply; -} +// return parsedReply as XInfoStreamReply; +// } diff --git a/packages/client/lib/commands/XLEN.ts b/packages/client/lib/commands/XLEN.ts index fda4192c8a0..d2ed566a190 100644 --- a/packages/client/lib/commands/XLEN.ts +++ b/packages/client/lib/commands/XLEN.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['XLEN', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XPENDING.ts b/packages/client/lib/commands/XPENDING.ts index ac56e429410..215295afd25 100644 --- a/packages/client/lib/commands/XPENDING.ts +++ b/packages/client/lib/commands/XPENDING.ts @@ -1,44 +1,44 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument -): RedisCommandArguments { - return ['XPENDING', key, group]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument +// ): RedisCommandArguments { +// return ['XPENDING', key, group]; +// } -type XPendingRawReply = [ - pending: number, - firstId: RedisCommandArgument | null, - lastId: RedisCommandArgument | null, - consumers: Array<[ - name: RedisCommandArgument, - deliveriesCounter: RedisCommandArgument - ]> | null -]; +// type XPendingRawReply = [ +// pending: number, +// firstId: RedisCommandArgument | null, +// lastId: RedisCommandArgument | null, +// consumers: Array<[ +// name: RedisCommandArgument, +// deliveriesCounter: RedisCommandArgument +// ]> | null +// ]; -interface XPendingReply { - pending: number; - firstId: RedisCommandArgument | null; - lastId: RedisCommandArgument | null; - consumers: Array<{ - name: RedisCommandArgument; - deliveriesCounter: number; - }> | null; -} +// interface XPendingReply { +// pending: number; +// firstId: RedisCommandArgument | null; +// lastId: RedisCommandArgument | null; +// consumers: Array<{ +// name: RedisCommandArgument; +// deliveriesCounter: number; +// }> | null; +// } -export function transformReply(reply: XPendingRawReply): XPendingReply { - return { - pending: reply[0], - firstId: reply[1], - lastId: reply[2], - consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({ - name, - deliveriesCounter: Number(deliveriesCounter) - })) - }; -} +// export function transformReply(reply: XPendingRawReply): XPendingReply { +// return { +// pending: reply[0], +// firstId: reply[1], +// lastId: reply[2], +// consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({ +// name, +// deliveriesCounter: Number(deliveriesCounter) +// })) +// }; +// } diff --git a/packages/client/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts index 87660de545d..37d95efd4f8 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.ts @@ -1,56 +1,56 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -interface XPendingRangeOptions { - IDLE?: number; - consumer?: RedisCommandArgument; -} - -export function transformArguments( - key: RedisCommandArgument, - group: RedisCommandArgument, - start: string, - end: string, - count: number, - options?: XPendingRangeOptions -): RedisCommandArguments { - const args = ['XPENDING', key, group]; - - if (options?.IDLE) { - args.push('IDLE', options.IDLE.toString()); - } - - args.push(start, end, count.toString()); - - if (options?.consumer) { - args.push(options.consumer); - } - - return args; -} - -type XPendingRangeRawReply = Array<[ - id: RedisCommandArgument, - consumer: RedisCommandArgument, - millisecondsSinceLastDelivery: number, - deliveriesCounter: number -]>; - -type XPendingRangeReply = Array<{ - id: RedisCommandArgument; - owner: RedisCommandArgument; - millisecondsSinceLastDelivery: number; - deliveriesCounter: number; -}>; - -export function transformReply(reply: XPendingRangeRawReply): XPendingRangeReply { - return reply.map(([id, owner, millisecondsSinceLastDelivery, deliveriesCounter]) => ({ - id, - owner, - millisecondsSinceLastDelivery, - deliveriesCounter - })); -} +// import { RedisCommandArgument, RedisCommandArguments } from '.'; + +// export const FIRST_KEY_INDEX = 1; + +// export const IS_READ_ONLY = true; + +// interface XPendingRangeOptions { +// IDLE?: number; +// consumer?: RedisCommandArgument; +// } + +// export function transformArguments( +// key: RedisCommandArgument, +// group: RedisCommandArgument, +// start: string, +// end: string, +// count: number, +// options?: XPendingRangeOptions +// ): RedisCommandArguments { +// const args = ['XPENDING', key, group]; + +// if (options?.IDLE) { +// args.push('IDLE', options.IDLE.toString()); +// } + +// args.push(start, end, count.toString()); + +// if (options?.consumer) { +// args.push(options.consumer); +// } + +// return args; +// } + +// type XPendingRangeRawReply = Array<[ +// id: RedisCommandArgument, +// consumer: RedisCommandArgument, +// millisecondsSinceLastDelivery: number, +// deliveriesCounter: number +// ]>; + +// type XPendingRangeReply = Array<{ +// id: RedisCommandArgument; +// owner: RedisCommandArgument; +// millisecondsSinceLastDelivery: number; +// deliveriesCounter: number; +// }>; + +// export function transformReply(reply: XPendingRangeRawReply): XPendingRangeReply { +// return reply.map(([id, owner, millisecondsSinceLastDelivery, deliveriesCounter]) => ({ +// id, +// owner, +// millisecondsSinceLastDelivery, +// deliveriesCounter +// })); +// } diff --git a/packages/client/lib/commands/XRANGE.ts b/packages/client/lib/commands/XRANGE.ts index ae56639f769..1f3cf1d856e 100644 --- a/packages/client/lib/commands/XRANGE.ts +++ b/packages/client/lib/commands/XRANGE.ts @@ -1,26 +1,26 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -interface XRangeOptions { - COUNT?: number; -} +// interface XRangeOptions { +// COUNT?: number; +// } -export function transformArguments( - key: RedisCommandArgument, - start: RedisCommandArgument, - end: RedisCommandArgument, - options?: XRangeOptions -): RedisCommandArguments { - const args = ['XRANGE', key, start, end]; +// export function transformArguments( +// key: RedisCommandArgument, +// start: RedisCommandArgument, +// end: RedisCommandArgument, +// options?: XRangeOptions +// ): RedisCommandArguments { +// const args = ['XRANGE', key, start, end]; - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } - return args; -} +// return args; +// } -export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XREAD.ts b/packages/client/lib/commands/XREAD.ts index e5f85dbe7fe..f58972b1f65 100644 --- a/packages/client/lib/commands/XREAD.ts +++ b/packages/client/lib/commands/XREAD.ts @@ -1,46 +1,46 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = (streams: Array | XReadStream): RedisCommandArgument => { - return Array.isArray(streams) ? streams[0].key : streams.key; -}; +// export const FIRST_KEY_INDEX = (streams: Array | XReadStream): RedisCommandArgument => { +// return Array.isArray(streams) ? streams[0].key : streams.key; +// }; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -interface XReadStream { - key: RedisCommandArgument; - id: RedisCommandArgument; -} +// interface XReadStream { +// key: RedisCommandArgument; +// id: RedisCommandArgument; +// } -interface XReadOptions { - COUNT?: number; - BLOCK?: number; -} +// interface XReadOptions { +// COUNT?: number; +// BLOCK?: number; +// } -export function transformArguments( - streams: Array | XReadStream, - options?: XReadOptions -): RedisCommandArguments { - const args: RedisCommandArguments = ['XREAD']; +// export function transformArguments( +// streams: Array | XReadStream, +// options?: XReadOptions +// ): RedisCommandArguments { +// const args: RedisCommandArguments = ['XREAD']; - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } - if (typeof options?.BLOCK === 'number') { - args.push('BLOCK', options.BLOCK.toString()); - } +// if (typeof options?.BLOCK === 'number') { +// args.push('BLOCK', options.BLOCK.toString()); +// } - args.push('STREAMS'); +// args.push('STREAMS'); - const streamsArray = Array.isArray(streams) ? streams : [streams], - argsLength = args.length; - for (let i = 0; i < streamsArray.length; i++) { - const stream = streamsArray[i]; - args[argsLength + i] = stream.key; - args[argsLength + streamsArray.length + i] = stream.id; - } +// const streamsArray = Array.isArray(streams) ? streams : [streams], +// argsLength = args.length; +// for (let i = 0; i < streamsArray.length; i++) { +// const stream = streamsArray[i]; +// args[argsLength + i] = stream.key; +// args[argsLength + streamsArray.length + i] = stream.id; +// } - return args; -} +// return args; +// } -export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; +// export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XREADGROUP.ts b/packages/client/lib/commands/XREADGROUP.ts index e90e698a2ad..40064934cd6 100644 --- a/packages/client/lib/commands/XREADGROUP.ts +++ b/packages/client/lib/commands/XREADGROUP.ts @@ -1,57 +1,57 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; - -export interface XReadGroupStream { - key: RedisCommandArgument; - id: RedisCommandArgument; -} - -export interface XReadGroupOptions { - COUNT?: number; - BLOCK?: number; - NOACK?: true; -} - -export const FIRST_KEY_INDEX = ( - _group: RedisCommandArgument, - _consumer: RedisCommandArgument, - streams: Array | XReadGroupStream -): RedisCommandArgument => { - return Array.isArray(streams) ? streams[0].key : streams.key; -}; - -export const IS_READ_ONLY = true; - -export function transformArguments( - group: RedisCommandArgument, - consumer: RedisCommandArgument, - streams: Array | XReadGroupStream, - options?: XReadGroupOptions -): RedisCommandArguments { - const args = ['XREADGROUP', 'GROUP', group, consumer]; - - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } - - if (typeof options?.BLOCK === 'number') { - args.push('BLOCK', options.BLOCK.toString()); - } - - if (options?.NOACK) { - args.push('NOACK'); - } - - args.push('STREAMS'); - - const streamsArray = Array.isArray(streams) ? streams : [streams], - argsLength = args.length; - for (let i = 0; i < streamsArray.length; i++) { - const stream = streamsArray[i]; - args[argsLength + i] = stream.key; - args[argsLength + streamsArray.length + i] = stream.id; - } - - return args; -} - -export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; + +// export interface XReadGroupStream { +// key: RedisCommandArgument; +// id: RedisCommandArgument; +// } + +// export interface XReadGroupOptions { +// COUNT?: number; +// BLOCK?: number; +// NOACK?: true; +// } + +// export const FIRST_KEY_INDEX = ( +// _group: RedisCommandArgument, +// _consumer: RedisCommandArgument, +// streams: Array | XReadGroupStream +// ): RedisCommandArgument => { +// return Array.isArray(streams) ? streams[0].key : streams.key; +// }; + +// export const IS_READ_ONLY = true; + +// export function transformArguments( +// group: RedisCommandArgument, +// consumer: RedisCommandArgument, +// streams: Array | XReadGroupStream, +// options?: XReadGroupOptions +// ): RedisCommandArguments { +// const args = ['XREADGROUP', 'GROUP', group, consumer]; + +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } + +// if (typeof options?.BLOCK === 'number') { +// args.push('BLOCK', options.BLOCK.toString()); +// } + +// if (options?.NOACK) { +// args.push('NOACK'); +// } + +// args.push('STREAMS'); + +// const streamsArray = Array.isArray(streams) ? streams : [streams], +// argsLength = args.length; +// for (let i = 0; i < streamsArray.length; i++) { +// const stream = streamsArray[i]; +// args[argsLength + i] = stream.key; +// args[argsLength + streamsArray.length + i] = stream.id; +// } + +// return args; +// } + +// export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XREVRANGE.ts b/packages/client/lib/commands/XREVRANGE.ts index 96bbeba83ce..de095dc0297 100644 --- a/packages/client/lib/commands/XREVRANGE.ts +++ b/packages/client/lib/commands/XREVRANGE.ts @@ -1,26 +1,26 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -interface XRangeRevOptions { - COUNT?: number; -} +// interface XRangeRevOptions { +// COUNT?: number; +// } -export function transformArguments( - key: RedisCommandArgument, - start: RedisCommandArgument, - end: RedisCommandArgument, - options?: XRangeRevOptions -): RedisCommandArguments { - const args = ['XREVRANGE', key, start, end]; +// export function transformArguments( +// key: RedisCommandArgument, +// start: RedisCommandArgument, +// end: RedisCommandArgument, +// options?: XRangeRevOptions +// ): RedisCommandArguments { +// const args = ['XREVRANGE', key, start, end]; - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } - return args; -} +// return args; +// } -export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XSETID.ts b/packages/client/lib/commands/XSETID.ts index 76acc7ebab4..df7cc10f906 100644 --- a/packages/client/lib/commands/XSETID.ts +++ b/packages/client/lib/commands/XSETID.ts @@ -1,28 +1,28 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -interface XSetIdOptions { - ENTRIESADDED?: number; - MAXDELETEDID?: RedisCommandArgument; -} +// interface XSetIdOptions { +// ENTRIESADDED?: number; +// MAXDELETEDID?: RedisCommandArgument; +// } -export function transformArguments( - key: RedisCommandArgument, - lastId: RedisCommandArgument, - options?: XSetIdOptions -): RedisCommandArguments { - const args = ['XSETID', key, lastId]; +// export function transformArguments( +// key: RedisCommandArgument, +// lastId: RedisCommandArgument, +// options?: XSetIdOptions +// ): RedisCommandArguments { +// const args = ['XSETID', key, lastId]; - if (options?.ENTRIESADDED) { - args.push('ENTRIESADDED', options.ENTRIESADDED.toString()); - } +// if (options?.ENTRIESADDED) { +// args.push('ENTRIESADDED', options.ENTRIESADDED.toString()); +// } - if (options?.MAXDELETEDID) { - args.push('MAXDELETEDID', options.MAXDELETEDID); - } +// if (options?.MAXDELETEDID) { +// args.push('MAXDELETEDID', options.MAXDELETEDID); +// } - return args; -} +// return args; +// } -export declare function transformReply(): 'OK'; +// export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/XTRIM.ts b/packages/client/lib/commands/XTRIM.ts index 15b934c56ef..780aeb30d7b 100644 --- a/packages/client/lib/commands/XTRIM.ts +++ b/packages/client/lib/commands/XTRIM.ts @@ -1,31 +1,31 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -interface XTrimOptions { - strategyModifier?: '=' | '~'; - LIMIT?: number; -} +// interface XTrimOptions { +// strategyModifier?: '=' | '~'; +// LIMIT?: number; +// } -export function transformArguments( - key: RedisCommandArgument, - strategy: 'MAXLEN' | 'MINID', - threshold: number, - options?: XTrimOptions -): RedisCommandArguments { - const args = ['XTRIM', key, strategy]; +// export function transformArguments( +// key: RedisCommandArgument, +// strategy: 'MAXLEN' | 'MINID', +// threshold: number, +// options?: XTrimOptions +// ): RedisCommandArguments { +// const args = ['XTRIM', key, strategy]; - if (options?.strategyModifier) { - args.push(options.strategyModifier); - } +// if (options?.strategyModifier) { +// args.push(options.strategyModifier); +// } - args.push(threshold.toString()); +// args.push(threshold.toString()); - if (options?.LIMIT) { - args.push('LIMIT', options.LIMIT.toString()); - } +// if (options?.LIMIT) { +// args.push('LIMIT', options.LIMIT.toString()); +// } - return args; -} +// return args; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index 9372c9217ed..0c2a1e105d8 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,5 +1,5 @@ import { RedisArgument, NumberReply, DoubleReply, Command } from '../RESP/types'; -import { ZMember, transformNumberInfinityArgument, transformNumberInfinityReply } from './generic-transformers'; +import { ZMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; interface NX { NX?: boolean; @@ -62,7 +62,7 @@ export default { for (const { score, value } of (Array.isArray(members) ? members : [members])) { args.push( - transformNumberInfinityArgument(score), + transformDoubleArgument(score), value ); } @@ -70,7 +70,7 @@ export default { return args; }, transformReply: { - 2: transformNumberInfinityReply, + 2: transformDoubleReply, 3: undefined as unknown as () => NumberReply | DoubleReply } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZCOUNT.ts b/packages/client/lib/commands/ZCOUNT.ts index 06bd4b915a8..187a316b15a 100644 --- a/packages/client/lib/commands/ZCOUNT.ts +++ b/packages/client/lib/commands/ZCOUNT.ts @@ -1,5 +1,5 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; +import { transformStringDoubleArgument } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -12,8 +12,8 @@ export default { return [ 'ZCOUNT', key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) ]; }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts index 66b3dfa1f24..c20da15161d 100644 --- a/packages/client/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -1,5 +1,5 @@ import { RedisArgument, DoubleReply, Command } from '../RESP/types'; -import { transformNumberInfinityArgument, transformNumberInfinityReply } from './generic-transformers'; +import { transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -11,12 +11,12 @@ export default { return [ 'ZINCRBY', key, - transformNumberInfinityArgument(increment), + transformDoubleArgument(increment), member ]; }, transformReply: { - 2: transformNumberInfinityReply, + 2: transformDoubleReply, 3: undefined as unknown as () => DoubleReply } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTER.ts b/packages/client/lib/commands/ZINTER.ts index 8c185c03c74..a4c0be6debe 100644 --- a/packages/client/lib/commands/ZINTER.ts +++ b/packages/client/lib/commands/ZINTER.ts @@ -1,5 +1,5 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { transformNumberInfinityArgument } from './generic-transformers'; +import { transformDoubleArgument } from './generic-transformers'; export type ZInterKeyAndWeight = { key: RedisArgument; @@ -29,7 +29,7 @@ export function pushZInterArguments( for (let i = 0; i < keys.length; i++) { const index = start + i; args[index] = keys[i].key; - args[index + 1 + keys.length] = transformNumberInfinityArgument(keys[i].weight); + args[index + 1 + keys.length] = transformDoubleArgument(keys[i].weight); } } } @@ -42,7 +42,7 @@ export function pushZInterArguments( args.push( keys.key, 'WEIGHTS', - transformNumberInfinityArgument(keys.weight) + transformDoubleArgument(keys.weight) ); } } diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts index d430b1cbc48..ae704ab2863 100644 --- a/packages/client/lib/commands/ZMPOP.ts +++ b/packages/client/lib/commands/ZMPOP.ts @@ -1,54 +1,61 @@ -import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; -import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide } from './generic-transformers'; +// import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command, RedisArgument } from '../RESP/types'; +// import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide } from './generic-transformers'; -export interface ZMPopOptions { - COUNT?: number; -} +// export interface ZMPopOptions { +// COUNT?: number; +// } -export type ZMPopRawReply = NullReply | TuplesReply<[ - key: BlobStringReply, - elements: ArrayReply> -]>; +// export type ZMPopRawReply = NullReply | TuplesReply<[ +// key: BlobStringReply, +// elements: ArrayReply> +// ]>; -export default { - FIRST_KEY_INDEX: 2, - IS_READ_ONLY: false, - transformArguments( - keys: RedisVariadicArgument, - side: SortedSetSide, - options?: ZMPopOptions - ) { - const args = pushVariadicArgument(['ZMPOP'], keys); +// export function pushZMPopArguments( +// args: Array, +// keys: RedisVariadicArgument, +// side: SortedSetSide, +// options: ZMPopOptions +// ) - args.push(side); +// export default { +// FIRST_KEY_INDEX: 2, +// IS_READ_ONLY: false, +// transformArguments( +// keys: RedisVariadicArgument, +// side: SortedSetSide, +// options?: ZMPopOptions +// ) { +// const args = pushVariadicArgument(['ZMPOP'], keys); - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +// args.push(side); - return args; - }, - transformReply: { - 2: (reply: Resp2Reply) => { - return reply === null ? null : { - key: reply[0], - elements: reply[1].map(([member, score]) => ({ - member, - score: Number(score) - })) - }; - }, - 3: (reply: ZMPopRawReply) => { - return reply === null ? null : { - key: reply[0], - elements: reply[1].map(([member, score]) => ({ - member, - score - })) - }; - }, - } -} as const satisfies Command; +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } + +// return args; +// }, +// transformReply: { +// 2: (reply: Resp2Reply) => { +// return reply === null ? null : { +// key: reply[0], +// elements: reply[1].map(([member, score]) => ({ +// member, +// score: Number(score) +// })) +// }; +// }, +// 3: (reply: ZMPopRawReply) => { +// return reply === null ? null : { +// key: reply[0], +// elements: reply[1].map(([member, score]) => ({ +// member, +// score +// })) +// }; +// }, +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMAX.ts b/packages/client/lib/commands/ZPOPMAX.ts index 811166a690c..959c3b927ba 100644 --- a/packages/client/lib/commands/ZPOPMAX.ts +++ b/packages/client/lib/commands/ZPOPMAX.ts @@ -1,12 +1,12 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return [ - 'ZPOPMAX', - key - ]; -} +// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +// return [ +// 'ZPOPMAX', +// key +// ]; +// } -export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; +// export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.ts index 875bcfb9147..881f5472e68 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.ts @@ -1,16 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformZPopMaxArguments } from './ZPOPMAX'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformArguments as transformZPopMaxArguments } from './ZPOPMAX'; -export { FIRST_KEY_INDEX } from './ZPOPMAX'; +// export { FIRST_KEY_INDEX } from './ZPOPMAX'; -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformZPopMaxArguments(key), - count.toString() - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// count: number +// ): RedisCommandArguments { +// return [ +// ...transformZPopMaxArguments(key), +// count.toString() +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZPOPMIN.ts b/packages/client/lib/commands/ZPOPMIN.ts index 053ffd2d2ce..dea8948b8bc 100644 --- a/packages/client/lib/commands/ZPOPMIN.ts +++ b/packages/client/lib/commands/ZPOPMIN.ts @@ -1,12 +1,12 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return [ - 'ZPOPMIN', - key - ]; -} +// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +// return [ +// 'ZPOPMIN', +// key +// ]; +// } -export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; +// export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.ts index 54125ade0ac..385043be658 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.ts @@ -1,16 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformZPopMinArguments } from './ZPOPMIN'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformArguments as transformZPopMinArguments } from './ZPOPMIN'; -export { FIRST_KEY_INDEX } from './ZPOPMIN'; +// export { FIRST_KEY_INDEX } from './ZPOPMIN'; -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformZPopMinArguments(key), - count.toString() - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// count: number +// ): RedisCommandArguments { +// return [ +// ...transformZPopMinArguments(key), +// count.toString() +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZRANDMEMBER.ts b/packages/client/lib/commands/ZRANDMEMBER.ts index 00420872c0c..449eb281c66 100644 --- a/packages/client/lib/commands/ZRANDMEMBER.ts +++ b/packages/client/lib/commands/ZRANDMEMBER.ts @@ -1,11 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['ZRANDMEMBER', key]; -} - -export declare function transformReply(): RedisCommandArgument | null; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT.ts index 3aa91902c62..89b921f007a 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT.ts @@ -1,16 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformArguments as transformZRandMemberArguments } from './ZRANDMEMBER'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import ZRANDMEMBER from './ZRANDMEMBER'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANDMEMBER'; - -export function transformArguments( - key: RedisCommandArgument, - count: number -): RedisCommandArguments { - return [ - ...transformZRandMemberArguments(key), - count.toString() - ]; -} - -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: ZRANDMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANDMEMBER.IS_READ_ONLY, + transformArguments(key: RedisArgument, count: number) { + const args = ZRANDMEMBER.transformArguments(key); + args.push(count.toString()); + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts index cc9d2bc26ee..14c28d4b6c6 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.ts @@ -1,13 +1,14 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformZRandMemberCountArguments } from './ZRANDMEMBER_COUNT'; +import { Command, RedisArgument } from '../RESP/types'; +import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; +import { transformSortedSetReply } from './generic-transformers'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANDMEMBER_COUNT'; - -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformZRandMemberCountArguments(...args), - 'WITHSCORES' - ]; -} - -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: ZRANDMEMBER_COUNT.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANDMEMBER_COUNT.IS_READ_ONLY, + transformArguments(key: RedisArgument, count: number) { + const args = ZRANDMEMBER_COUNT.transformArguments(key, count); + args.push('WITHSCORES'); + return args; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGE.ts b/packages/client/lib/commands/ZRANGE.ts index 83f09aaa1b0..9683c09ab5e 100644 --- a/packages/client/lib/commands/ZRANGE.ts +++ b/packages/client/lib/commands/ZRANGE.ts @@ -1,51 +1,54 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; interface ZRangeOptions { - BY?: 'SCORE' | 'LEX'; - REV?: true; - LIMIT?: { - offset: number; - count: number; - }; + BY?: 'SCORE' | 'LEX'; + REV?: boolean; + LIMIT?: { + offset: number; + count: number; + }; } -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument | number, - max: RedisCommandArgument | number, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + min: RedisArgument | number, + max: RedisArgument | number, options?: ZRangeOptions -): RedisCommandArguments { + ) { const args = [ - 'ZRANGE', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) + 'ZRANGE', + key, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) ]; switch (options?.BY) { - case 'SCORE': - args.push('BYSCORE'); - break; + case 'SCORE': + args.push('BYSCORE'); + break; - case 'LEX': - args.push('BYLEX'); - break; + case 'LEX': + args.push('BYLEX'); + break; } if (options?.REV) { - args.push('REV'); + args.push('REV'); } if (options?.LIMIT) { - args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); + args.push( + 'LIMIT', + options.LIMIT.offset.toString(), + options.LIMIT.count.toString() + ); } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGEBYLEX.ts b/packages/client/lib/commands/ZRANGEBYLEX.ts index d6e621a562f..d06debb008b 100644 --- a/packages/client/lib/commands/ZRANGEBYLEX.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.ts @@ -1,35 +1,35 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformStringDoubleArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export interface ZRangeByLexOptions { - LIMIT?: { - offset: number; - count: number; - }; -} +// export interface ZRangeByLexOptions { +// LIMIT?: { +// offset: number; +// count: number; +// }; +// } -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument, - max: RedisCommandArgument, - options?: ZRangeByLexOptions -): RedisCommandArguments { - const args = [ - 'ZRANGEBYLEX', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) - ]; +// export function transformArguments( +// key: RedisCommandArgument, +// min: RedisCommandArgument, +// max: RedisCommandArgument, +// options?: ZRangeByLexOptions +// ): RedisCommandArguments { +// const args = [ +// 'ZRANGEBYLEX', +// key, +// transformStringDoubleArgument(min), +// transformStringDoubleArgument(max) +// ]; - if (options?.LIMIT) { - args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); - } +// if (options?.LIMIT) { +// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); +// } - return args; -} +// return args; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE.ts b/packages/client/lib/commands/ZRANGEBYSCORE.ts index 5ab7d7ac727..562dd6b5d0d 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.ts @@ -1,35 +1,35 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformStringDoubleArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export interface ZRangeByScoreOptions { - LIMIT?: { - offset: number; - count: number; - }; -} +// export interface ZRangeByScoreOptions { +// LIMIT?: { +// offset: number; +// count: number; +// }; +// } -export function transformArguments( - key: RedisCommandArgument, - min: string | number, - max: string | number, - options?: ZRangeByScoreOptions -): RedisCommandArguments { - const args = [ - 'ZRANGEBYSCORE', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) - ]; +// export function transformArguments( +// key: RedisCommandArgument, +// min: string | number, +// max: string | number, +// options?: ZRangeByScoreOptions +// ): RedisCommandArguments { +// const args = [ +// 'ZRANGEBYSCORE', +// key, +// transformStringDoubleArgument(min), +// transformStringDoubleArgument(max) +// ]; - if (options?.LIMIT) { - args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); - } +// if (options?.LIMIT) { +// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); +// } - return args; -} +// return args; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts index c7266f1c062..1cd2df10f0a 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts @@ -1,18 +1,18 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { ZRangeByScoreOptions, transformArguments as transformZRangeByScoreArguments } from './ZRANGEBYSCORE'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { ZRangeByScoreOptions, transformArguments as transformZRangeByScoreArguments } from './ZRANGEBYSCORE'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGEBYSCORE'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGEBYSCORE'; -export function transformArguments( - key: RedisCommandArgument, - min: string | number, - max: string | number, - options?: ZRangeByScoreOptions -): RedisCommandArguments { - return [ - ...transformZRangeByScoreArguments(key, min, max, options), - 'WITHSCORES' - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// min: string | number, +// max: string | number, +// options?: ZRangeByScoreOptions +// ): RedisCommandArguments { +// return [ +// ...transformZRangeByScoreArguments(key, min, max, options), +// 'WITHSCORES' +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZRANGESTORE.ts b/packages/client/lib/commands/ZRANGESTORE.ts index 28067ceabe0..96fd8302de4 100644 --- a/packages/client/lib/commands/ZRANGESTORE.ts +++ b/packages/client/lib/commands/ZRANGESTORE.ts @@ -1,62 +1,62 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; - -export const FIRST_KEY_INDEX = 1; - -interface ZRangeStoreOptions { - BY?: 'SCORE' | 'LEX'; - REV?: true; - LIMIT?: { - offset: number; - count: number; - }; - WITHSCORES?: true; -} - -export function transformArguments( - dst: RedisCommandArgument, - src: RedisCommandArgument, - min: RedisCommandArgument | number, - max: RedisCommandArgument | number, - options?: ZRangeStoreOptions -): RedisCommandArguments { - const args = [ - 'ZRANGESTORE', - dst, - src, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) - ]; - - switch (options?.BY) { - case 'SCORE': - args.push('BYSCORE'); - break; - - case 'LEX': - args.push('BYLEX'); - break; - } - - if (options?.REV) { - args.push('REV'); - } - - if (options?.LIMIT) { - args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); - } - - if (options?.WITHSCORES) { - args.push('WITHSCORES'); - } - - return args; -} - -export function transformReply(reply: number): number { - if (typeof reply !== 'number') { - throw new TypeError(`Upgrade to Redis 6.2.5 and up (https://github.com/redis/redis/pull/9089)`); - } - - return reply; -} +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformStringDoubleArgument } from './generic-transformers'; + +// export const FIRST_KEY_INDEX = 1; + +// interface ZRangeStoreOptions { +// BY?: 'SCORE' | 'LEX'; +// REV?: true; +// LIMIT?: { +// offset: number; +// count: number; +// }; +// WITHSCORES?: true; +// } + +// export function transformArguments( +// dst: RedisCommandArgument, +// src: RedisCommandArgument, +// min: RedisCommandArgument | number, +// max: RedisCommandArgument | number, +// options?: ZRangeStoreOptions +// ): RedisCommandArguments { +// const args = [ +// 'ZRANGESTORE', +// dst, +// src, +// transformStringDoubleArgument(min), +// transformStringDoubleArgument(max) +// ]; + +// switch (options?.BY) { +// case 'SCORE': +// args.push('BYSCORE'); +// break; + +// case 'LEX': +// args.push('BYLEX'); +// break; +// } + +// if (options?.REV) { +// args.push('REV'); +// } + +// if (options?.LIMIT) { +// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); +// } + +// if (options?.WITHSCORES) { +// args.push('WITHSCORES'); +// } + +// return args; +// } + +// export function transformReply(reply: number): number { +// if (typeof reply !== 'number') { +// throw new TypeError(`Upgrade to Redis 6.2.5 and up (https://github.com/redis/redis/pull/9089)`); +// } + +// return reply; +// } diff --git a/packages/client/lib/commands/ZRANGE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts index 23ea4d6337c..d05b856263c 100644 --- a/packages/client/lib/commands/ZRANGE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts @@ -1,13 +1,13 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformZRangeArguments } from './ZRANGE'; +// import { RedisCommandArguments } from '.'; +// import { transformArguments as transformZRangeArguments } from './ZRANGE'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGE'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGE'; -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformZRangeArguments(...args), - 'WITHSCORES' - ]; -} +// export function transformArguments(...args: Parameters): RedisCommandArguments { +// return [ +// ...transformZRangeArguments(...args), +// 'WITHSCORES' +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZRANK.ts b/packages/client/lib/commands/ZRANK.ts index 33439ea4b55..11184c0a28f 100644 --- a/packages/client/lib/commands/ZRANK.ts +++ b/packages/client/lib/commands/ZRANK.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, NullReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, member: RedisArgument) { return ['ZRANK', key, member]; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZREM.ts b/packages/client/lib/commands/ZREM.ts index a5e1ff559cf..54f55841fce 100644 --- a/packages/client/lib/commands/ZREM.ts +++ b/packages/client/lib/commands/ZREM.ts @@ -1,13 +1,14 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + member: RedisVariadicArgument + ) { return pushVariadicArguments(['ZREM', key], member); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZREMRANGEBYLEX.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.ts index f1f3908f538..8c7adf0c91f 100644 --- a/packages/client/lib/commands/ZREMRANGEBYLEX.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.ts @@ -1,19 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformStringDoubleArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument | number, - max: RedisCommandArgument | number -): RedisCommandArguments { - return [ - 'ZREMRANGEBYLEX', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// min: RedisCommandArgument | number, +// max: RedisCommandArgument | number +// ): RedisCommandArguments { +// return [ +// 'ZREMRANGEBYLEX', +// key, +// transformStringDoubleArgument(min), +// transformStringDoubleArgument(max) +// ]; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZREMRANGEBYRANK.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.ts index c50d06e3bf6..bfb36cb6cbd 100644 --- a/packages/client/lib/commands/ZREMRANGEBYRANK.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.ts @@ -1,13 +1,13 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - start: number, - stop: number -): RedisCommandArguments { - return ['ZREMRANGEBYRANK', key, start.toString(), stop.toString()]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// start: number, +// stop: number +// ): RedisCommandArguments { +// return ['ZREMRANGEBYRANK', key, start.toString(), stop.toString()]; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZREMRANGEBYSCORE.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.ts index 12d1eff811e..802e42db8da 100644 --- a/packages/client/lib/commands/ZREMRANGEBYSCORE.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.ts @@ -1,19 +1,19 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { transformStringNumberInfinityArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { transformStringDoubleArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export function transformArguments( - key: RedisCommandArgument, - min: RedisCommandArgument | number, - max: RedisCommandArgument | number, -): RedisCommandArguments { - return [ - 'ZREMRANGEBYSCORE', - key, - transformStringNumberInfinityArgument(min), - transformStringNumberInfinityArgument(max) - ]; -} +// export function transformArguments( +// key: RedisCommandArgument, +// min: RedisCommandArgument | number, +// max: RedisCommandArgument | number, +// ): RedisCommandArguments { +// return [ +// 'ZREMRANGEBYSCORE', +// key, +// transformStringDoubleArgument(min), +// transformStringDoubleArgument(max) +// ]; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZREVRANK.ts b/packages/client/lib/commands/ZREVRANK.ts index b88936c0c92..3bf52d21de5 100644 --- a/packages/client/lib/commands/ZREVRANK.ts +++ b/packages/client/lib/commands/ZREVRANK.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { NumberReply, NullReply, Command, RedisArgument } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, member: RedisArgument) { return ['ZREVRANK', key, member]; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index 2377b90aace..50c9c5fa9cb 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -1,5 +1,6 @@ import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; -import { ScanOptions, ZMember, pushScanArguments, transformNumberInfinityReply } from './generic-transformers'; +import { ScanCommonOptions, pushScanArguments } from './SCAN'; +import { ZMember, transformDoubleReply } from './generic-transformers'; export interface HScanEntry { field: BlobStringReply; @@ -12,7 +13,7 @@ export default { transformArguments( key: RedisArgument, cursor: number, - options?: ScanOptions + options?: ScanCommonOptions ) { return pushScanArguments(['ZSCAN', key], cursor, options); }, @@ -22,7 +23,7 @@ export default { while (i < rawMembers.length) { members.push({ value: rawMembers[i++], - score: transformNumberInfinityReply(rawMembers[i++]) + score: transformDoubleReply(rawMembers[i++]) } satisfies ZMember); } diff --git a/packages/client/lib/commands/ZSCORE.ts b/packages/client/lib/commands/ZSCORE.ts index 118abc10850..b62e6b53059 100644 --- a/packages/client/lib/commands/ZSCORE.ts +++ b/packages/client/lib/commands/ZSCORE.ts @@ -1,14 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -export const FIRST_KEY_INDEX = 1; +import { DoubleReply, NullReply, Command, RedisArgument } from '../RESP/types'; +import { transformNullableDoubleReply } from './generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - member: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, member: RedisArgument) { return ['ZSCORE', key, member]; -} - -export { transformNumberInfinityNullReply as transformReply } from './generic-transformers'; + }, + transformReply: { + 2: transformNullableDoubleReply, + 3: undefined as unknown as () => DoubleReply | NullReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZUNION.ts b/packages/client/lib/commands/ZUNION.ts index 3f57c5ba724..537aecc8508 100644 --- a/packages/client/lib/commands/ZUNION.ts +++ b/packages/client/lib/commands/ZUNION.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 2; +// export const FIRST_KEY_INDEX = 2; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -interface ZUnionOptions { - WEIGHTS?: Array; - AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; -} +// interface ZUnionOptions { +// WEIGHTS?: Array; +// AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; +// } -export function transformArguments( - keys: Array | RedisCommandArgument, - options?: ZUnionOptions -): RedisCommandArguments { - const args = pushVariadicArgument(['ZUNION'], keys); +// export function transformArguments( +// keys: Array | RedisCommandArgument, +// options?: ZUnionOptions +// ): RedisCommandArguments { +// const args = pushVariadicArgument(['ZUNION'], keys); - if (options?.WEIGHTS) { - args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); - } +// if (options?.WEIGHTS) { +// args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); +// } - if (options?.AGGREGATE) { - args.push('AGGREGATE', options.AGGREGATE); - } +// if (options?.AGGREGATE) { +// args.push('AGGREGATE', options.AGGREGATE); +// } - return args; -} +// return args; +// } -export declare function transformReply(): Array; +// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/ZUNIONSTORE.ts b/packages/client/lib/commands/ZUNIONSTORE.ts index 4795161d00b..dab0417fac9 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.ts @@ -1,29 +1,29 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { pushVariadicArgument } from './generic-transformers'; +// import { RedisCommandArgument, RedisCommandArguments } from '.'; +// import { pushVariadicArgument } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -interface ZUnionOptions { - WEIGHTS?: Array; - AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; -} +// interface ZUnionOptions { +// WEIGHTS?: Array; +// AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; +// } -export function transformArguments( - destination: RedisCommandArgument, - keys: Array | RedisCommandArgument, - options?: ZUnionOptions -): RedisCommandArguments { - const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); +// export function transformArguments( +// destination: RedisCommandArgument, +// keys: Array | RedisCommandArgument, +// options?: ZUnionOptions +// ): RedisCommandArguments { +// const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); - if (options?.WEIGHTS) { - args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); - } +// if (options?.WEIGHTS) { +// args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); +// } - if (options?.AGGREGATE) { - args.push('AGGREGATE', options.AGGREGATE); - } +// if (options?.AGGREGATE) { +// args.push('AGGREGATE', options.AGGREGATE); +// } - return args; -} +// return args; +// } -export declare function transformReply(): number; +// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.ts index 168cc929ac8..54a43da7ecf 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.ts @@ -1,13 +1,13 @@ -import { RedisCommandArguments } from '.'; -import { transformArguments as transformZUnionArguments } from './ZUNION'; +// import { RedisCommandArguments } from '.'; +// import { transformArguments as transformZUnionArguments } from './ZUNION'; -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZUNION'; +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZUNION'; -export function transformArguments(...args: Parameters): RedisCommandArguments { - return [ - ...transformZUnionArguments(...args), - 'WITHSCORES' - ]; -} +// export function transformArguments(...args: Parameters): RedisCommandArguments { +// return [ +// ...transformZUnionArguments(...args), +// 'WITHSCORES' +// ]; +// } -export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index dd89610718e..9a8eef476e4 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,160 +1,156 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { ArrayReply, BlobStringReply, NullReply, RedisArgument } from '../RESP/types'; +import { ArrayReply, BlobStringReply, CommandArguments, DoubleReply, NullReply, RedisArgument, Resp2Reply } from '../RESP/types'; -export function transformBooleanReply(reply: number): boolean { - return reply === 1; -} +// export function transformBooleanReply(reply: number): boolean { +// return reply === 1; +// } -export function transformBooleanArrayReply(reply: Array): Array { - return reply.map(transformBooleanReply); -} +// export function transformBooleanArrayReply(reply: Array): Array { +// return reply.map(transformBooleanReply); +// } export type BitValue = 0 | 1; -export interface ScanOptions { - MATCH?: string; - COUNT?: number; -} - -export function pushScanArguments( - args: RedisCommandArguments, - cursor: number, - options?: ScanOptions -): RedisCommandArguments { - args.push(cursor.toString()); - - if (options?.MATCH) { - args.push('MATCH', options.MATCH); - } - - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } - - return args; -} - -export function transformNumberInfinityReply(reply: BlobStringReply): number { - switch (reply.toString()) { - case '+inf': - return Infinity; +export function transformDoubleReply(reply: BlobStringReply): number { + switch (reply.toString()) { + case '+inf': + return Infinity; - case '-inf': - return -Infinity; + case '-inf': + return -Infinity; - default: - return Number(reply); - } + default: + return Number(reply); + } } -export function transformNumberInfinityNullReply(reply: BlobStringReply | NullReply): number | null { - if (reply === null) return null; +export function transformNullableDoubleReply(reply: BlobStringReply | NullReply): number | null { + if (reply === null) return null; - return transformNumberInfinityReply(reply); + return transformDoubleReply(reply); } -export function transformNumberInfinityNullArrayReply(reply: Array): Array { - return reply.map(transformNumberInfinityNullReply); +export function transformArrayNullableDoubleReply(reply: Array): Array { + return reply.map(transformNullableDoubleReply); } -export function transformNumberInfinityArgument(num: number): string { - switch (num) { - case Infinity: - return '+inf'; +export function transformDoubleArgument(num: number): string { + switch (num) { + case Infinity: + return '+inf'; - case -Infinity: - return '-inf'; + case -Infinity: + return '-inf'; - default: - return num.toString(); - } + default: + return num.toString(); + } } -export function transformStringNumberInfinityArgument(num: RedisCommandArgument | number): RedisCommandArgument { - if (typeof num !== 'number') return num; +export function transformStringDoubleArgument(num: RedisArgument | number): RedisArgument { + if (typeof num !== 'number') return num; - return transformNumberInfinityArgument(num); + return transformDoubleArgument(num); } export function transformTuplesReply( - reply: ArrayReply + reply: ArrayReply ): Record { - const message = Object.create(null); + const message = Object.create(null); - for (let i = 0; i < reply.length; i += 2) { - message[reply[i].toString()] = reply[i + 1]; - } + for (let i = 0; i < reply.length; i += 2) { + message[reply[i].toString()] = reply[i + 1]; + } - return message; + return message; } export interface StreamMessageReply { - id: RedisCommandArgument; - message: Record; + id: RedisArgument; + message: Record; } export type StreamMessagesReply = Array; export function transformStreamMessagesReply(reply: Array): StreamMessagesReply { - const messages = []; + const messages = []; - for (const [id, message] of reply) { - messages.push({ - id, - message: transformTuplesReply(message) - }); - } + for (const [id, message] of reply) { + messages.push({ + id, + message: transformTuplesReply(message) + }); + } - return messages; + return messages; } export type StreamsMessagesReply = Array<{ - name: RedisCommandArgument; - messages: StreamMessagesReply; + name: RedisArgument; + messages: StreamMessagesReply; }> | null; export function transformStreamsMessagesReply(reply: Array | null): StreamsMessagesReply | null { - if (reply === null) return null; + if (reply === null) return null; - return reply.map(([name, rawMessages]) => ({ - name, - messages: transformStreamMessagesReply(rawMessages) - })); + return reply.map(([name, rawMessages]) => ({ + name, + messages: transformStreamMessagesReply(rawMessages) + })); } export interface ZMember { - score: number; - value: RedisArgument; + score: number; + value: RedisArgument; } export function transformSortedSetMemberNullReply( - reply: [BlobStringReply, BlobStringReply] | [] + reply: [BlobStringReply, BlobStringReply] | [] ): ZMember | null { - if (!reply.length) return null; + if (!reply.length) return null; - return transformSortedSetMemberReply(reply); + return transformSortedSetMemberReply(reply); } export function transformSortedSetMemberReply( - reply: [BlobStringReply, BlobStringReply] + reply: [BlobStringReply, BlobStringReply] ): ZMember { - return { - value: reply[0], - score: transformNumberInfinityReply(reply[1]) - }; + return { + value: reply[0], + score: transformDoubleReply(reply[1]) + }; } -export function transformSortedSetWithScoresReply(reply: ArrayReply): Array { +export const transformSortedSetReply = { + 2: (reply: ArrayReply) => { const members = []; - for (let i = 0; i < reply.length; i += 2) { - members.push({ - value: reply[i], - score: transformNumberInfinityReply(reply[i + 1]) - }); + members.push({ + value: reply[i], + score: transformDoubleReply(reply[i + 1]) + }); } return members; + }, + 3: (reply: ArrayReply<[BlobStringReply, DoubleReply]>) => { + return reply.map(([value, score]) => ({ + value, + score + })); + } +} + +export function transformSortedSetWithScoresReply(reply: ArrayReply): Array { + const members = []; + + for (let i = 0; i < reply.length; i += 2) { + members.push({ + value: reply[i], + score: transformDoubleReply(reply[i + 1]) + }); + } + + return members; } export type ListSide = 'LEFT' | 'RIGHT'; @@ -162,53 +158,53 @@ export type ListSide = 'LEFT' | 'RIGHT'; export type SortedSetSide = 'MIN' | 'MAX'; export interface LMPopOptions { - COUNT?: number; + COUNT?: number; } export function transformLMPopArguments( - args: RedisCommandArguments, - keys: RedisCommandArgument | Array, - side: ListSide, - options?: LMPopOptions -): RedisCommandArguments { - pushVariadicArgument(args, keys); + args: CommandArguments, + keys: RedisVariadicArgument, + side: ListSide, + options?: LMPopOptions +): CommandArguments { + pushVariadicArgument(args, keys); - args.push(side); + args.push(side); - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } - return args; + return args; } type GeoCountArgument = number | { - value: number; - ANY?: true + value: number; + ANY?: true }; export function pushGeoCountArgument( - args: RedisCommandArguments, - count: GeoCountArgument | undefined -): RedisCommandArguments { - if (typeof count === 'number') { - args.push('COUNT', count.toString()); - } else if (count) { - args.push('COUNT', count.value.toString()); - - if (count.ANY) { - args.push('ANY'); - } + args: CommandArguments, + count: GeoCountArgument | undefined +): CommandArguments { + if (typeof count === 'number') { + args.push('COUNT', count.toString()); + } else if (count) { + args.push('COUNT', count.value.toString()); + + if (count.ANY) { + args.push('ANY'); } + } - return args; + return args; } export type GeoUnits = 'm' | 'km' | 'mi' | 'ft'; export interface GeoCoordinates { - longitude: string | number; - latitude: string | number; + longitude: RedisArgument | number; + latitude: RedisArgument | number; } type GeoSearchFromMember = string; @@ -216,456 +212,412 @@ type GeoSearchFromMember = string; export type GeoSearchFrom = GeoSearchFromMember | GeoCoordinates; interface GeoSearchByRadius { - radius: number; - unit: GeoUnits; + radius: number; + unit: GeoUnits; } interface GeoSearchByBox { - width: number; - height: number; - unit: GeoUnits; + width: number; + height: number; + unit: GeoUnits; } export type GeoSearchBy = GeoSearchByRadius | GeoSearchByBox; export interface GeoSearchOptions { - SORT?: 'ASC' | 'DESC'; - COUNT?: GeoCountArgument; + SORT?: 'ASC' | 'DESC'; + COUNT?: GeoCountArgument; } export function pushGeoSearchArguments( - args: RedisCommandArguments, - key: RedisCommandArgument, - from: GeoSearchFrom, - by: GeoSearchBy, - options?: GeoSearchOptions -): RedisCommandArguments { - args.push(key); - - if (typeof from === 'string') { - args.push('FROMMEMBER', from); - } else { - args.push('FROMLONLAT', from.longitude.toString(), from.latitude.toString()); - } + args: CommandArguments, + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchOptions +): CommandArguments { + args.push(key); - if ('radius' in by) { - args.push('BYRADIUS', by.radius.toString()); - } else { - args.push('BYBOX', by.width.toString(), by.height.toString()); - } + if (typeof from === 'string') { + args.push('FROMMEMBER', from); + } else { + args.push('FROMLONLAT', from.longitude.toString(), from.latitude.toString()); + } - args.push(by.unit); + if ('radius' in by) { + args.push('BYRADIUS', by.radius.toString()); + } else { + args.push('BYBOX', by.width.toString(), by.height.toString()); + } - if (options?.SORT) { - args.push(options.SORT); - } + args.push(by.unit); + + if (options?.SORT) { + args.push(options.SORT); + } - pushGeoCountArgument(args, options?.COUNT); + pushGeoCountArgument(args, options?.COUNT); - return args; + return args; } export function pushGeoRadiusArguments( - args: RedisCommandArguments, - key: RedisCommandArgument, - from: GeoSearchFrom, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): RedisCommandArguments { - args.push(key); - - if (typeof from === 'string') { - args.push(from); - } else { - args.push( - from.longitude.toString(), - from.latitude.toString() - ); - } - + args: CommandArguments, + key: RedisArgument, + from: GeoSearchFrom, + radius: number, + unit: GeoUnits, + options?: GeoSearchOptions +): CommandArguments { + args.push(key); + + if (typeof from === 'string') { + args.push(from); + } else { args.push( - radius.toString(), - unit + from.longitude.toString(), + from.latitude.toString() ); + } - if (options?.SORT) { - args.push(options.SORT); - } + args.push( + radius.toString(), + unit + ); + + if (options?.SORT) { + args.push(options.SORT); + } - pushGeoCountArgument(args, options?.COUNT); + pushGeoCountArgument(args, options?.COUNT); - return args; + return args; } export interface GeoRadiusStoreOptions extends GeoSearchOptions { - STOREDIST?: boolean; + STOREDIST?: boolean; } export function pushGeoRadiusStoreArguments( - args: RedisCommandArguments, - key: RedisCommandArgument, - from: GeoSearchFrom, - radius: number, - unit: GeoUnits, - destination: RedisCommandArgument, - options?: GeoRadiusStoreOptions -): RedisCommandArguments { - pushGeoRadiusArguments(args, key, from, radius, unit, options); - - if (options?.STOREDIST) { - args.push('STOREDIST', destination); - } else { - args.push('STORE', destination); - } + args: CommandArguments, + key: RedisArgument, + from: GeoSearchFrom, + radius: number, + unit: GeoUnits, + destination: RedisArgument, + options?: GeoRadiusStoreOptions +): CommandArguments { + pushGeoRadiusArguments(args, key, from, radius, unit, options); + + if (options?.STOREDIST) { + args.push('STOREDIST', destination); + } else { + args.push('STORE', destination); + } - return args; + return args; } export enum GeoReplyWith { - DISTANCE = 'WITHDIST', - HASH = 'WITHHASH', - COORDINATES = 'WITHCOORD' + DISTANCE = 'WITHDIST', + HASH = 'WITHHASH', + COORDINATES = 'WITHCOORD' } export interface GeoReplyWithMember { - member: string; - distance?: number; - hash?: string; - coordinates?: { - longitude: string; - latitude: string; - }; + member: string; + distance?: number; + hash?: string; + coordinates?: { + longitude: string; + latitude: string; + }; } export function transformGeoMembersWithReply(reply: Array>, replyWith: Array): Array { - const replyWithSet = new Set(replyWith); - - let index = 0; - const distanceIndex = replyWithSet.has(GeoReplyWith.DISTANCE) && ++index, - hashIndex = replyWithSet.has(GeoReplyWith.HASH) && ++index, - coordinatesIndex = replyWithSet.has(GeoReplyWith.COORDINATES) && ++index; - - return reply.map(member => { - const transformedMember: GeoReplyWithMember = { - member: member[0] - }; - - if (distanceIndex) { - transformedMember.distance = member[distanceIndex]; - } - - if (hashIndex) { - transformedMember.hash = member[hashIndex]; - } - - if (coordinatesIndex) { - const [longitude, latitude] = member[coordinatesIndex]; - transformedMember.coordinates = { - longitude, - latitude - }; - } - - return transformedMember; - }); + const replyWithSet = new Set(replyWith); + + let index = 0; + const distanceIndex = replyWithSet.has(GeoReplyWith.DISTANCE) && ++index, + hashIndex = replyWithSet.has(GeoReplyWith.HASH) && ++index, + coordinatesIndex = replyWithSet.has(GeoReplyWith.COORDINATES) && ++index; + + return reply.map(member => { + const transformedMember: GeoReplyWithMember = { + member: member[0] + }; + + if (distanceIndex) { + transformedMember.distance = member[distanceIndex]; + } + + if (hashIndex) { + transformedMember.hash = member[hashIndex]; + } + + if (coordinatesIndex) { + const [longitude, latitude] = member[coordinatesIndex]; + transformedMember.coordinates = { + longitude, + latitude + }; + } + + return transformedMember; + }); } export function transformEXAT(EXAT: number | Date): string { - return (typeof EXAT === 'number' ? EXAT : Math.floor(EXAT.getTime() / 1000)).toString(); + return (typeof EXAT === 'number' ? EXAT : Math.floor(EXAT.getTime() / 1000)).toString(); } export function transformPXAT(PXAT: number | Date): string { - return (typeof PXAT === 'number' ? PXAT : PXAT.getTime()).toString(); + return (typeof PXAT === 'number' ? PXAT : PXAT.getTime()).toString(); } export interface EvalOptions { - keys?: Array; - arguments?: Array; + keys?: Array; + arguments?: Array; } export function evalFirstKeyIndex(options?: EvalOptions): string | undefined { - return options?.keys?.[0]; + return options?.keys?.[0]; } export function pushEvalArguments(args: Array, options?: EvalOptions): Array { - if (options?.keys) { - args.push( - options.keys.length.toString(), - ...options.keys - ); - } else { - args.push('0'); - } + if (options?.keys) { + args.push( + options.keys.length.toString(), + ...options.keys + ); + } else { + args.push('0'); + } - if (options?.arguments) { - args.push(...options.arguments); - } + if (options?.arguments) { + args.push(...options.arguments); + } - return args; + return args; } -export function pushVariadicArguments(args: RedisCommandArguments, value: RedisCommandArgument | Array): RedisCommandArguments { - if (Array.isArray(value)) { - // https://github.com/redis/node-redis/pull/2160 - args = args.concat(value); - } else { - args.push(value); - } +export function pushVariadicArguments(args: CommandArguments, value: RedisVariadicArgument): CommandArguments { + if (Array.isArray(value)) { + // https://github.com/redis/node-redis/pull/2160 + args = args.concat(value); + } else { + args.push(value); + } - return args; + return args; } export function pushVariadicNumberArguments( - args: RedisCommandArguments, - value: number | Array -): RedisCommandArguments { - if (Array.isArray(value)) { - for (const item of value) { - args.push(item.toString()); - } - } else { - args.push(value.toString()); + args: CommandArguments, + value: number | Array +): CommandArguments { + if (Array.isArray(value)) { + for (const item of value) { + args.push(item.toString()); } + } else { + args.push(value.toString()); + } - return args; + return args; } export type RedisVariadicArgument = RedisArgument | Array; export function pushVariadicArgument( - args: Array, - value: RedisVariadicArgument -): RedisCommandArguments { - if (Array.isArray(value)) { - args.push(value.length.toString(), ...value); - } else { - args.push('1', value); - } + args: Array, + value: RedisVariadicArgument +): CommandArguments { + if (Array.isArray(value)) { + args.push(value.length.toString(), ...value); + } else { + args.push('1', value); + } - return args; + return args; } export function pushOptionalVariadicArgument( - args: RedisCommandArguments, - name: RedisCommandArgument, - value: undefined | RedisCommandArgument | Array -): RedisCommandArguments { - if (value === undefined) return args; + args: CommandArguments, + name: RedisArgument, + value?: RedisVariadicArgument +): CommandArguments { + if (value === undefined) return args; - args.push(name); + args.push(name); - return pushVariadicArgument(args, value); + return pushVariadicArgument(args, value); } export enum CommandFlags { - WRITE = 'write', // command may result in modifications - READONLY = 'readonly', // command will never modify keys - DENYOOM = 'denyoom', // reject command if currently out of memory - ADMIN = 'admin', // server admin command - PUBSUB = 'pubsub', // pubsub-related command - NOSCRIPT = 'noscript', // deny this command from scripts - RANDOM = 'random', // command has random results, dangerous for scripts - SORT_FOR_SCRIPT = 'sort_for_script', // if called from script, sort output - LOADING = 'loading', // allow command while database is loading - STALE = 'stale', // allow command while replica has stale data - SKIP_MONITOR = 'skip_monitor', // do not show this command in MONITOR - ASKING = 'asking', // cluster related - accept even if importing - FAST = 'fast', // command operates in constant or log(N) time. Used for latency monitoring. - MOVABLEKEYS = 'movablekeys' // keys have no pre-determined position. You must discover keys yourself. + WRITE = 'write', // command may result in modifications + READONLY = 'readonly', // command will never modify keys + DENYOOM = 'denyoom', // reject command if currently out of memory + ADMIN = 'admin', // server admin command + PUBSUB = 'pubsub', // pubsub-related command + NOSCRIPT = 'noscript', // deny this command from scripts + RANDOM = 'random', // command has random results, dangerous for scripts + SORT_FOR_SCRIPT = 'sort_for_script', // if called from script, sort output + LOADING = 'loading', // allow command while database is loading + STALE = 'stale', // allow command while replica has stale data + SKIP_MONITOR = 'skip_monitor', // do not show this command in MONITOR + ASKING = 'asking', // cluster related - accept even if importing + FAST = 'fast', // command operates in constant or log(N) time. Used for latency monitoring. + MOVABLEKEYS = 'movablekeys' // keys have no pre-determined position. You must discover keys yourself. } export enum CommandCategories { - KEYSPACE = '@keyspace', - READ = '@read', - WRITE = '@write', - SET = '@set', - SORTEDSET = '@sortedset', - LIST = '@list', - HASH = '@hash', - STRING = '@string', - BITMAP = '@bitmap', - HYPERLOGLOG = '@hyperloglog', - GEO = '@geo', - STREAM = '@stream', - PUBSUB = '@pubsub', - ADMIN = '@admin', - FAST = '@fast', - SLOW = '@slow', - BLOCKING = '@blocking', - DANGEROUS = '@dangerous', - CONNECTION = '@connection', - TRANSACTION = '@transaction', - SCRIPTING = '@scripting' + KEYSPACE = '@keyspace', + READ = '@read', + WRITE = '@write', + SET = '@set', + SORTEDSET = '@sortedset', + LIST = '@list', + HASH = '@hash', + STRING = '@string', + BITMAP = '@bitmap', + HYPERLOGLOG = '@hyperloglog', + GEO = '@geo', + STREAM = '@stream', + PUBSUB = '@pubsub', + ADMIN = '@admin', + FAST = '@fast', + SLOW = '@slow', + BLOCKING = '@blocking', + DANGEROUS = '@dangerous', + CONNECTION = '@connection', + TRANSACTION = '@transaction', + SCRIPTING = '@scripting' } export type CommandRawReply = [ - name: string, - arity: number, - flags: Array, - firstKeyIndex: number, - lastKeyIndex: number, - step: number, - categories: Array + name: string, + arity: number, + flags: Array, + firstKeyIndex: number, + lastKeyIndex: number, + step: number, + categories: Array ]; export type CommandReply = { - name: string, - arity: number, - flags: Set, - firstKeyIndex: number, - lastKeyIndex: number, - step: number, - categories: Set + name: string, + arity: number, + flags: Set, + firstKeyIndex: number, + lastKeyIndex: number, + step: number, + categories: Set }; export function transformCommandReply( - this: void, - [name, arity, flags, firstKeyIndex, lastKeyIndex, step, categories]: CommandRawReply + this: void, + [name, arity, flags, firstKeyIndex, lastKeyIndex, step, categories]: CommandRawReply ): CommandReply { - return { - name, - arity, - flags: new Set(flags), - firstKeyIndex, - lastKeyIndex, - step, - categories: new Set(categories) - }; + return { + name, + arity, + flags: new Set(flags), + firstKeyIndex, + lastKeyIndex, + step, + categories: new Set(categories) + }; } export enum RedisFunctionFlags { - NO_WRITES = 'no-writes', - ALLOW_OOM = 'allow-oom', - ALLOW_STALE = 'allow-stale', - NO_CLUSTER = 'no-cluster' + NO_WRITES = 'no-writes', + ALLOW_OOM = 'allow-oom', + ALLOW_STALE = 'allow-stale', + NO_CLUSTER = 'no-cluster' } export type FunctionListRawItemReply = [ - 'library_name', + 'library_name', + string, + 'engine', + string, + 'functions', + Array<[ + 'name', string, - 'engine', - string, - 'functions', - Array<[ - 'name', - string, - 'description', - string | null, - 'flags', - Array - ]> + 'description', + string | null, + 'flags', + Array + ]> ]; export interface FunctionListItemReply { - libraryName: string; - engine: string; - functions: Array<{ - name: string; - description: string | null; - flags: Array; - }>; + libraryName: string; + engine: string; + functions: Array<{ + name: string; + description: string | null; + flags: Array; + }>; } export function transformFunctionListItemReply(reply: FunctionListRawItemReply): FunctionListItemReply { - return { - libraryName: reply[1], - engine: reply[3], - functions: reply[5].map(fn => ({ - name: fn[1], - description: fn[3], - flags: fn[5] - })) - }; -} - -export interface SortOptions { - BY?: string; - LIMIT?: { - offset: number; - count: number; - }, - GET?: string | Array; - DIRECTION?: 'ASC' | 'DESC'; - ALPHA?: true; -} - -export function pushSortArguments( - args: RedisCommandArguments, - options?: SortOptions -): RedisCommandArguments { - if (options?.BY) { - args.push('BY', options.BY); - } - - if (options?.LIMIT) { - args.push( - 'LIMIT', - options.LIMIT.offset.toString(), - options.LIMIT.count.toString() - ); - } - - if (options?.GET) { - for (const pattern of (typeof options.GET === 'string' ? [options.GET] : options.GET)) { - args.push('GET', pattern); - } - } - - if (options?.DIRECTION) { - args.push(options.DIRECTION); - } - - if (options?.ALPHA) { - args.push('ALPHA'); - } - - return args; + return { + libraryName: reply[1], + engine: reply[3], + functions: reply[5].map(fn => ({ + name: fn[1], + description: fn[3], + flags: fn[5] + })) + }; } export interface SlotRange { - start: number; - end: number; + start: number; + end: number; } function pushSlotRangeArguments( - args: RedisCommandArguments, - range: SlotRange + args: CommandArguments, + range: SlotRange ): void { - args.push( - range.start.toString(), - range.end.toString() - ); + args.push( + range.start.toString(), + range.end.toString() + ); } export function pushSlotRangesArguments( - args: RedisCommandArguments, - ranges: SlotRange | Array -): RedisCommandArguments { - if (Array.isArray(ranges)) { - for (const range of ranges) { - pushSlotRangeArguments(args, range); - } - } else { - pushSlotRangeArguments(args, ranges); + args: CommandArguments, + ranges: SlotRange | Array +): CommandArguments { + if (Array.isArray(ranges)) { + for (const range of ranges) { + pushSlotRangeArguments(args, range); } + } else { + pushSlotRangeArguments(args, ranges); + } - return args; + return args; } export type RawRangeReply = [ - start: number, - end: number + start: number, + end: number ]; export interface RangeReply { - start: number; - end: number; + start: number; + end: number; } export function transformRangeReply([start, end]: RawRangeReply): RangeReply { - return { - start, - end - }; + return { + start, + end + }; } diff --git a/packages/client/package.json b/packages/client/package.json index 7cd7c758d2a..dc311791f9c 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -8,7 +8,7 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/commands/PING.spec.ts' './lib/commands/APPEND.spec.ts'", + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", "build": "tsc", "lint": "eslint ./*.ts ./lib/**/*.ts", "documentation": "typedoc" From ae0d3521b3654b5901a6e67adca6abf0f9730019 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 13:42:51 -0400 Subject: [PATCH 013/325] upgrade deps --- packages/bloom/package.json | 8 ++++---- packages/client/package.json | 18 +++++++++--------- packages/graph/package.json | 8 ++++---- packages/json/package.json | 8 ++++---- packages/search/package.json | 8 ++++---- packages/time-series/package.json | 8 ++++---- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index bba584b25ee..9bcae785dd9 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -18,13 +18,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "repository": { "type": "git", diff --git a/packages/client/package.json b/packages/client/package.json index d4d1fe0f124..90f4ebf5e0f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -21,19 +21,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", - "@types/sinon": "^10.0.13", + "@types/node": "^18.16.1", + "@types/sinon": "^10.0.14", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.0", - "@typescript-eslint/parser": "^5.57.0", - "eslint": "^8.36.0", + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "eslint": "^8.39.0", "nyc": "^15.1.0", - "release-it": "^15.9.3", - "sinon": "^15.0.3", + "release-it": "^15.10.1", + "sinon": "^15.0.4", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "engines": { "node": ">=14" diff --git a/packages/graph/package.json b/packages/graph/package.json index eb031d2e359..c37f956ffb2 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -18,13 +18,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "repository": { "type": "git", diff --git a/packages/json/package.json b/packages/json/package.json index 1c3cd7b74e3..6f30dc16779 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -18,13 +18,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "repository": { "type": "git", diff --git a/packages/search/package.json b/packages/search/package.json index 240c30e4305..27e80335c95 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -18,13 +18,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "repository": { "type": "git", diff --git a/packages/time-series/package.json b/packages/time-series/package.json index a6b2ba54678..095cc72e26b 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -18,13 +18,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "repository": { "type": "git", From cf7d4cc30e96b6233bdb88a7a1263b9a92a859d4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 13:43:16 -0400 Subject: [PATCH 014/325] wip --- package-lock.json | 511 ++++++++++++------------------- packages/test-utils/package.json | 4 +- 2 files changed, 196 insertions(+), 319 deletions(-) diff --git a/package-lock.json b/package-lock.json index 56f66c8abcc..25de62fa8ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -451,14 +451,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.0", + "espree": "^9.5.1", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -474,9 +474,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1040,9 +1040,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz", - "integrity": "sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ==", + "version": "18.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", + "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", "dev": true }, "node_modules/@types/semver": { @@ -1052,9 +1052,10 @@ "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.13", + "version": "10.0.14", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.14.tgz", + "integrity": "sha512-mn72up6cjaMyMuaPaa/AwKf6WtsSRysQC7wxFkCm1XcOKXPM1z+5Y4H5wjIVBz4gdAkjvZxVVfjA6ba1nHr5WQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" } @@ -1084,15 +1085,15 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", - "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz", + "integrity": "sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/type-utils": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/type-utils": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1118,14 +1119,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", - "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.1.tgz", + "integrity": "sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "debug": "^4.3.4" }, "engines": { @@ -1145,13 +1146,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", - "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz", + "integrity": "sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0" + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1162,13 +1163,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", - "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz", + "integrity": "sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.57.0", - "@typescript-eslint/utils": "5.57.0", + "@typescript-eslint/typescript-estree": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1189,9 +1190,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", - "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.1.tgz", + "integrity": "sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1202,13 +1203,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", - "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz", + "integrity": "sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/visitor-keys": "5.57.0", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1229,17 +1230,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", - "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", + "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.57.0", - "@typescript-eslint/types": "5.57.0", - "@typescript-eslint/typescript-estree": "5.57.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1255,12 +1256,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", - "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", + "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.57.0", + "@typescript-eslint/types": "5.59.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2143,45 +2144,6 @@ "node": ">= 8" } }, - "node_modules/cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==", - "deprecated": "cross-spawn no longer requires a build toolchain, use it instead", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "node_modules/cross-spawn-async/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/cross-spawn-async/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/cross-spawn-async/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, "node_modules/crypto-random-string": { "version": "4.0.0", "dev": true, @@ -2279,18 +2241,18 @@ "license": "MIT" }, "node_modules/default-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-3.1.0.tgz", - "integrity": "sha512-SOHecvSoairSAWxEHP/0qcsld/KtI3DargfEuELQDyHIYmS2EMgdGhHOTC1GxaYr+NLUV6kDroeiSBfnNHnn8w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", "dev": true, "dependencies": { "bundle-name": "^3.0.0", "default-browser-id": "^3.0.0", - "execa": "^5.0.0", - "xdg-default-browser": "^2.1.0" + "execa": "^7.1.1", + "titleize": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2312,83 +2274,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-browser/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-browser/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-browser/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==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/default-browser/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-browser/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/default-require-extensions": { "version": "3.0.1", "dev": true, @@ -2761,15 +2646,15 @@ } }, "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.39.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2779,9 +2664,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2843,34 +2728,39 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2914,8 +2804,9 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2925,8 +2816,9 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -4540,6 +4432,22 @@ "dev": true, "license": "ISC" }, + "node_modules/issue-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "dev": true, + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": ">=10.13" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "dev": true, @@ -4805,6 +4713,18 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "dev": true, @@ -4816,11 +4736,29 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "dev": true, "license": "MIT" }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "dev": true, @@ -4901,9 +4839,9 @@ "license": "ISC" }, "node_modules/marked": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", - "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -5568,12 +5506,12 @@ } }, "node_modules/open": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.0.0.tgz", - "integrity": "sha512-yerrN5WPzgwuE3T6rxAkT1UuMLDzs4Szpug7hy9s4gru3iOTnaU0yKc1AYOVYrBzvykce5gUdr9RPNB4R+Zc/A==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", "dev": true, "dependencies": { - "default-browser": "^3.1.0", + "default-browser": "^4.0.0", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^2.2.0" @@ -6107,12 +6045,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -6293,9 +6225,9 @@ } }, "node_modules/release-it": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.9.3.tgz", - "integrity": "sha512-yFZTGJ9lH075zEAiVB4w58GgQ+bFR4by+eNClN3sdLtTLwbEm9VXrISt+8vO1fHDH83557Fns5ub1FuhAY/a3A==", + "version": "15.10.1", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.10.1.tgz", + "integrity": "sha512-Wkk4aFHSo27vQwHIlcEy77lJwnQlh4UDQckc53gh5tKo7F22mAUEAe8SYQZJcFh7icdkf0OV70onhB1dDmeClA==", "dev": true, "dependencies": { "@iarna/toml": "2.2.5", @@ -6309,11 +6241,12 @@ "got": "12.6.0", "inquirer": "9.1.5", "is-ci": "3.0.1", + "issue-parser": "6.0.0", "lodash": "4.17.21", "mime-types": "2.1.35", "new-github-release-url": "2.0.0", "node-fetch": "3.3.1", - "open": "9.0.0", + "open": "9.1.0", "ora": "6.3.0", "os-name": "5.1.0", "promise.allsettled": "1.0.6", @@ -6822,9 +6755,9 @@ "license": "ISC" }, "node_modules/sinon": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.3.tgz", - "integrity": "sha512-si3geiRkeovP7Iel2O+qGL4NrO9vbMf3KsrJEi0ghP1l5aBkB5UxARea5j0FUsSqH3HLBh0dQPAyQ8fObRUqHw==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.4.tgz", + "integrity": "sha512-uzmfN6zx3GQaria1kwgWGeKiXSSbShBbue6Dcj0SI8fiCNFbiUDqKl57WFlY5lyhxZVUKmXvzgG2pilRQCBwWg==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -7076,15 +7009,6 @@ "node": ">=8" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -7174,12 +7098,15 @@ "dev": true }, "node_modules/titleize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz", - "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tmp": { @@ -7375,14 +7302,14 @@ } }, "node_modules/typedoc": { - "version": "0.23.28", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.28.tgz", - "integrity": "sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==", + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", "dev": true, "dependencies": { "lunr": "^2.3.9", - "marked": "^4.2.12", - "minimatch": "^7.1.3", + "marked": "^4.3.0", + "minimatch": "^9.0.0", "shiki": "^0.14.1" }, "bin": { @@ -7405,24 +7332,24 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", - "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7911,56 +7838,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/xdg-default-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/xdg-default-browser/-/xdg-default-browser-2.1.0.tgz", - "integrity": "sha512-HY4G725+IDQr16N8XOjAms5qJGArdJaWIuC7Q7A8UXIwj2mifqnPXephazyL7sIkQPvmEoPX3E0v2yFv6hQUNg==", - "dev": true, - "dependencies": { - "execa": "^0.2.2", - "titleize": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/xdg-default-browser/node_modules/execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==", - "dev": true, - "dependencies": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/xdg-default-browser/node_modules/npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==", - "dev": true, - "dependencies": { - "path-key": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xdg-default-browser/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/xregexp": { "version": "2.0.0", "dev": true, @@ -8093,13 +7970,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8117,19 +7994,19 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", - "@types/sinon": "^10.0.13", + "@types/node": "^18.16.1", + "@types/sinon": "^10.0.14", "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.57.0", - "@typescript-eslint/parser": "^5.57.0", - "eslint": "^8.36.0", + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "eslint": "^8.39.0", "nyc": "^15.1.0", - "release-it": "^15.9.3", - "sinon": "^15.0.3", + "release-it": "^15.10.1", + "sinon": "^15.0.4", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "engines": { "node": ">=14" @@ -8146,13 +8023,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8165,13 +8042,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8184,13 +8061,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "peerDependencies": { "@redis/client": "^1.0.0" @@ -8201,13 +8078,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "@types/yargs": "^17.0.24", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typescript": "^5.0.2", + "typescript": "^5.0.4", "yargs": "^17.7.1" }, "peerDependencies": { @@ -8221,13 +8098,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "nyc": "^15.1.0", - "release-it": "^15.9.3", + "release-it": "^15.10.1", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.23.28", - "typescript": "^5.0.2" + "typedoc": "^0.24.6", + "typescript": "^5.0.4" }, "peerDependencies": { "@redis/client": "^1.0.0" diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index a6e55abe0d5..0ebeea37a26 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -12,13 +12,13 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.1", - "@types/node": "^18.15.10", + "@types/node": "^18.16.1", "@types/yargs": "^17.0.24", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typescript": "^5.0.2", + "typescript": "^5.0.4", "yargs": "^17.7.1" } } From 0fbf78a1055c2e4a5b26d1e64079549495016b35 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 13:46:18 -0400 Subject: [PATCH 015/325] wip --- benchmark/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/package.json b/benchmark/package.json index 51357ce0326..73acf9d0f1c 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -9,9 +9,9 @@ "dependencies": { "hdr-histogram-js": "3.0.0", "ioredis": "5", + "redis-local": "file:../packages/client", "redis-v3": "npm:redis@3", "redis-v4": "npm:redis@4", - "redis-local": "file:../packages/client", "yargs": "17.7.1" } } From 126d2cc9cfe9c616c85c234bdf35ff375788cd1a Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 14:11:31 -0400 Subject: [PATCH 016/325] fix #2469 --- .github/workflows/documentation.yml | 2 - .github/workflows/tests.yml | 2 +- README.md | 341 +---------------- package-lock.json | 37 +- package.json | 44 +-- .../redis/.release-it.json | 0 packages/redis/README.md | 359 ++++++++++++++++++ index.ts => packages/redis/index.ts | 0 packages/redis/package.json | 37 ++ tsconfig.json => packages/redis/tsconfig.json | 2 +- tsconfig.base.json | 2 +- 11 files changed, 430 insertions(+), 396 deletions(-) rename .release-it.json => packages/redis/.release-it.json (100%) create mode 100644 packages/redis/README.md rename index.ts => packages/redis/index.ts (100%) create mode 100644 packages/redis/package.json rename tsconfig.json => packages/redis/tsconfig.json (68%) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 7b3d42bf9f4..c1232259cc1 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -17,8 +17,6 @@ jobs: uses: actions/setup-node@v2.3.0 - name: Install Packages run: npm ci - - name: Build tests tools - run: npm run build:tests-tools - name: Generate Documentation run: npm run documentation - name: Upload diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 365e9f31d3c..0693c796ff3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Install Packages run: npm ci - name: Build tests tools - run: npm run build:tests-tools + run: npm run build:client && npm run build:test-utils - name: Run Tests run: npm run test -- -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov diff --git a/README.md b/README.md index 80a34b75528..ec317d0d115 100644 --- a/README.md +++ b/README.md @@ -16,351 +16,14 @@ node-redis is a modern, high performance [Redis](https://redis.io) client for No | Name | Description | |----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [redis](./) | [![Downloads](https://img.shields.io/npm/dm/redis.svg)](https://www.npmjs.com/package/redis) [![Version](https://img.shields.io/npm/v/redis.svg)](https://www.npmjs.com/package/redis) | +| [redis](./packages/redis) | [![Downloads](https://img.shields.io/npm/dm/redis.svg)](https://www.npmjs.com/package/redis) [![Version](https://img.shields.io/npm/v/redis.svg)](https://www.npmjs.com/package/redis) | | [@redis/client](./packages/client) | [![Downloads](https://img.shields.io/npm/dm/@redis/client.svg)](https://www.npmjs.com/package/@redis/client) [![Version](https://img.shields.io/npm/v/@redis/client.svg)](https://www.npmjs.com/package/@redis/client) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/client/) | | [@redis/bloom](./packages/bloom) | [![Downloads](https://img.shields.io/npm/dm/@redis/bloom.svg)](https://www.npmjs.com/package/@redis/bloom) [![Version](https://img.shields.io/npm/v/@redis/bloom.svg)](https://www.npmjs.com/package/@redis/bloom) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/bloom/) [Redis Bloom](https://oss.redis.com/redisbloom/) commands | | [@redis/graph](./packages/graph) | [![Downloads](https://img.shields.io/npm/dm/@redis/graph.svg)](https://www.npmjs.com/package/@redis/graph) [![Version](https://img.shields.io/npm/v/@redis/graph.svg)](https://www.npmjs.com/package/@redis/graph) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/graph/) [Redis Graph](https://oss.redis.com/redisgraph/) commands | | [@redis/json](./packages/json) | [![Downloads](https://img.shields.io/npm/dm/@redis/json.svg)](https://www.npmjs.com/package/@redis/json) [![Version](https://img.shields.io/npm/v/@redis/json.svg)](https://www.npmjs.com/package/@redis/json) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/json/) [Redis JSON](https://oss.redis.com/redisjson/) commands | -| [@redis/search](./packages/search) | [![Downloads](https://img.shields.io/npm/dm/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Version](https://img.shields.io/npm/v/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/search/) [RediSearch](https://oss.redis.com/redisearch/) commands | +| [@redis/search](./packages/search) | [![Downloads](https://img.shields.io/npm/dm/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Version](https://img.shields.io/npm/v/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/search/) [RediSearch](https://oss.redis.com/redisearch/) commands | | [@redis/time-series](./packages/time-series) | [![Downloads](https://img.shields.io/npm/dm/@redis/time-series.svg)](https://www.npmjs.com/package/@redis/time-series) [![Version](https://img.shields.io/npm/v/@redis/time-series.svg)](https://www.npmjs.com/package/@redis/time-series) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/time-series/) [Redis Time-Series](https://oss.redis.com/redistimeseries/) commands | -> :warning: In version 4.1.0 we moved our subpackages from `@node-redis` to `@redis`. If you're just using `npm install redis`, you don't need to do anything—it'll upgrade automatically. If you're using the subpackages directly, you'll need to point to the new scope (e.g. `@redis/client` instead of `@node-redis/client`). - -## Installation - -Start a redis via docker: - -``` bash -docker run -p 6379:6379 -it redis/redis-stack-server:latest -``` - -To install node-redis, simply: - -```bash -npm install redis -``` - -> :warning: The new interface is clean and cool, but if you have an existing codebase, you'll want to read the [migration guide](./docs/v3-to-v4.md). - -Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! - -## Usage - -### Basic Example - -```typescript -import { createClient } from 'redis'; - -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'); -await client.disconnect(); -``` - -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). - -To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). - -### 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', { - expiration: { - type: 'EX', - value: 10 - }, - condition: 'NX' -}); -``` - -Replies will be transformed into useful data structures: - -```typescript -await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } -await client.hVals('key'); // ['value1', 'value2'] -``` - -`Buffer`s are supported as well: - -```typescript -await client.hSet('key', 'field', Buffer.from('value')); // 'OK' -await client.withFlags({ - [TYPES.BLOB_STRING]: Buffer -}).hGetAll('key'); // { field: } -``` - -### 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.isolated().blPop( - '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 - -See the [Pub/Sub overview](./docs/pub-sub.md). - -### 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, value } 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 -}); -``` - -### [Programmability](https://redis.io/docs/manual/programmability/) - -Redis provides a programming interface allowing code execution on the redis server. - -#### [Functions](https://redis.io/docs/manual/programmability/functions-intro/) - -The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. - -```lua -#!lua name=library - -redis.register_function { - function_name = 'add', - callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end, - flags = { 'no-writes' } -} -``` - -Here is the same example, but in a format that can be pasted into the `redis-cli`. - -``` -FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" -``` - -Load the prior redis function on the _redis server_ before running the example below. - -```typescript -import { createClient } from 'redis'; - -const client = createClient({ - functions: { - library: { - add: { - NUMBER_OF_KEYS: 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.library.add('key', 2); // 3 -``` - -#### [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/) - -The following is an end-to-end example of the prior concept. - -```typescript -import { createClient, defineScript } from 'redis'; - -const client = createClient({ - scripts: { - add: defineScript({ - NUMBER_OF_KEYS: 1, - SCRIPT: - 'return redis.call("GET", KEYS[1]) + 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. - -### Events - -The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes: - -| Name | When | Listener arguments | -|-------------------------|------------------------------------------------------------------------------------|------------------------------------------------------------| -| `connect` | Initiating a connection to the server | *No arguments* | -| `ready` | Client is ready to use | *No arguments* | -| `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | *No arguments* | -| `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` | -| `reconnecting` | Client is trying to reconnect to the server | *No arguments* | -| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | - -> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. - -> The client will not emit [any other events](./docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. - -## Supported Redis versions - -Node Redis is supported with the following versions of Redis: - -| Version | Supported | -|---------|--------------------| -| 7.0.z | :heavy_check_mark: | -| 6.2.z | :heavy_check_mark: | -| 6.0.z | :heavy_check_mark: | -| 5.0.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. - ## Contributing If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md). diff --git a/package-lock.json b/package-lock.json index 25de62fa8ba..35fac588e3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,16 @@ { - "name": "redis", + "name": "node-redis", "version": "4.6.5", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "redis", - "version": "4.6.5", - "license": "MIT", "workspaces": [ "./packages/*" ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.5.6", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.2", - "@redis/time-series": "1.0.4" - }, "devDependencies": { "@tsconfig/node14": "^1.0.3", - "gh-pages": "^5.0.0", - "release-it": "^15.9.3", - "typescript": "^5.0.2" + "gh-pages": "^5.0.0" } }, "node_modules/@ampproject/remapping": { @@ -6182,6 +6169,10 @@ "node": ">= 0.10" } }, + "node_modules/redis": { + "resolved": "packages/redis", + "link": true + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -8054,6 +8045,22 @@ "@redis/client": "^1.0.0" } }, + "packages/redis": { + "version": "4.6.5", + "license": "MIT", + "dependencies": { + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.6", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.2", + "@redis/time-series": "1.0.4" + }, + "devDependencies": { + "release-it": "^15.9.3", + "typescript": "^5.0.2" + } + }, "packages/search": { "name": "@redis/search", "version": "1.1.2", diff --git a/package.json b/package.json index 3be6fe2175b..3ecfc02e435 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,5 @@ { - "name": "redis", - "description": "A modern, high performance Redis client", - "version": "4.6.5", - "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist/" - ], + "private": true, "workspaces": [ "./packages/*" ], @@ -15,36 +7,14 @@ "test": "npm run test -ws --if-present", "build:client": "npm run build -w ./packages/client", "build:test-utils": "npm run build -w ./packages/test-utils", - "build:tests-tools": "npm run build:client && npm run build:test-utils", - "build:modules": "find ./packages -mindepth 1 -maxdepth 1 -type d ! -name 'client' ! -name 'test-utils' -exec npm run build -w {} \\;", - "build": "tsc", - "build-all": "npm run build:client && npm run build:test-utils && npm run build:modules && npm run build", + "build:modules": "npm run build -w ./packages/bloom -w ./packages/graph -w ./packages/json -w ./packages/search -w ./packages/time-series", + "build:redis": "npm run build -w ./packages/redis", + "build": "npm run build:client && npm run build:test-utils && npm run build:modules && npm run build:redis", "documentation": "npm run documentation -ws --if-present", "gh-pages": "gh-pages -d ./documentation -e ./documentation -u 'documentation-bot '" }, - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.5.6", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.2", - "@redis/time-series": "1.0.4" - }, "devDependencies": { - "@tsconfig/node14": "^1.0.3", - "gh-pages": "^5.0.0", - "release-it": "^15.9.3", - "typescript": "^5.0.2" - }, - "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", - "keywords": [ - "redis" - ] + "@tsconfig/node16": "^1.0.3", + "gh-pages": "^5.0.0" + } } diff --git a/.release-it.json b/packages/redis/.release-it.json similarity index 100% rename from .release-it.json rename to packages/redis/.release-it.json diff --git a/packages/redis/README.md b/packages/redis/README.md new file mode 100644 index 00000000000..0d758d1088c --- /dev/null +++ b/packages/redis/README.md @@ -0,0 +1,359 @@ +# Node-Redis + +[![Tests](https://img.shields.io/github/actions/workflow/status/redis/node-redis/tests.yml?branch=master)](https://github.com/redis/node-redis/actions/workflows/tests.yml) +[![Coverage](https://codecov.io/gh/redis/node-redis/branch/master/graph/badge.svg?token=xcfqHhJC37)](https://codecov.io/gh/redis/node-redis) +[![License](https://img.shields.io/github/license/redis/node-redis.svg)](https://github.com/redis/node-redis/blob/master/LICENSE) + +[![Discord](https://img.shields.io/discord/697882427875393627.svg?style=social&logo=discord)](https://discord.gg/redis) +[![Twitch](https://img.shields.io/twitch/status/redisinc?style=social)](https://www.twitch.tv/redisinc) +[![YouTube](https://img.shields.io/youtube/channel/views/UCD78lHSwYqMlyetR0_P4Vig?style=social)](https://www.youtube.com/redisinc) +[![Twitter](https://img.shields.io/twitter/follow/redisinc?style=social)](https://twitter.com/redisinc) + +node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js. + +## Installation + +Start a redis via docker: + +``` bash +docker run -p 6379:6379 -it redis/redis-stack-server:latest +``` + +To install node-redis, simply: + +```bash +npm install redis +``` + +> :warning: The new interface is clean and cool, but if you have an existing codebase, you'll want to read the [migration guide](./docs/v3-to-v4.md). + +Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! + +## Usage + +### Basic Example + +```typescript +import { createClient } from 'redis'; + +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'); +await client.disconnect(); +``` + +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). + +To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). + +### 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', { + expiration: { + type: 'EX', + value: 10 + }, + condition: 'NX' +}); +``` + +Replies will be transformed into useful data structures: + +```typescript +await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } +await client.hVals('key'); // ['value1', 'value2'] +``` + +`Buffer`s are supported as well: + +```typescript +await client.hSet('key', 'field', Buffer.from('value')); // 'OK' +await client.withFlags({ + [TYPES.BLOB_STRING]: Buffer +}).hGetAll('key'); // { field: } +``` + +### 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.isolated().blPop( + '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 + +See the [Pub/Sub overview](./docs/pub-sub.md). + +### 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, value } 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 +}); +``` + +### [Programmability](https://redis.io/docs/manual/programmability/) + +Redis provides a programming interface allowing code execution on the redis server. + +#### [Functions](https://redis.io/docs/manual/programmability/functions-intro/) + +The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. + +```lua +#!lua name=library + +redis.register_function { + function_name = 'add', + callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end, + flags = { 'no-writes' } +} +``` + +Here is the same example, but in a format that can be pasted into the `redis-cli`. + +``` +FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" +``` + +Load the prior redis function on the _redis server_ before running the example below. + +```typescript +import { createClient } from 'redis'; + +const client = createClient({ + functions: { + library: { + add: { + NUMBER_OF_KEYS: 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.library.add('key', 2); // 3 +``` + +#### [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/) + +The following is an end-to-end example of the prior concept. + +```typescript +import { createClient, defineScript } from 'redis'; + +const client = createClient({ + scripts: { + add: defineScript({ + NUMBER_OF_KEYS: 1, + SCRIPT: + 'return redis.call("GET", KEYS[1]) + 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. + +### Events + +The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes: + +| Name | When | Listener arguments | +|-------------------------|------------------------------------------------------------------------------------|------------------------------------------------------------| +| `connect` | Initiating a connection to the server | *No arguments* | +| `ready` | Client is ready to use | *No arguments* | +| `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | *No arguments* | +| `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` | +| `reconnecting` | Client is trying to reconnect to the server | *No arguments* | +| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | + +> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. + +> The client will not emit [any other events](./docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. + +## Supported Redis versions + +Node Redis is supported with the following versions of Redis: + +| Version | Supported | +|---------|--------------------| +| 7.0.z | :heavy_check_mark: | +| 6.2.z | :heavy_check_mark: | +| 6.0.z | :heavy_check_mark: | +| 5.0.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. + +## Contributing + +If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md). + +Thank you to all the people who already contributed to Node Redis! + +[![Contributors](https://contrib.rocks/image?repo=redis/node-redis)](https://github.com/redis/node-redis/graphs/contributors) + +## License + +This repository is licensed under the "MIT" license. See [LICENSE](LICENSE). diff --git a/index.ts b/packages/redis/index.ts similarity index 100% rename from index.ts rename to packages/redis/index.ts diff --git a/packages/redis/package.json b/packages/redis/package.json new file mode 100644 index 00000000000..461e4808e87 --- /dev/null +++ b/packages/redis/package.json @@ -0,0 +1,37 @@ +{ + "name": "redis", + "description": "A modern, high performance Redis client", + "version": "4.6.5", + "license": "MIT", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist/" + ], + "scripts": { + "build": "tsc" + }, + "dependencies": { + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.6", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.2", + "@redis/time-series": "1.0.4" + }, + "devDependencies": { + "release-it": "^15.9.3", + "typescript": "^5.0.2" + }, + "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", + "keywords": [ + "redis" + ] +} diff --git a/tsconfig.json b/packages/redis/tsconfig.json similarity index 68% rename from tsconfig.json rename to packages/redis/tsconfig.json index 285b7ff0a97..50da0ba733a 100644 --- a/tsconfig.json +++ b/packages/redis/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "./tsconfig.base.json", + "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "./dist" }, diff --git a/tsconfig.base.json b/tsconfig.base.json index 68325e51dcc..5824c33a9e6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,5 +1,5 @@ { - "extends": "@tsconfig/node14/tsconfig.json", + "extends": "@tsconfig/node16/tsconfig.json", "compilerOptions": { "declaration": true, "allowJs": true, From aae501e271416fafedd76ba6a58600f5130dbb9c Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 14:29:04 -0400 Subject: [PATCH 017/325] wip --- {md => docs}/RESP3.md | 0 md/Redis-todo.md => docs/todo.md | 0 {md => docs}/v4-to-v5.md | 0 md/v5-new-features.md => docs/v5.md | 0 package-lock.json | 5 +- package.json | 1 + packages/redis/index.ts | 84 ++++++++++++++--------------- 7 files changed, 46 insertions(+), 44 deletions(-) rename {md => docs}/RESP3.md (100%) rename md/Redis-todo.md => docs/todo.md (100%) rename {md => docs}/v4-to-v5.md (100%) rename md/v5-new-features.md => docs/v5.md (100%) diff --git a/md/RESP3.md b/docs/RESP3.md similarity index 100% rename from md/RESP3.md rename to docs/RESP3.md diff --git a/md/Redis-todo.md b/docs/todo.md similarity index 100% rename from md/Redis-todo.md rename to docs/todo.md diff --git a/md/v4-to-v5.md b/docs/v4-to-v5.md similarity index 100% rename from md/v4-to-v5.md rename to docs/v4-to-v5.md diff --git a/md/v5-new-features.md b/docs/v5.md similarity index 100% rename from md/v5-new-features.md rename to docs/v5.md diff --git a/package-lock.json b/package-lock.json index 35fac588e3f..d9ea8e50f96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { - "name": "node-redis", + "name": "redis-monorepo", "version": "4.6.5", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "redis-monorepo", "workspaces": [ "./packages/*" ], "devDependencies": { - "@tsconfig/node14": "^1.0.3", + "@tsconfig/node16": "^1.0.3", "gh-pages": "^5.0.0" } }, diff --git a/package.json b/package.json index 3ecfc02e435..afb549a486c 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "name": "redis-monorepo", "private": true, "workspaces": [ "./packages/*" diff --git a/packages/redis/index.ts b/packages/redis/index.ts index 5b5a6e81294..58552adf1f3 100644 --- a/packages/redis/index.ts +++ b/packages/redis/index.ts @@ -1,13 +1,13 @@ import { - RedisModules, - RedisFunctions, - RedisScripts, - createClient as _createClient, - RedisClientOptions, - RedisClientType as _RedisClientType, - createCluster as _createCluster, - RedisClusterOptions, - RedisClusterType as _RedisClusterType + RedisModules, + RedisFunctions, + RedisScripts, + createClient as _createClient, + RedisClientOptions, + RedisClientType as _RedisClientType, + createCluster as _createCluster, + RedisClusterOptions, + RedisClusterType as _RedisClusterType } from '@redis/client'; import RedisBloomModules from '@redis/bloom'; import RedisGraph from '@redis/graph'; @@ -23,55 +23,55 @@ export * from '@redis/search'; export * from '@redis/time-series'; const modules = { - ...RedisBloomModules, - graph: RedisGraph, - json: RedisJSON, - ft: RediSearch, - ts: RedisTimeSeries + ...RedisBloomModules, + graph: RedisGraph, + json: RedisJSON, + ft: RediSearch, + ts: RedisTimeSeries }; export type RedisDefaultModules = typeof modules; export type RedisClientType< - M extends RedisModules = RedisDefaultModules, - F extends RedisFunctions = Record, - S extends RedisScripts = Record + M extends RedisModules = RedisDefaultModules, + F extends RedisFunctions = Record, + S extends RedisScripts = Record > = _RedisClientType; export function createClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts >( - options?: RedisClientOptions + options?: RedisClientOptions ): _RedisClientType { - return _createClient({ - ...options, - modules: { - ...modules, - ...(options?.modules as M) - } - }); + return _createClient({ + ...options, + modules: { + ...modules, + ...(options?.modules as M) + } + }); } export type RedisClusterType< - M extends RedisModules = RedisDefaultModules, - F extends RedisFunctions = Record, - S extends RedisScripts = Record + M extends RedisModules = RedisDefaultModules, + F extends RedisFunctions = Record, + S extends RedisScripts = Record > = _RedisClusterType; export function createCluster< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts >( - options: RedisClusterOptions + options: RedisClusterOptions ): RedisClusterType { - return _createCluster({ - ...options, - modules: { - ...modules, - ...(options?.modules as M) - } - }); + return _createCluster({ + ...options, + modules: { + ...modules, + ...(options?.modules as M) + } + }); } From feae3d184bba1766b2f0bdfc4af758af6f68feb9 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 14:30:57 -0400 Subject: [PATCH 018/325] npm update --- package-lock.json | 2624 ++++++++++++++++++++++++++++----------------- 1 file changed, 1630 insertions(+), 994 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9ea8e50f96..7e5c35a257f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,5 @@ { "name": "redis-monorepo", - "version": "4.6.5", "lockfileVersion": 3, "requires": true, "packages": { @@ -15,11 +14,12 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -27,9 +27,10 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -38,32 +39,34 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.19.4", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", + "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.19.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.6", - "@babel/helpers": "^7.19.4", - "@babel/parser": "^7.19.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", + "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", + "@babel/helper-compilation-targets": "^7.21.4", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.4", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.4", + "@babel/types": "^7.21.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { @@ -74,48 +77,31 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.19.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", + "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.21.4", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", + "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.4", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { @@ -125,29 +111,23 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -155,8 +135,9 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -165,40 +146,43 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", + "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.6", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.19.4", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.6", - "@babel/types": "^7.19.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.19.4", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -206,8 +190,9 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -217,36 +202,40 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.19.4", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -254,8 +243,9 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -267,8 +257,9 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -278,8 +269,9 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -291,37 +283,33 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -330,9 +318,10 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", + "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -341,31 +330,33 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.19.6", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", + "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.6", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.4", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.6", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -375,16 +366,18 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.19.4", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", + "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -396,8 +389,9 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -407,8 +401,9 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -430,9 +425,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", - "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -486,8 +481,9 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -504,13 +500,15 @@ }, "node_modules/@iarna/toml": { "version": "2.2.5", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -524,28 +522,18 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -554,54 +542,20 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", + "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2" }, @@ -614,19 +568,22 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, - "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -634,38 +591,49 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "dev": true, - "license": "MIT" + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -676,16 +644,18 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -753,9 +723,9 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.0.0.tgz", + "integrity": "sha512-V8BVJGN0ZmMlURF55VFHFd/L92XQQ43KvFjNmY1IYbCN3V/h/uUFV6iQi19WEHM395Nn+1qhUbViCAD/1czzog==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { @@ -865,18 +835,28 @@ } }, "node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.1.2.tgz", + "integrity": "sha512-LPbJIuu1WNoRHbN4UMysEdlissRFpTCWyoKT7kHPufI8T+XX33/qilfMWJo3mCOjNIKu0+43oSQPf+HJa0+TTQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^17.0.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" } }, "node_modules/@pnpm/network.ca-file": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" }, @@ -884,11 +864,19 @@ "node": ">=12.22.0" } }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, "node_modules/@pnpm/npm-conf": { - "version": "1.0.5", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.1.1.tgz", + "integrity": "sha512-yfRcuupmxxeDOSxvw4g+wFCrGiPD0L32f5WMzqMXp7Rl93EOCdFiDcaSNnZ10Up9GdNqkj70UTa8hfhPFphaZA==", "dev": true, - "license": "MIT", "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" }, @@ -926,8 +914,9 @@ }, "node_modules/@sindresorhus/is": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", + "integrity": "sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -936,9 +925,9 @@ } }, "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -953,6 +942,15 @@ "@sinonjs/commons": "^2.0.0" } }, + "node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/@sinonjs/samsam": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", @@ -964,6 +962,15 @@ "type-detect": "^4.0.8" } }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", @@ -972,8 +979,9 @@ }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dev": true, - "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -983,31 +991,36 @@ }, "node_modules/@tootallnate/once": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", @@ -1050,13 +1063,15 @@ }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "dev": true }, "node_modules/@types/yallist": { "version": "4.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", + "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", + "dev": true }, "node_modules/@types/yargs": { "version": "17.0.24", @@ -1069,8 +1084,9 @@ }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.59.1", @@ -1106,6 +1122,33 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/parser": { "version": "5.59.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.1.tgz", @@ -1217,40 +1260,123 @@ } } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", - "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.1", - "@typescript-eslint/types": "5.59.1", - "@typescript-eslint/typescript-estree": "5.59.1", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", - "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.1", - "eslint-visitor-keys": "^3.3.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", + "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", + "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.1", + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1261,9 +1387,10 @@ } }, "node_modules/acorn": { - "version": "8.8.1", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1282,16 +1409,18 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, - "license": "MIT", "dependencies": { "debug": "4" }, @@ -1301,8 +1430,9 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, - "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1329,21 +1459,24 @@ }, "node_modules/ansi-align": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.1.0" } }, "node_modules/ansi-align/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/ansi-align/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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1355,16 +1488,17 @@ }, "node_modules/ansi-colors": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.1.0.tgz", - "integrity": "sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { "type-fest": "^3.0.0" @@ -1377,9 +1511,9 @@ } }, "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.7.1.tgz", - "integrity": "sha512-8LZNdvuztgxCF4eYpEmPYUPS0lbbByM2qHcp2oMxHZhWLIQB9QE36EeQ1PKwsUIDZXEP8HCBEmkBbT1//kLU4Q==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.9.0.tgz", + "integrity": "sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA==", "dev": true, "engines": { "node": ">=14.16" @@ -1390,8 +1524,9 @@ }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -1404,8 +1539,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1417,9 +1553,10 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1430,8 +1567,9 @@ }, "node_modules/append-transform": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, - "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -1441,32 +1579,52 @@ }, "node_modules/archy": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true }, "node_modules/arg": { "version": "4.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dev": true, - "license": "Python-2.0" + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/array-uniq": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1492,8 +1650,9 @@ }, "node_modules/ast-types": { "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, - "license": "MIT", "dependencies": { "tslib": "^2.0.1" }, @@ -1509,8 +1668,9 @@ }, "node_modules/async-retry": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "dev": true, - "license": "MIT", "dependencies": { "retry": "0.13.1" } @@ -1529,8 +1689,9 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -1569,8 +1730,9 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -1586,10 +1748,34 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/boxen": { - "version": "7.0.0", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.2.tgz", + "integrity": "sha512-1Z4UJabXUP1/R9rLpoU3O2lEMnG3pPLAs/ZD2lF3t2q7qD5lM8rqbtnvtvm4N0wEyNlE+9yZVTVAGmd1V5jabg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^7.0.0", @@ -1608,9 +1794,10 @@ } }, "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.0", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -1619,9 +1806,10 @@ } }, "node_modules/boxen/node_modules/chalk": { - "version": "5.1.2", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1631,8 +1819,9 @@ }, "node_modules/boxen/node_modules/type-fest": { "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -1654,8 +1843,9 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1663,8 +1853,9 @@ }, "node_modules/braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1674,11 +1865,14 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, "node_modules/browserslist": { - "version": "4.21.4", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -1690,12 +1884,11 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -1730,8 +1923,9 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/bundle-name": { "version": "3.0.0", @@ -1750,24 +1944,26 @@ }, "node_modules/bytes": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/cacheable-lookup": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" } }, "node_modules/cacheable-request": { - "version": "10.2.8", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.8.tgz", - "integrity": "sha512-IDVO5MJ4LItE6HKFQTqT2ocAQsisOoCTUDu1ddCmnhyiwFQjXNPp4081Xj23N4tO+AFEFNzGuNEf/c8Gwwt15A==", + "version": "10.2.10", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.10.tgz", + "integrity": "sha512-v6WB+Epm/qO4Hdlio/sfUn69r5Shgh39SsE9DSd4bIezP0mblOlObI+I0kUEM7J0JFc+I7pSeMeYaOYtX1N/VQ==", "dev": true, "dependencies": { "@types/http-cache-semantics": "^4.0.1", @@ -1784,8 +1980,9 @@ }, "node_modules/caching-transform": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, - "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1820,14 +2017,17 @@ }, "node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001425", + "version": "1.0.30001481", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", + "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==", "dev": true, "funding": [ { @@ -1837,14 +2037,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1864,6 +2068,8 @@ }, "node_modules/chokidar": { "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -1871,7 +2077,6 @@ "url": "https://paulmillr.com/funding/" } ], - "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1890,8 +2095,9 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1900,22 +2106,34 @@ } }, "node_modules/ci-info": { - "version": "3.5.0", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-boxes": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -1939,9 +2157,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", + "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", "dev": true, "engines": { "node": ">=6" @@ -1961,8 +2179,9 @@ }, "node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -1974,13 +2193,15 @@ }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/cliui/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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1992,8 +2213,9 @@ }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2025,8 +2247,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2036,28 +2259,33 @@ }, "node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/commander": { "version": "2.20.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/commondir": { "version": "1.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/config-chain": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, - "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -2065,13 +2293,15 @@ }, "node_modules/config-chain/node_modules/ini": { "version": "1.3.8", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/configstore": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "dot-prop": "^6.0.1", "graceful-fs": "^4.2.6", @@ -2088,13 +2318,15 @@ }, "node_modules/convert-source-map": { "version": "1.9.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/core-util-is": { "version": "1.0.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true }, "node_modules/cosmiconfig": { "version": "8.1.3", @@ -2116,13 +2348,15 @@ }, "node_modules/create-require": { "version": "1.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2134,8 +2368,9 @@ }, "node_modules/crypto-random-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^1.0.1" }, @@ -2148,8 +2383,9 @@ }, "node_modules/crypto-random-string/node_modules/type-fest": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2168,8 +2404,9 @@ }, "node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2184,16 +2421,18 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/decompress-response": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, - "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -2206,8 +2445,9 @@ }, "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2217,16 +2457,18 @@ }, "node_modules/deep-extend": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "node_modules/default-browser": { "version": "4.0.0", @@ -2264,8 +2506,9 @@ }, "node_modules/default-require-extensions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, - "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -2290,8 +2533,9 @@ }, "node_modules/defer-to-connect": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" } @@ -2325,14 +2569,15 @@ } }, "node_modules/degenerator": { - "version": "3.0.2", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.4.tgz", + "integrity": "sha512-Z66uPeBfHZAHVmue3HPfyKu2Q0rC2cRxbTOsvmU/po5fvvcx27W4mIu9n0PUlQih4oUYvcG1BsbtVv8x7KDOSw==", "dev": true, - "license": "MIT", "dependencies": { "ast-types": "^0.13.2", "escodegen": "^1.8.1", "esprima": "^4.0.0", - "vm2": "^3.9.8" + "vm2": "^3.9.17" }, "engines": { "node": ">= 6" @@ -2340,8 +2585,9 @@ }, "node_modules/depd": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2354,8 +2600,9 @@ }, "node_modules/diff": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -2374,8 +2621,9 @@ }, "node_modules/doctrine": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -2385,8 +2633,9 @@ }, "node_modules/dot-prop": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", "dev": true, - "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -2399,13 +2648,15 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "dev": true, - "license": "ISC" + "version": "1.4.373", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.373.tgz", + "integrity": "sha512-whGyixOVSRlyOBQDsRH9xltFaMij2/+DQRdaYahCq0P/fiVnAVGaW7OVsFnEjze/qUo298ez9C46gnALpo6ukg==", + "dev": true }, "node_modules/email-addresses": { "version": "5.0.0", @@ -2415,8 +2666,9 @@ }, "node_modules/emoji-regex": { "version": "9.2.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/error-ex": { "version": "1.3.2", @@ -2428,18 +2680,18 @@ } }, "node_modules/es-abstract": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", - "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", @@ -2447,8 +2699,8 @@ "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.4", - "is-array-buffer": "^3.0.1", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", @@ -2456,11 +2708,12 @@ "is-string": "^1.0.7", "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", "string.prototype.trimend": "^1.0.6", "string.prototype.trimstart": "^1.0.6", "typed-array-length": "^1.0.4", @@ -2533,21 +2786,24 @@ }, "node_modules/es6-error": { "version": "4.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true }, "node_modules/escalade": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-goat": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -2556,20 +2812,19 @@ } }, "node_modules/escape-string-regexp": { - "version": "4.0.0", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.0" } }, "node_modules/escodegen": { "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^4.2.0", @@ -2589,8 +2844,9 @@ }, "node_modules/escodegen/node_modules/levn": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -2601,8 +2857,9 @@ }, "node_modules/escodegen/node_modules/optionator": { "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, - "license": "MIT", "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -2617,6 +2874,8 @@ }, "node_modules/escodegen/node_modules/prelude-ls": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -2624,8 +2883,9 @@ }, "node_modules/escodegen/node_modules/type-check": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -2715,6 +2975,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", @@ -2740,6 +3012,67 @@ "node": ">=4.0" } }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/espree": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", @@ -2759,8 +3092,9 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2813,16 +3147,18 @@ }, "node_modules/estraverse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -2918,13 +3254,15 @@ }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, "node_modules/fastq": { - "version": "1.13.0", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2994,8 +3332,9 @@ }, "node_modules/file-entry-cache": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -3005,24 +3344,27 @@ }, "node_modules/file-uri-to-path": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/filename-reserved-regex": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/filenamify": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, - "license": "MIT", "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -3037,8 +3379,9 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3048,8 +3391,9 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, - "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -3063,32 +3407,32 @@ } }, "node_modules/find-up": { - "version": "5.0.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", + "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/flat": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, - "license": "MIT", "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -3099,8 +3443,9 @@ }, "node_modules/flatted": { "version": "3.2.7", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true }, "node_modules/for-each": { "version": "0.3.3", @@ -3113,8 +3458,9 @@ }, "node_modules/foreground-child": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, - "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -3124,9 +3470,10 @@ } }, "node_modules/form-data-encoder": { - "version": "2.1.3", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 14.17" } @@ -3145,6 +3492,8 @@ }, "node_modules/fromentries": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { @@ -3159,13 +3508,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -3177,11 +3526,28 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "license": "ISC" + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/ftp": { "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", "dev": true, "dependencies": { "readable-stream": "1.1.x", @@ -3191,31 +3557,11 @@ "node": ">=0.8.0" } }, - "node_modules/ftp/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/ftp/node_modules/readable-stream": { - "version": "1.1.14", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ftp/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, "node_modules/function-bind": { "version": "1.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -3246,23 +3592,26 @@ }, "node_modules/generic-pool": { "version": "3.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -3283,16 +3632,18 @@ }, "node_modules/get-package-type": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -3318,8 +3669,9 @@ }, "node_modules/get-uri": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/once": "1", "data-uri-to-buffer": "3", @@ -3334,8 +3686,9 @@ }, "node_modules/get-uri/node_modules/data-uri-to-buffer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } @@ -3362,38 +3715,11 @@ "node": ">=10" } }, - "node_modules/gh-pages/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gh-pages/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/git-up": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "dev": true, - "license": "MIT", "dependencies": { "is-ssh": "^1.4.0", "parse-url": "^8.1.0" @@ -3401,21 +3727,23 @@ }, "node_modules/git-url-parse": { "version": "13.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", + "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", "dev": true, - "license": "MIT", "dependencies": { "git-up": "^7.0.0" } }, "node_modules/glob": { - "version": "7.2.0", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -3428,8 +3756,9 @@ }, "node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -3438,9 +3767,10 @@ } }, "node_modules/global-dirs": { - "version": "3.0.0", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, - "license": "MIT", "dependencies": { "ini": "2.0.0" }, @@ -3482,23 +3812,19 @@ } }, "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/gopd": { @@ -3539,19 +3865,22 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "dev": true, - "license": "ISC" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/grapheme-splitter": { "version": "1.0.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "node_modules/has": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, - "license": "MIT", "dependencies": { "function-bind": "^1.1.1" }, @@ -3570,8 +3899,9 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -3629,8 +3959,9 @@ }, "node_modules/has-yarn": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -3640,8 +3971,9 @@ }, "node_modules/hasha": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, - "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -3655,24 +3987,27 @@ }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/html-escaper": { "version": "2.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "node_modules/http-cache-semantics": { "version": "4.1.1", @@ -3682,8 +4017,9 @@ }, "node_modules/http-errors": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, - "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -3697,8 +4033,9 @@ }, "node_modules/http-proxy-agent": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -3709,9 +4046,10 @@ } }, "node_modules/http2-wrapper": { - "version": "2.1.11", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", + "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", "dev": true, - "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -3722,8 +4060,9 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -3743,8 +4082,9 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -3773,9 +4113,10 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } @@ -3798,32 +4139,36 @@ }, "node_modules/import-lazy": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, - "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3831,13 +4176,15 @@ }, "node_modules/inherits": { "version": "2.0.4", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/ini": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } @@ -3923,16 +4270,18 @@ }, "node_modules/interpret": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/ip": { "version": "1.1.8", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true }, "node_modules/is-arguments": { "version": "1.1.1", @@ -3984,8 +4333,9 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4023,8 +4373,9 @@ }, "node_modules/is-ci": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, - "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -4033,9 +4384,10 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "dev": true, - "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -4075,24 +4427,27 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -4120,8 +4475,9 @@ }, "node_modules/is-installed-globally": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, - "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" @@ -4168,8 +4524,9 @@ }, "node_modules/is-npm": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4179,8 +4536,9 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4202,24 +4560,27 @@ }, "node_modules/is-obj": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -4272,16 +4633,18 @@ }, "node_modules/is-ssh": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", + "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", "dev": true, - "license": "MIT", "dependencies": { "protocols": "^2.0.1" } }, "node_modules/is-stream": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -4340,13 +4703,15 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -4368,8 +4733,9 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4402,9 +4768,10 @@ } }, "node_modules/is-yarn-global": { - "version": "0.4.0", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" } @@ -4417,8 +4784,9 @@ }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/issue-parser": { "version": "6.0.0", @@ -4438,16 +4806,18 @@ }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -4457,8 +4827,9 @@ }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -4469,18 +4840,11 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, - "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -4495,8 +4859,9 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -4508,8 +4873,9 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -4521,8 +4887,9 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -4554,19 +4921,26 @@ } }, "node_modules/js-sdsl": { - "version": "4.1.5", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", "dev": true, - "license": "MIT" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } }, "node_modules/js-tokens": { "version": "4.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4576,8 +4950,9 @@ }, "node_modules/jsesc": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -4605,8 +4980,9 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -4628,8 +5004,9 @@ }, "node_modules/jsonfile": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4651,8 +5028,9 @@ }, "node_modules/latest-version": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", "dev": true, - "license": "MIT", "dependencies": { "package-json": "^8.1.0" }, @@ -4665,8 +5043,9 @@ }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -4682,17 +5061,15 @@ "dev": true }, "node_modules/locate-path": { - "version": "6.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/lodash": { @@ -4715,8 +5092,9 @@ }, "node_modules/lodash.flattendeep": { "version": "4.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", @@ -4738,8 +5116,9 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.uniqby": { "version": "4.7.0", @@ -4749,8 +5128,9 @@ }, "node_modules/log-symbols": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -4776,16 +5156,24 @@ }, "node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, - "node_modules/lunr": { - "version": "2.3.9", - "dev": true, - "license": "MIT" + "node_modules/lru-cache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true }, "node_modules/macos-release": { "version": "3.1.0", @@ -4801,8 +5189,9 @@ }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -4813,18 +5202,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/make-error": { "version": "1.3.6", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "node_modules/marked": { "version": "4.3.0", @@ -4913,8 +5295,9 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4923,9 +5306,10 @@ } }, "node_modules/minimist": { - "version": "1.2.7", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4970,18 +5354,11 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -4990,13 +5367,90 @@ }, "node_modules/mocha/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==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT" + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5004,15 +5458,56 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT" + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/mocha/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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5024,8 +5519,9 @@ }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -5038,8 +5534,9 @@ }, "node_modules/mocha/node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5054,8 +5551,9 @@ }, "node_modules/mocha/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -5071,8 +5569,9 @@ }, "node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/mute-stream": { "version": "1.0.0", @@ -5085,8 +5584,9 @@ }, "node_modules/nanoid": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5096,8 +5596,9 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", @@ -5107,16 +5608,18 @@ }, "node_modules/netmask": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/new-github-release-url": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", + "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^2.5.1" }, @@ -5129,8 +5632,9 @@ }, "node_modules/new-github-release-url/node_modules/type-fest": { "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -5151,6 +5655,15 @@ "path-to-regexp": "^1.7.0" } }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -5190,8 +5703,9 @@ }, "node_modules/node-preload": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, - "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -5200,14 +5714,16 @@ } }, "node_modules/node-releases": { - "version": "2.0.6", - "dev": true, - "license": "MIT" + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5253,8 +5769,9 @@ }, "node_modules/nyc": { "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -5293,8 +5810,9 @@ }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -5303,69 +5821,24 @@ }, "node_modules/nyc/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/nyc/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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5377,8 +5850,9 @@ }, "node_modules/nyc/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==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5390,13 +5864,15 @@ }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -5416,8 +5892,9 @@ }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -5428,8 +5905,9 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5472,8 +5950,9 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "license": "ISC", "dependencies": { "wrappy": "1" } @@ -5513,8 +5992,9 @@ }, "node_modules/optionator": { "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, - "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -5644,44 +6124,45 @@ }, "node_modules/p-cancelable": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, - "license": "MIT", "engines": { "node": ">=12.20" } }, "node_modules/p-limit": { - "version": "3.1.0", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "5.0.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/p-map": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, - "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -5691,16 +6172,18 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pac-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -5718,8 +6201,9 @@ }, "node_modules/pac-resolver": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", + "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", "dev": true, - "license": "MIT", "dependencies": { "degenerator": "^3.0.2", "ip": "^1.1.5", @@ -5731,8 +6215,9 @@ }, "node_modules/package-hash": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, - "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -5745,8 +6230,9 @@ }, "node_modules/package-json": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.0.tgz", + "integrity": "sha512-hySwcV8RAWeAfPsXb9/HGSPn8lwDnv6fabH+obUZKX169QknRkRhPxd1yMubpKDskLFATkl3jHpNtVtDPFA0Wg==", "dev": true, - "license": "MIT", "dependencies": { "got": "^12.1.0", "registry-auth-token": "^5.0.1", @@ -5760,6 +6246,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5792,48 +6305,54 @@ }, "node_modules/parse-path": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", "dev": true, - "license": "MIT", "dependencies": { "protocols": "^2.0.0" } }, "node_modules/parse-url": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "dev": true, - "license": "MIT", "dependencies": { "parse-path": "^7.0.0" } }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-to-regexp": { "version": "1.8.0", @@ -5861,13 +6380,15 @@ }, "node_modules/picocolors": { "version": "1.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -5877,24 +6398,27 @@ }, "node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, - "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -5904,8 +6428,9 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -5913,66 +6438,20 @@ "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/process-on-spawn": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, - "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -6002,18 +6481,21 @@ }, "node_modules/proto-list": { "version": "1.2.4", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true }, "node_modules/protocols": { "version": "2.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true }, "node_modules/proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^6.0.0", "debug": "4", @@ -6030,8 +6512,9 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, "node_modules/punycode": { "version": "2.3.0", @@ -6044,8 +6527,9 @@ }, "node_modules/pupa": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", "dev": true, - "license": "MIT", "dependencies": { "escape-goat": "^4.0.0" }, @@ -6058,6 +6542,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -6072,13 +6558,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/quick-lru": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -6088,16 +6574,18 @@ }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/raw-body": { - "version": "2.5.1", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, - "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6110,8 +6598,9 @@ }, "node_modules/rc": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -6124,35 +6613,42 @@ }, "node_modules/rc/node_modules/ini": { "version": "1.3.8", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -6162,6 +6658,8 @@ }, "node_modules/rechoir": { "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "dependencies": { "resolve": "^1.1.6" @@ -6175,14 +6673,14 @@ "link": true }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -6192,11 +6690,12 @@ } }, "node_modules/registry-auth-token": { - "version": "5.0.1", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "dev": true, - "license": "MIT", "dependencies": { - "@pnpm/npm-conf": "^1.0.4" + "@pnpm/npm-conf": "^2.1.0" }, "engines": { "node": ">=14" @@ -6204,8 +6703,9 @@ }, "node_modules/registry-url": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", "dev": true, - "license": "MIT", "dependencies": { "rc": "1.2.8" }, @@ -6288,6 +6788,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/release-it/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/release-it/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/release-it/node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -6302,16 +6829,18 @@ }, "node_modules/release-it/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/release-zalgo": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, - "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -6321,23 +6850,26 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "node_modules/resolve": { - "version": "1.22.1", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, - "license": "MIT", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -6350,8 +6882,9 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true }, "node_modules/resolve-from": { "version": "4.0.0", @@ -6419,16 +6952,18 @@ }, "node_modules/retry": { "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/reusify": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -6436,8 +6971,9 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, - "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -6551,6 +7087,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -6566,7 +7104,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -6582,6 +7119,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -6596,8 +7135,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/safe-regex-test": { "version": "1.0.0", @@ -6615,27 +7153,24 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/semver": { - "version": "7.3.8", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/semver-diff": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -6646,10 +7181,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver/node_modules/lru-cache": { + "node_modules/semver-diff/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -6657,33 +7193,47 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", + "node_modules/semver-diff/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", "dev": true, - "license": "ISC" + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/serialize-javascript": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/setprototypeof": { "version": "1.2.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6693,16 +7243,18 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shelljs": { "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -6743,8 +7295,9 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/sinon": { "version": "15.0.4", @@ -6764,15 +7317,6 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, "node_modules/sinon/node_modules/diff": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", @@ -6793,8 +7337,9 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -6802,8 +7347,9 @@ }, "node_modules/socks": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, - "license": "MIT", "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -6815,8 +7361,9 @@ }, "node_modules/socks-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "4", @@ -6828,21 +7375,24 @@ }, "node_modules/socks/node_modules/ip": { "version": "2.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6850,8 +7400,9 @@ }, "node_modules/spawn-wrap": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, - "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -6866,13 +7417,15 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/statuses": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -6905,18 +7458,16 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true }, "node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, - "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -6931,8 +7482,9 @@ }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -6942,8 +7494,9 @@ }, "node_modules/string-width/node_modules/strip-ansi": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -6954,6 +7507,23 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -6984,8 +7554,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6995,8 +7566,9 @@ }, "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -7015,8 +7587,9 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -7026,8 +7599,9 @@ }, "node_modules/strip-outer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7035,18 +7609,11 @@ "node": ">=0.10.0" } }, - "node_modules/strip-outer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7056,8 +7623,9 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7067,8 +7635,9 @@ }, "node_modules/test-exclude": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -7080,8 +7649,9 @@ }, "node_modules/text-table": { "version": "0.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/through": { "version": "2.3.8", @@ -7115,16 +7685,18 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -7134,8 +7706,9 @@ }, "node_modules/toidentifier": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.6" } @@ -7148,8 +7721,9 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7157,18 +7731,11 @@ "node": ">=0.10.0" } }, - "node_modules/trim-repeated/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/ts-node": { "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7209,21 +7776,24 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/tslib": { - "version": "2.4.0", - "dev": true, - "license": "0BSD" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true }, "node_modules/tsutils": { "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -7236,13 +7806,15 @@ }, "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", - "dev": true, - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -7287,8 +7859,9 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, - "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } @@ -7368,8 +7941,9 @@ }, "node_modules/unique-string": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", "dev": true, - "license": "MIT", "dependencies": { "crypto-random-string": "^4.0.0" }, @@ -7388,16 +7962,18 @@ }, "node_modules/universalify": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -7412,7 +7988,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -7422,15 +8000,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -7438,8 +8019,9 @@ }, "node_modules/update-notifier": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boxen": "^7.0.0", "chalk": "^5.0.1", @@ -7464,9 +8046,10 @@ } }, "node_modules/update-notifier/node_modules/chalk": { - "version": "5.1.2", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -7474,6 +8057,33 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/update-notifier/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/update-notifier/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7485,8 +8095,9 @@ }, "node_modules/url-join": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -7499,21 +8110,24 @@ }, "node_modules/uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/vm2": { - "version": "3.9.11", + "version": "3.9.17", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.17.tgz", + "integrity": "sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw==", "dev": true, - "license": "MIT", "dependencies": { "acorn": "^8.7.0", "acorn-walk": "^8.2.0" @@ -7573,8 +8187,9 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -7602,9 +8217,10 @@ } }, "node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "license": "ISC" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true }, "node_modules/which-typed-array": { "version": "1.1.9", @@ -7628,8 +8244,9 @@ }, "node_modules/widest-line": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, - "license": "MIT", "dependencies": { "string-width": "^5.0.1" }, @@ -7642,8 +8259,9 @@ }, "node_modules/wildcard-match": { "version": "5.1.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", + "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", + "dev": true }, "node_modules/windows-release": { "version": "5.1.0", @@ -7739,16 +8357,18 @@ }, "node_modules/word-wrap": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { "version": "6.2.1", - "dev": true, - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "node_modules/wrap-ansi": { "version": "8.1.0", @@ -7769,8 +8389,9 @@ }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7780,8 +8401,9 @@ }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7791,8 +8413,9 @@ }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -7805,13 +8428,15 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -7821,8 +8446,9 @@ }, "node_modules/xdg-basedir": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7832,21 +8458,26 @@ }, "node_modules/xregexp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", "dev": true, - "license": "MIT" + "engines": { + "node": "*" + } }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.7.1", @@ -7868,16 +8499,18 @@ }, "node_modules/yargs-parser": { "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -7890,8 +8523,9 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7901,8 +8535,9 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7912,13 +8547,15 @@ }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/yargs/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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7930,24 +8567,27 @@ }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/yn": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -8004,10 +8644,6 @@ "node": ">=14" } }, - "packages/client/node_modules/yallist": { - "version": "4.0.0", - "license": "ISC" - }, "packages/graph": { "name": "@redis/graph", "version": "1.1.0", From 11c1738e7e495b2fe77dc9a9317ce509481812d9 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 17:48:42 -0400 Subject: [PATCH 019/325] wip --- docs/clustering.md | 2 ++ docs/v5.md | 2 ++ examples/package.json | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/clustering.md b/docs/clustering.md index 7b8b66a9ad4..b5594e49a76 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -105,6 +105,8 @@ createCluster({ ## Command Routing +TODO request response policy + ### Commands that operate on Redis Keys Commands such as `GET`, `SET`, etc. are routed by the first key specified. For example `MGET 1 2 3` will be routed by the key `1`. diff --git a/docs/v5.md b/docs/v5.md index bfac25315bd..a38d7800d7c 100644 --- a/docs/v5.md +++ b/docs/v5.md @@ -1,5 +1,7 @@ # RESP3 Support +[RESP3](./RESP3.md) + ```javascript const client = createClient({ RESP: 3 diff --git a/examples/package.json b/examples/package.json index 65ba1442f7e..91120774d94 100644 --- a/examples/package.json +++ b/examples/package.json @@ -6,7 +6,7 @@ "private": true, "type": "module", "dependencies": { - "redis": "../" + "redis": "../packages/client" } } From c78f3354e08d7bbd0e3f44b3dd368e09790f98ae Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 17:57:31 -0400 Subject: [PATCH 020/325] wip --- .github/workflows/documentation.yml | 4 ++-- .github/workflows/tests.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index c1232259cc1..8f1a1cec945 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -10,11 +10,11 @@ jobs: documentation: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v3 with: fetch-depth: 1 - name: Use Node.js - uses: actions/setup-node@v2.3.0 + uses: actions/setup-node@v3 - name: Install Packages run: npm ci - name: Generate Documentation diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0693c796ff3..5b23cdfba8c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,11 +19,11 @@ jobs: node-version: ['14', '16', '18', '19'] redis-version: ['5', '6.0', '6.2', '7.0'] steps: - - uses: actions/checkout@v2.3.4 + - uses: actions/checkout@v3 with: fetch-depth: 1 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2.3.0 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Update npm From 1254ff7ebd59bd3cdea05de41670e7b808250f37 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Apr 2023 18:04:27 -0400 Subject: [PATCH 021/325] wip --- packages/client/lib/RESP/decoder.spec.ts | 390 ++-- packages/client/lib/client/index.spec.ts | 1958 +++++++++---------- packages/client/lib/cluster/index.spec.ts | 700 +++---- packages/client/lib/commands/APPEND.spec.ts | 2 +- packages/client/lib/commands/PING.spec.ts | 2 +- 5 files changed, 1526 insertions(+), 1526 deletions(-) diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index dcce9f60115..cff4fbe047f 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -1,195 +1,195 @@ -import { strict as assert } from 'assert'; -import { SinonSpy, spy } from 'sinon'; -import RESP2Decoder from './decoder'; -import { ErrorReply } from '../../errors'; - -interface DecoderAndSpies { - decoder: RESP2Decoder; - returnStringsAsBuffersSpy: SinonSpy; - onReplySpy: SinonSpy; -} - -function createDecoderAndSpies(returnStringsAsBuffers: boolean): DecoderAndSpies { - const returnStringsAsBuffersSpy = spy(() => returnStringsAsBuffers), - onReplySpy = spy(); - - return { - decoder: new RESP2Decoder({ - returnStringsAsBuffers: returnStringsAsBuffersSpy, - onReply: onReplySpy - }), - returnStringsAsBuffersSpy, - onReplySpy - }; -} - -function writeChunks(stream: RESP2Decoder, buffer: Buffer) { - let i = 0; - while (i < buffer.length) { - stream.write(buffer.slice(i, ++i)); - } -} - -type Replies = Array>; - -interface TestsOptions { - toWrite: Buffer; - returnStringsAsBuffers: boolean; - replies: Replies; -} - -function generateTests({ - toWrite, - returnStringsAsBuffers, - replies -}: TestsOptions): void { - it('single chunk', () => { - const { decoder, returnStringsAsBuffersSpy, onReplySpy } = - createDecoderAndSpies(returnStringsAsBuffers); - decoder.write(toWrite); - assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); - testReplies(onReplySpy, replies); - }); - - it('multiple chunks', () => { - const { decoder, returnStringsAsBuffersSpy, onReplySpy } = - createDecoderAndSpies(returnStringsAsBuffers); - writeChunks(decoder, toWrite); - assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); - testReplies(onReplySpy, replies); - }); -} - -function testReplies(spy: SinonSpy, replies: Replies): void { - if (!replies) { - assert.equal(spy.callCount, 0); - return; - } - - assert.equal(spy.callCount, replies.length); - for (const [i, reply] of replies.entries()) { - assert.deepEqual( - spy.getCall(i).args, - reply - ); - } -} - -describe('RESP2Parser', () => { - describe('Simple String', () => { - describe('as strings', () => { - generateTests({ - toWrite: Buffer.from('+OK\r\n'), - returnStringsAsBuffers: false, - replies: [['OK']] - }); - }); - - describe('as buffers', () => { - generateTests({ - toWrite: Buffer.from('+OK\r\n'), - returnStringsAsBuffers: true, - replies: [[Buffer.from('OK')]] - }); - }); - }); - - describe('Error', () => { - generateTests({ - toWrite: Buffer.from('-ERR\r\n'), - returnStringsAsBuffers: false, - replies: [[new ErrorReply('ERR')]] - }); - }); - - describe('Integer', () => { - describe('-1', () => { - generateTests({ - toWrite: Buffer.from(':-1\r\n'), - returnStringsAsBuffers: false, - replies: [[-1]] - }); - }); - - describe('0', () => { - generateTests({ - toWrite: Buffer.from(':0\r\n'), - returnStringsAsBuffers: false, - replies: [[0]] - }); - }); - }); - - describe('Bulk String', () => { - describe('null', () => { - generateTests({ - toWrite: Buffer.from('$-1\r\n'), - returnStringsAsBuffers: false, - replies: [[null]] - }); - }); - - describe('as strings', () => { - generateTests({ - toWrite: Buffer.from('$2\r\naa\r\n'), - returnStringsAsBuffers: false, - replies: [['aa']] - }); - }); - - describe('as buffers', () => { - generateTests({ - toWrite: Buffer.from('$2\r\naa\r\n'), - returnStringsAsBuffers: true, - replies: [[Buffer.from('aa')]] - }); - }); - }); - - describe('Array', () => { - describe('null', () => { - generateTests({ - toWrite: Buffer.from('*-1\r\n'), - returnStringsAsBuffers: false, - replies: [[null]] - }); - }); - - const arrayBuffer = Buffer.from( - '*5\r\n' + - '+OK\r\n' + - '-ERR\r\n' + - ':0\r\n' + - '$1\r\na\r\n' + - '*0\r\n' - ); - - describe('as strings', () => { - generateTests({ - toWrite: arrayBuffer, - returnStringsAsBuffers: false, - replies: [[[ - 'OK', - new ErrorReply('ERR'), - 0, - 'a', - [] - ]]] - }); - }); - - describe('as buffers', () => { - generateTests({ - toWrite: arrayBuffer, - returnStringsAsBuffers: true, - replies: [[[ - Buffer.from('OK'), - new ErrorReply('ERR'), - 0, - Buffer.from('a'), - [] - ]]] - }); - }); - }); -}); +// import { strict as assert } from 'assert'; +// import { SinonSpy, spy } from 'sinon'; +// import RESP2Decoder from './decoder'; +// import { ErrorReply } from '../../errors'; + +// interface DecoderAndSpies { +// decoder: RESP2Decoder; +// returnStringsAsBuffersSpy: SinonSpy; +// onReplySpy: SinonSpy; +// } + +// function createDecoderAndSpies(returnStringsAsBuffers: boolean): DecoderAndSpies { +// const returnStringsAsBuffersSpy = spy(() => returnStringsAsBuffers), +// onReplySpy = spy(); + +// return { +// decoder: new RESP2Decoder({ +// returnStringsAsBuffers: returnStringsAsBuffersSpy, +// onReply: onReplySpy +// }), +// returnStringsAsBuffersSpy, +// onReplySpy +// }; +// } + +// function writeChunks(stream: RESP2Decoder, buffer: Buffer) { +// let i = 0; +// while (i < buffer.length) { +// stream.write(buffer.slice(i, ++i)); +// } +// } + +// type Replies = Array>; + +// interface TestsOptions { +// toWrite: Buffer; +// returnStringsAsBuffers: boolean; +// replies: Replies; +// } + +// function generateTests({ +// toWrite, +// returnStringsAsBuffers, +// replies +// }: TestsOptions): void { +// it('single chunk', () => { +// const { decoder, returnStringsAsBuffersSpy, onReplySpy } = +// createDecoderAndSpies(returnStringsAsBuffers); +// decoder.write(toWrite); +// assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); +// testReplies(onReplySpy, replies); +// }); + +// it('multiple chunks', () => { +// const { decoder, returnStringsAsBuffersSpy, onReplySpy } = +// createDecoderAndSpies(returnStringsAsBuffers); +// writeChunks(decoder, toWrite); +// assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); +// testReplies(onReplySpy, replies); +// }); +// } + +// function testReplies(spy: SinonSpy, replies: Replies): void { +// if (!replies) { +// assert.equal(spy.callCount, 0); +// return; +// } + +// assert.equal(spy.callCount, replies.length); +// for (const [i, reply] of replies.entries()) { +// assert.deepEqual( +// spy.getCall(i).args, +// reply +// ); +// } +// } + +// describe('RESP2Parser', () => { +// describe('Simple String', () => { +// describe('as strings', () => { +// generateTests({ +// toWrite: Buffer.from('+OK\r\n'), +// returnStringsAsBuffers: false, +// replies: [['OK']] +// }); +// }); + +// describe('as buffers', () => { +// generateTests({ +// toWrite: Buffer.from('+OK\r\n'), +// returnStringsAsBuffers: true, +// replies: [[Buffer.from('OK')]] +// }); +// }); +// }); + +// describe('Error', () => { +// generateTests({ +// toWrite: Buffer.from('-ERR\r\n'), +// returnStringsAsBuffers: false, +// replies: [[new ErrorReply('ERR')]] +// }); +// }); + +// describe('Integer', () => { +// describe('-1', () => { +// generateTests({ +// toWrite: Buffer.from(':-1\r\n'), +// returnStringsAsBuffers: false, +// replies: [[-1]] +// }); +// }); + +// describe('0', () => { +// generateTests({ +// toWrite: Buffer.from(':0\r\n'), +// returnStringsAsBuffers: false, +// replies: [[0]] +// }); +// }); +// }); + +// describe('Bulk String', () => { +// describe('null', () => { +// generateTests({ +// toWrite: Buffer.from('$-1\r\n'), +// returnStringsAsBuffers: false, +// replies: [[null]] +// }); +// }); + +// describe('as strings', () => { +// generateTests({ +// toWrite: Buffer.from('$2\r\naa\r\n'), +// returnStringsAsBuffers: false, +// replies: [['aa']] +// }); +// }); + +// describe('as buffers', () => { +// generateTests({ +// toWrite: Buffer.from('$2\r\naa\r\n'), +// returnStringsAsBuffers: true, +// replies: [[Buffer.from('aa')]] +// }); +// }); +// }); + +// describe('Array', () => { +// describe('null', () => { +// generateTests({ +// toWrite: Buffer.from('*-1\r\n'), +// returnStringsAsBuffers: false, +// replies: [[null]] +// }); +// }); + +// const arrayBuffer = Buffer.from( +// '*5\r\n' + +// '+OK\r\n' + +// '-ERR\r\n' + +// ':0\r\n' + +// '$1\r\na\r\n' + +// '*0\r\n' +// ); + +// describe('as strings', () => { +// generateTests({ +// toWrite: arrayBuffer, +// returnStringsAsBuffers: false, +// replies: [[[ +// 'OK', +// new ErrorReply('ERR'), +// 0, +// 'a', +// [] +// ]]] +// }); +// }); + +// describe('as buffers', () => { +// generateTests({ +// toWrite: arrayBuffer, +// returnStringsAsBuffers: true, +// replies: [[[ +// Buffer.from('OK'), +// new ErrorReply('ERR'), +// 0, +// Buffer.from('a'), +// [] +// ]]] +// }); +// }); +// }); +// }); diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index a0824e440ba..8003590e70b 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -1,981 +1,981 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; -import RedisClient, { RedisClientType } from '.'; -import { RedisClientMultiCommandType } from './multi-command'; -import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; -import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; -import { defineScript } from '../lua-script'; -import { spy } from 'sinon'; -import { once } from 'events'; -import { ClientKillFilters } from '../commands/CLIENT_KILL'; -import { promisify } from 'util'; - -export const SQUARE_SCRIPT = defineScript({ - SCRIPT: 'return ARGV[1] * ARGV[1];', - NUMBER_OF_KEYS: 0, - transformArguments(number: number): Array { - return [number.toString()]; - } -}); - -export const MATH_FUNCTION = { - name: 'math', - engine: 'LUA', - code: `#!LUA name=math - redis.register_function{ - function_name = "square", - callback = function(keys, args) return args[1] * args[1] end, - flags = { "no-writes" } - }`, - library: { - square: { - NAME: 'square', - IS_READ_ONLY: true, - NUMBER_OF_KEYS: 0, - transformArguments(number: number): Array { - return [number.toString()]; - } - } - } -}; - -export async function loadMathFunction( - client: RedisClientType -): Promise { - await client.functionLoad( - MATH_FUNCTION.code, - { REPLACE: true } - ); -} - -describe('Client', () => { - describe('parseURL', () => { - it('redis://user:secret@localhost:6379/0', () => { - assert.deepEqual( - RedisClient.parseURL('redis://user:secret@localhost:6379/0'), - { - socket: { - host: 'localhost', - port: 6379 - }, - username: 'user', - password: 'secret', - database: 0 - } - ); - }); - - it('rediss://user:secret@localhost:6379/0', () => { - assert.deepEqual( - RedisClient.parseURL('rediss://user:secret@localhost:6379/0'), - { - socket: { - host: 'localhost', - port: 6379, - tls: true - }, - username: 'user', - password: 'secret', - database: 0 - } - ); - }); - - it('Invalid protocol', () => { - assert.throws( - () => RedisClient.parseURL('redi://user:secret@localhost:6379/0'), - TypeError - ); - }); - - it('Invalid pathname', () => { - assert.throws( - () => RedisClient.parseURL('redis://user:secret@localhost:6379/NaN'), - TypeError - ); - }); - - it('redis://localhost', () => { - assert.deepEqual( - RedisClient.parseURL('redis://localhost'), - { - socket: { - host: 'localhost', - } - } - ); - }); - }); - - describe('authentication', () => { - testUtils.testWithClient('Client should be authenticated', async client => { - assert.equal( - await client.ping(), - 'PONG' - ); - }, GLOBAL.SERVERS.PASSWORD); - - testUtils.testWithClient('should execute AUTH before SELECT', async client => { - assert.equal( - (await client.clientInfo()).db, - 2 - ); - }, { - ...GLOBAL.SERVERS.PASSWORD, - clientOptions: { - ...GLOBAL.SERVERS.PASSWORD.clientOptions, - database: 2 - }, - minimumDockerVersion: [6, 2] - }); - }); - - testUtils.testWithClient('should set connection name', async client => { - assert.equal( - await client.clientGetName(), - 'name' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - name: 'name' - } - }); - - describe('legacyMode', () => { - testUtils.testWithClient('client.sendCommand should call the callback', async client => { - assert.equal( - await promisify(client.sendCommand).call(client, 'PING'), - 'PONG' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.sendCommand should work without callback', async client => { - client.sendCommand(['PING']); - await client.v4.ping(); // make sure the first command was replied - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.sendCommand should reply with error', async client => { - await assert.rejects( - promisify(client.sendCommand).call(client, '1', '2') - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.hGetAll should reply with error', async client => { - await assert.rejects( - promisify(client.hGetAll).call(client) - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { - assert.equal( - await client.v4.sendCommand(['PING']), - 'PONG' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.v4.{command} should return a promise', async client => { - assert.equal( - await client.v4.ping(), - 'PONG' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { - assert.equal( - await promisify(client.set).call(client, 'a', 'b'), - 'OK' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.{command} should accept arguments array', async client => { - assert.equal( - await promisify(client.set).call(client, ['a', 'b']), - 'OK' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { - assert.equal( - await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), - 'OK' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.hGetAll should return object', async client => { - await client.v4.hSet('key', 'field', 'value'); +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; +// import RedisClient, { RedisClientType } from '.'; +// import { RedisClientMultiCommandType } from './multi-command'; +// import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; +// import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; +// import { defineScript } from '../lua-script'; +// import { spy } from 'sinon'; +// import { once } from 'events'; +// import { ClientKillFilters } from '../commands/CLIENT_KILL'; +// import { promisify } from 'util'; + +// export const SQUARE_SCRIPT = defineScript({ +// SCRIPT: 'return ARGV[1] * ARGV[1];', +// NUMBER_OF_KEYS: 0, +// transformArguments(number: number): Array { +// return [number.toString()]; +// } +// }); + +// export const MATH_FUNCTION = { +// name: 'math', +// engine: 'LUA', +// code: `#!LUA name=math +// redis.register_function{ +// function_name = "square", +// callback = function(keys, args) return args[1] * args[1] end, +// flags = { "no-writes" } +// }`, +// library: { +// square: { +// NAME: 'square', +// IS_READ_ONLY: true, +// NUMBER_OF_KEYS: 0, +// transformArguments(number: number): Array { +// return [number.toString()]; +// } +// } +// } +// }; + +// export async function loadMathFunction( +// client: RedisClientType +// ): Promise { +// await client.functionLoad( +// MATH_FUNCTION.code, +// { REPLACE: true } +// ); +// } + +// describe('Client', () => { +// describe('parseURL', () => { +// it('redis://user:secret@localhost:6379/0', () => { +// assert.deepEqual( +// RedisClient.parseURL('redis://user:secret@localhost:6379/0'), +// { +// socket: { +// host: 'localhost', +// port: 6379 +// }, +// username: 'user', +// password: 'secret', +// database: 0 +// } +// ); +// }); + +// it('rediss://user:secret@localhost:6379/0', () => { +// assert.deepEqual( +// RedisClient.parseURL('rediss://user:secret@localhost:6379/0'), +// { +// socket: { +// host: 'localhost', +// port: 6379, +// tls: true +// }, +// username: 'user', +// password: 'secret', +// database: 0 +// } +// ); +// }); + +// it('Invalid protocol', () => { +// assert.throws( +// () => RedisClient.parseURL('redi://user:secret@localhost:6379/0'), +// TypeError +// ); +// }); + +// it('Invalid pathname', () => { +// assert.throws( +// () => RedisClient.parseURL('redis://user:secret@localhost:6379/NaN'), +// TypeError +// ); +// }); + +// it('redis://localhost', () => { +// assert.deepEqual( +// RedisClient.parseURL('redis://localhost'), +// { +// socket: { +// host: 'localhost', +// } +// } +// ); +// }); +// }); + +// describe('authentication', () => { +// testUtils.testWithClient('Client should be authenticated', async client => { +// assert.equal( +// await client.ping(), +// 'PONG' +// ); +// }, GLOBAL.SERVERS.PASSWORD); + +// testUtils.testWithClient('should execute AUTH before SELECT', async client => { +// assert.equal( +// (await client.clientInfo()).db, +// 2 +// ); +// }, { +// ...GLOBAL.SERVERS.PASSWORD, +// clientOptions: { +// ...GLOBAL.SERVERS.PASSWORD.clientOptions, +// database: 2 +// }, +// minimumDockerVersion: [6, 2] +// }); +// }); + +// testUtils.testWithClient('should set connection name', async client => { +// assert.equal( +// await client.clientGetName(), +// 'name' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// name: 'name' +// } +// }); + +// describe('legacyMode', () => { +// testUtils.testWithClient('client.sendCommand should call the callback', async client => { +// assert.equal( +// await promisify(client.sendCommand).call(client, 'PING'), +// 'PONG' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.sendCommand should work without callback', async client => { +// client.sendCommand(['PING']); +// await client.v4.ping(); // make sure the first command was replied +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.sendCommand should reply with error', async client => { +// await assert.rejects( +// promisify(client.sendCommand).call(client, '1', '2') +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.hGetAll should reply with error', async client => { +// await assert.rejects( +// promisify(client.hGetAll).call(client) +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { +// assert.equal( +// await client.v4.sendCommand(['PING']), +// 'PONG' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.v4.{command} should return a promise', async client => { +// assert.equal( +// await client.v4.ping(), +// 'PONG' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { +// assert.equal( +// await promisify(client.set).call(client, 'a', 'b'), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.{command} should accept arguments array', async client => { +// assert.equal( +// await promisify(client.set).call(client, ['a', 'b']), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { +// assert.equal( +// await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.hGetAll should return object', async client => { +// await client.v4.hSet('key', 'field', 'value'); - assert.deepEqual( - await promisify(client.hGetAll).call(client, 'key'), - Object.create(null, { - field: { - value: 'value', - configurable: true, - enumerable: true - } - }) - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - function multiExecAsync< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >(multi: RedisClientMultiCommandType): Promise> { - return new Promise((resolve, reject) => { - (multi as any).exec((err: Error | undefined, replies: Array) => { - if (err) return reject(err); - - resolve(replies); - }); - }); - } - - testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { - assert.deepEqual( - await multiExecAsync( - client.multi().ping() - ), - ['PONG'] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { - client.multi() - .ping() - .exec(); - await client.v4.ping(); // make sure the first command was replied - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { - assert.deepEqual( - await client.multi() - .ping() - .v4.ping() - .v4.exec(), - ['PONG', 'PONG'] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.{script} should return a promise', async client => { - assert.equal( - await client.square(2), - 4 - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true, - scripts: { - square: SQUARE_SCRIPT - } - } - }); - - testUtils.testWithClient('client.multi.{command}.exec should flatten array arguments', async client => { - assert.deepEqual( - await client.multi() - .sAdd('a', ['b', 'c']) - .v4.exec(), - [2] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - - testUtils.testWithClient('client.multi.hGetAll should return object', async client => { - assert.deepEqual( - await multiExecAsync( - client.multi() - .hSet('key', 'field', 'value') - .hGetAll('key') - ), - [ - 1, - Object.create(null, { - field: { - value: 'value', - configurable: true, - enumerable: true - } - }) - ] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - legacyMode: true - } - }); - }); - - describe('events', () => { - testUtils.testWithClient('connect, ready, end', async client => { - await Promise.all([ - once(client, 'connect'), - once(client, 'ready'), - client.connect() - ]); - - await Promise.all([ - once(client, 'end'), - client.disconnect() - ]); - }, { - ...GLOBAL.SERVERS.OPEN, - disableClientSetup: true - }); - }); - - describe('sendCommand', () => { - testUtils.testWithClient('PING', async client => { - assert.equal(await client.sendCommand(['PING']), 'PONG'); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('returnBuffers', async client => { - assert.deepEqual( - await client.sendCommand(['PING'], { - returnBuffers: true - }), - Buffer.from('PONG') - ); - }, GLOBAL.SERVERS.OPEN); - - describe('AbortController', () => { - before(function () { - if (!global.AbortController) { - this.skip(); - } - }); - - testUtils.testWithClient('success', async client => { - await client.sendCommand(['PING'], { - signal: new AbortController().signal - }); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('AbortError', client => { - const controller = new AbortController(); - controller.abort(); - - return assert.rejects( - client.sendCommand(['PING'], { - signal: controller.signal - }), - AbortError - ); - }, GLOBAL.SERVERS.OPEN); - }); - - testUtils.testWithClient('undefined and null should not break the client', async client => { - await assert.rejects( - client.sendCommand([null as any, undefined as any]), - TypeError - ); - - assert.equal( - await client.ping(), - 'PONG' - ); - }, GLOBAL.SERVERS.OPEN); - }); - - describe('multi', () => { - testUtils.testWithClient('simple', async client => { - assert.deepEqual( - await client.multi() - .ping() - .set('key', 'value') - .get('key') - .exec(), - ['PONG', 'OK', 'value'] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should reject the whole chain on error', client => { - return assert.rejects( - client.multi() - .ping() - .addCommand(['INVALID COMMAND']) - .ping() - .exec() - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { - await client.disconnect(); - - return assert.rejects( - client.multi() - .ping() - .set('key', 'value') - .get('key') - .exec(), - ClientClosedError - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with script', async client => { - assert.deepEqual( - await client.multi() - .square(2) - .exec(), - [4] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - scripts: { - square: SQUARE_SCRIPT - } - } - }); - - testUtils.testWithClient('WatchError', async client => { - await client.watch('key'); - - await client.set( - RedisClient.commandOptions({ - isolated: true - }), - 'key', - '1' - ); - - await assert.rejects( - client.multi() - .decr('key') - .exec(), - WatchError - ); - }, GLOBAL.SERVERS.OPEN); - - describe('execAsPipeline', () => { - testUtils.testWithClient('exec(true)', async client => { - assert.deepEqual( - await client.multi() - .ping() - .exec(true), - ['PONG'] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('empty execAsPipeline', async client => { - assert.deepEqual( - await client.multi().execAsPipeline(), - [] - ); - }, GLOBAL.SERVERS.OPEN); - }); - - testUtils.testWithClient('should remember selected db', async client => { - await client.multi() - .select(1) - .exec(); - await killClient(client); - assert.equal( - (await client.clientInfo()).db, - 1 - ); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [6, 2] // CLIENT INFO - }); - }); - - testUtils.testWithClient('scripts', async client => { - assert.equal( - await client.square(2), - 4 - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - scripts: { - square: SQUARE_SCRIPT - } - } - }); - - const module = { - echo: { - transformArguments(message: string): Array { - return ['ECHO', message]; - }, - transformReply(reply: string): string { - return reply; - } - } - }; - - testUtils.testWithClient('modules', async client => { - assert.equal( - await client.module.echo('message'), - 'message' - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - modules: { - module - } - } - }); - - testUtils.testWithClient('functions', async client => { - await loadMathFunction(client); - - assert.equal( - await client.math.square(2), - 4 - ); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [7, 0], - clientOptions: { - functions: { - math: MATH_FUNCTION.library - } - } - }); - - describe('isolationPool', () => { - testUtils.testWithClient('executeIsolated', async client => { - const id = await client.clientId(), - isolatedId = await client.executeIsolated(isolatedClient => isolatedClient.clientId()); - assert.ok(id !== isolatedId); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should be able to use pool even before connect', async client => { - await client.executeIsolated(() => Promise.resolve()); - // make sure to destroy isolation pool - await client.connect(); - await client.disconnect(); - }, { - ...GLOBAL.SERVERS.OPEN, - disableClientSetup: true - }); - - testUtils.testWithClient('should work after reconnect (#2406)', async client => { - await client.disconnect(); - await client.connect(); - await client.executeIsolated(() => Promise.resolve()); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should throw ClientClosedError after disconnect', async client => { - await client.connect(); - await client.disconnect(); - await assert.rejects( - client.executeIsolated(() => Promise.resolve()), - ClientClosedError - ); - }, { - ...GLOBAL.SERVERS.OPEN, - disableClientSetup: true - }); - }); - - async function killClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts - >( - client: RedisClientType, - errorClient: RedisClientType = client - ): Promise { - const onceErrorPromise = once(errorClient, 'error'); - await client.sendCommand(['QUIT']); - await Promise.all([ - onceErrorPromise, - assert.rejects(client.ping(), SocketClosedUnexpectedlyError) - ]); - } - - testUtils.testWithClient('should reconnect when socket disconnects', async client => { - await killClient(client); - await assert.doesNotReject(client.ping()); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should remember selected db', async client => { - await client.select(1); - await killClient(client); - assert.equal( - (await client.clientInfo()).db, - 1 - ); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [6, 2] // CLIENT INFO - }); - - testUtils.testWithClient('should propagated errors from "isolated" clients', client => { - client.on('error', () => { - // ignore errors - }); - return client.executeIsolated(isolated => killClient(isolated, client)); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('scanIterator', async client => { - const promises = [], - keys = new Set(); - for (let i = 0; i < 100; i++) { - const key = i.toString(); - keys.add(key); - promises.push(client.set(key, '')); - } - - await Promise.all(promises); - - const results = new Set(); - for await (const key of client.scanIterator()) { - results.add(key); - } - - assert.deepEqual(keys, results); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('hScanIterator', async client => { - const hash: Record = {}; - for (let i = 0; i < 100; i++) { - hash[i.toString()] = i.toString(); - } - - await client.hSet('key', hash); - - const results: Record = {}; - for await (const { field, value } of client.hScanIterator('key')) { - results[field] = value; - } - - assert.deepEqual(hash, results); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('sScanIterator', async client => { - const members = new Set(); - for (let i = 0; i < 100; i++) { - members.add(i.toString()); - } - - await client.sAdd('key', Array.from(members)); - - const results = new Set(); - for await (const key of client.sScanIterator('key')) { - results.add(key); - } - - assert.deepEqual(members, results); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('zScanIterator', async client => { - const members = []; - for (let i = 0; i < 100; i++) { - members.push({ - score: 1, - value: i.toString() - }); - } - - await client.zAdd('key', members); - - const map = new Map(); - for await (const member of client.zScanIterator('key')) { - map.set(member.value, member.score); - } - - type MemberTuple = [string, number]; - - function sort(a: MemberTuple, b: MemberTuple) { - return Number(b[0]) - Number(a[0]); - } - - assert.deepEqual( - [...map.entries()].sort(sort), - members.map(member => [member.value, member.score]).sort(sort) - ); - }, GLOBAL.SERVERS.OPEN); +// assert.deepEqual( +// await promisify(client.hGetAll).call(client, 'key'), +// Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true +// } +// }) +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// function multiExecAsync< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// >(multi: RedisClientMultiCommandType): Promise> { +// return new Promise((resolve, reject) => { +// (multi as any).exec((err: Error | undefined, replies: Array) => { +// if (err) return reject(err); + +// resolve(replies); +// }); +// }); +// } + +// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { +// assert.deepEqual( +// await multiExecAsync( +// client.multi().ping() +// ), +// ['PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { +// client.multi() +// .ping() +// .exec(); +// await client.v4.ping(); // make sure the first command was replied +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .v4.ping() +// .v4.exec(), +// ['PONG', 'PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.{script} should return a promise', async client => { +// assert.equal( +// await client.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true, +// scripts: { +// square: SQUARE_SCRIPT +// } +// } +// }); + +// testUtils.testWithClient('client.multi.{command}.exec should flatten array arguments', async client => { +// assert.deepEqual( +// await client.multi() +// .sAdd('a', ['b', 'c']) +// .v4.exec(), +// [2] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); + +// testUtils.testWithClient('client.multi.hGetAll should return object', async client => { +// assert.deepEqual( +// await multiExecAsync( +// client.multi() +// .hSet('key', 'field', 'value') +// .hGetAll('key') +// ), +// [ +// 1, +// Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true +// } +// }) +// ] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); +// }); + +// describe('events', () => { +// testUtils.testWithClient('connect, ready, end', async client => { +// await Promise.all([ +// once(client, 'connect'), +// once(client, 'ready'), +// client.connect() +// ]); + +// await Promise.all([ +// once(client, 'end'), +// client.disconnect() +// ]); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); +// }); + +// describe('sendCommand', () => { +// testUtils.testWithClient('PING', async client => { +// assert.equal(await client.sendCommand(['PING']), 'PONG'); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('returnBuffers', async client => { +// assert.deepEqual( +// await client.sendCommand(['PING'], { +// returnBuffers: true +// }), +// Buffer.from('PONG') +// ); +// }, GLOBAL.SERVERS.OPEN); + +// describe('AbortController', () => { +// before(function () { +// if (!global.AbortController) { +// this.skip(); +// } +// }); + +// testUtils.testWithClient('success', async client => { +// await client.sendCommand(['PING'], { +// signal: new AbortController().signal +// }); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('AbortError', client => { +// const controller = new AbortController(); +// controller.abort(); + +// return assert.rejects( +// client.sendCommand(['PING'], { +// signal: controller.signal +// }), +// AbortError +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// testUtils.testWithClient('undefined and null should not break the client', async client => { +// await assert.rejects( +// client.sendCommand([null as any, undefined as any]), +// TypeError +// ); + +// assert.equal( +// await client.ping(), +// 'PONG' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// describe('multi', () => { +// testUtils.testWithClient('simple', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .set('key', 'value') +// .get('key') +// .exec(), +// ['PONG', 'OK', 'value'] +// ); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should reject the whole chain on error', client => { +// return assert.rejects( +// client.multi() +// .ping() +// .addCommand(['INVALID COMMAND']) +// .ping() +// .exec() +// ); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { +// await client.disconnect(); + +// return assert.rejects( +// client.multi() +// .ping() +// .set('key', 'value') +// .get('key') +// .exec(), +// ClientClosedError +// ); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('with script', async client => { +// assert.deepEqual( +// await client.multi() +// .square(2) +// .exec(), +// [4] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// scripts: { +// square: SQUARE_SCRIPT +// } +// } +// }); + +// testUtils.testWithClient('WatchError', async client => { +// await client.watch('key'); + +// await client.set( +// RedisClient.commandOptions({ +// isolated: true +// }), +// 'key', +// '1' +// ); + +// await assert.rejects( +// client.multi() +// .decr('key') +// .exec(), +// WatchError +// ); +// }, GLOBAL.SERVERS.OPEN); + +// describe('execAsPipeline', () => { +// testUtils.testWithClient('exec(true)', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .exec(true), +// ['PONG'] +// ); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('empty execAsPipeline', async client => { +// assert.deepEqual( +// await client.multi().execAsPipeline(), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// testUtils.testWithClient('should remember selected db', async client => { +// await client.multi() +// .select(1) +// .exec(); +// await killClient(client); +// assert.equal( +// (await client.clientInfo()).db, +// 1 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [6, 2] // CLIENT INFO +// }); +// }); + +// testUtils.testWithClient('scripts', async client => { +// assert.equal( +// await client.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// scripts: { +// square: SQUARE_SCRIPT +// } +// } +// }); + +// const module = { +// echo: { +// transformArguments(message: string): Array { +// return ['ECHO', message]; +// }, +// transformReply(reply: string): string { +// return reply; +// } +// } +// }; + +// testUtils.testWithClient('modules', async client => { +// assert.equal( +// await client.module.echo('message'), +// 'message' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// modules: { +// module +// } +// } +// }); + +// testUtils.testWithClient('functions', async client => { +// await loadMathFunction(client); + +// assert.equal( +// await client.math.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [7, 0], +// clientOptions: { +// functions: { +// math: MATH_FUNCTION.library +// } +// } +// }); + +// describe('isolationPool', () => { +// testUtils.testWithClient('executeIsolated', async client => { +// const id = await client.clientId(), +// isolatedId = await client.executeIsolated(isolatedClient => isolatedClient.clientId()); +// assert.ok(id !== isolatedId); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to use pool even before connect', async client => { +// await client.executeIsolated(() => Promise.resolve()); +// // make sure to destroy isolation pool +// await client.connect(); +// await client.disconnect(); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); + +// testUtils.testWithClient('should work after reconnect (#2406)', async client => { +// await client.disconnect(); +// await client.connect(); +// await client.executeIsolated(() => Promise.resolve()); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should throw ClientClosedError after disconnect', async client => { +// await client.connect(); +// await client.disconnect(); +// await assert.rejects( +// client.executeIsolated(() => Promise.resolve()), +// ClientClosedError +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); +// }); + +// async function killClient< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// >( +// client: RedisClientType, +// errorClient: RedisClientType = client +// ): Promise { +// const onceErrorPromise = once(errorClient, 'error'); +// await client.sendCommand(['QUIT']); +// await Promise.all([ +// onceErrorPromise, +// assert.rejects(client.ping(), SocketClosedUnexpectedlyError) +// ]); +// } + +// testUtils.testWithClient('should reconnect when socket disconnects', async client => { +// await killClient(client); +// await assert.doesNotReject(client.ping()); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should remember selected db', async client => { +// await client.select(1); +// await killClient(client); +// assert.equal( +// (await client.clientInfo()).db, +// 1 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [6, 2] // CLIENT INFO +// }); + +// testUtils.testWithClient('should propagated errors from "isolated" clients', client => { +// client.on('error', () => { +// // ignore errors +// }); +// return client.executeIsolated(isolated => killClient(isolated, client)); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('scanIterator', async client => { +// const promises = [], +// keys = new Set(); +// for (let i = 0; i < 100; i++) { +// const key = i.toString(); +// keys.add(key); +// promises.push(client.set(key, '')); +// } + +// await Promise.all(promises); + +// const results = new Set(); +// for await (const key of client.scanIterator()) { +// results.add(key); +// } + +// assert.deepEqual(keys, results); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('hScanIterator', async client => { +// const hash: Record = {}; +// for (let i = 0; i < 100; i++) { +// hash[i.toString()] = i.toString(); +// } + +// await client.hSet('key', hash); + +// const results: Record = {}; +// for await (const { field, value } of client.hScanIterator('key')) { +// results[field] = value; +// } + +// assert.deepEqual(hash, results); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('sScanIterator', async client => { +// const members = new Set(); +// for (let i = 0; i < 100; i++) { +// members.add(i.toString()); +// } + +// await client.sAdd('key', Array.from(members)); + +// const results = new Set(); +// for await (const key of client.sScanIterator('key')) { +// results.add(key); +// } + +// assert.deepEqual(members, results); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('zScanIterator', async client => { +// const members = []; +// for (let i = 0; i < 100; i++) { +// members.push({ +// score: 1, +// value: i.toString() +// }); +// } + +// await client.zAdd('key', members); + +// const map = new Map(); +// for await (const member of client.zScanIterator('key')) { +// map.set(member.value, member.score); +// } + +// type MemberTuple = [string, number]; + +// function sort(a: MemberTuple, b: MemberTuple) { +// return Number(b[0]) - Number(a[0]); +// } + +// assert.deepEqual( +// [...map.entries()].sort(sort), +// members.map(member => [member.value, member.score]).sort(sort) +// ); +// }, GLOBAL.SERVERS.OPEN); - describe('PubSub', () => { - testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { - function assertStringListener(message: string, channel: string) { - assert.equal(typeof message, 'string'); - assert.equal(typeof channel, 'string'); - } - - function assertBufferListener(message: Buffer, channel: Buffer) { - assert.ok(Buffer.isBuffer(message)); - assert.ok(Buffer.isBuffer(channel)); - } - - const subscriber = publisher.duplicate(); - - await subscriber.connect(); - - try { - const channelListener1 = spy(assertBufferListener), - channelListener2 = spy(assertStringListener), - patternListener = spy(assertStringListener); - - await Promise.all([ - subscriber.subscribe('channel', channelListener1, true), - subscriber.subscribe('channel', channelListener2), - subscriber.pSubscribe('channel*', patternListener) - ]); - await Promise.all([ - waitTillBeenCalled(channelListener1), - waitTillBeenCalled(channelListener2), - waitTillBeenCalled(patternListener), - publisher.publish(Buffer.from('channel'), Buffer.from('message')) - ]); - - assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); - assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); - assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); - - await subscriber.unsubscribe('channel', channelListener1, true); - await Promise.all([ - waitTillBeenCalled(channelListener2), - waitTillBeenCalled(patternListener), - publisher.publish('channel', 'message') - ]); - assert.ok(channelListener1.calledOnce); - assert.ok(channelListener2.calledTwice); - assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); - assert.ok(patternListener.calledTwice); - assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); - await subscriber.unsubscribe('channel'); - await Promise.all([ - waitTillBeenCalled(patternListener), - publisher.publish('channel', 'message') - ]); - assert.ok(channelListener1.calledOnce); - assert.ok(channelListener2.calledTwice); - assert.ok(patternListener.calledThrice); - assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); - await subscriber.pUnsubscribe(); - await publisher.publish('channel', 'message'); - assert.ok(channelListener1.calledOnce); - assert.ok(channelListener2.calledTwice); - assert.ok(patternListener.calledThrice); - // should be able to send commands when unsubsribed from all channels (see #1652) - await assert.doesNotReject(subscriber.ping()); - } finally { - await subscriber.disconnect(); - } - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should resubscribe', async publisher => { - const subscriber = publisher.duplicate(); - - await subscriber.connect(); - - try { - const channelListener = spy(); - await subscriber.subscribe('channel', channelListener); - - const patternListener = spy(); - await subscriber.pSubscribe('channe*', patternListener); - - await Promise.all([ - once(subscriber, 'error'), - publisher.clientKill({ - filter: ClientKillFilters.SKIP_ME, - skipMe: true - }) - ]); - - await once(subscriber, 'ready'); - - await Promise.all([ - waitTillBeenCalled(channelListener), - waitTillBeenCalled(patternListener), - publisher.publish('channel', 'message') - ]); - } finally { - await subscriber.disconnect(); - } - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { - const subscriber = publisher.duplicate(); - - await subscriber.connect(); - - try { - await assert.doesNotReject(Promise.all([ - subscriber.subscribe('channel', () => { - // noop - }), - publisher.publish('channel', 'message') - ])); - } finally { - await subscriber.disconnect(); - } - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should be able to quit in PubSub mode', async client => { - await client.subscribe('channel', () => { - // noop - }); - - await assert.doesNotReject(client.quit()); - - assert.equal(client.isOpen, false); - }, GLOBAL.SERVERS.OPEN); - }); - - testUtils.testWithClient('ConnectionTimeoutError', async client => { - const promise = assert.rejects(client.connect(), ConnectionTimeoutError), - start = process.hrtime.bigint(); - - while (process.hrtime.bigint() - start < 1_000_000) { - // block the event loop for 1ms, to make sure the connection will timeout - } - - await promise; - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - socket: { - connectTimeout: 1 - } - }, - disableClientSetup: true - }); - - testUtils.testWithClient('client.quit', async client => { - await client.connect(); - - const pingPromise = client.ping(), - quitPromise = client.quit(); - assert.equal(client.isOpen, false); - - const [ping, quit] = await Promise.all([ - pingPromise, - quitPromise, - assert.rejects(client.ping(), ClientClosedError) - ]); - - assert.equal(ping, 'PONG'); - assert.equal(quit, 'OK'); - }, { - ...GLOBAL.SERVERS.OPEN, - disableClientSetup: true - }); - - testUtils.testWithClient('client.disconnect', async client => { - const pingPromise = client.ping(), - disconnectPromise = client.disconnect(); - assert.equal(client.isOpen, false); - await Promise.all([ - assert.rejects(pingPromise, DisconnectsClientError), - assert.doesNotReject(disconnectPromise), - assert.rejects(client.ping(), ClientClosedError) - ]); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { - await client.disconnect(); - await client.connect(); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('should be able to use ref and unref', client => { - client.unref(); - client.ref(); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('pingInterval', async client => { - assert.deepEqual( - await once(client, 'ping-interval'), - ['PONG'] - ); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - pingInterval: 1 - } - }); - - testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { - const connectPromise = client.connect(); - await assert.rejects( - client.ping(), - ClientOfflineError - ); - await connectPromise; - await client.disconnect(); - }, { - ...GLOBAL.SERVERS.OPEN, - clientOptions: { - disableOfflineQueue: true - }, - disableClientSetup: true - }); -}); +// describe('PubSub', () => { +// testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { +// function assertStringListener(message: string, channel: string) { +// assert.equal(typeof message, 'string'); +// assert.equal(typeof channel, 'string'); +// } + +// function assertBufferListener(message: Buffer, channel: Buffer) { +// assert.ok(Buffer.isBuffer(message)); +// assert.ok(Buffer.isBuffer(channel)); +// } + +// const subscriber = publisher.duplicate(); + +// await subscriber.connect(); + +// try { +// const channelListener1 = spy(assertBufferListener), +// channelListener2 = spy(assertStringListener), +// patternListener = spy(assertStringListener); + +// await Promise.all([ +// subscriber.subscribe('channel', channelListener1, true), +// subscriber.subscribe('channel', channelListener2), +// subscriber.pSubscribe('channel*', patternListener) +// ]); +// await Promise.all([ +// waitTillBeenCalled(channelListener1), +// waitTillBeenCalled(channelListener2), +// waitTillBeenCalled(patternListener), +// publisher.publish(Buffer.from('channel'), Buffer.from('message')) +// ]); + +// assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); +// assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); +// assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); + +// await subscriber.unsubscribe('channel', channelListener1, true); +// await Promise.all([ +// waitTillBeenCalled(channelListener2), +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') +// ]); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); +// assert.ok(patternListener.calledTwice); +// assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); +// await subscriber.unsubscribe('channel'); +// await Promise.all([ +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') +// ]); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(patternListener.calledThrice); +// assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); +// await subscriber.pUnsubscribe(); +// await publisher.publish('channel', 'message'); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(patternListener.calledThrice); +// // should be able to send commands when unsubsribed from all channels (see #1652) +// await assert.doesNotReject(subscriber.ping()); +// } finally { +// await subscriber.disconnect(); +// } +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should resubscribe', async publisher => { +// const subscriber = publisher.duplicate(); + +// await subscriber.connect(); + +// try { +// const channelListener = spy(); +// await subscriber.subscribe('channel', channelListener); + +// const patternListener = spy(); +// await subscriber.pSubscribe('channe*', patternListener); + +// await Promise.all([ +// once(subscriber, 'error'), +// publisher.clientKill({ +// filter: ClientKillFilters.SKIP_ME, +// skipMe: true +// }) +// ]); + +// await once(subscriber, 'ready'); + +// await Promise.all([ +// waitTillBeenCalled(channelListener), +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') +// ]); +// } finally { +// await subscriber.disconnect(); +// } +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { +// const subscriber = publisher.duplicate(); + +// await subscriber.connect(); + +// try { +// await assert.doesNotReject(Promise.all([ +// subscriber.subscribe('channel', () => { +// // noop +// }), +// publisher.publish('channel', 'message') +// ])); +// } finally { +// await subscriber.disconnect(); +// } +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to quit in PubSub mode', async client => { +// await client.subscribe('channel', () => { +// // noop +// }); + +// await assert.doesNotReject(client.quit()); + +// assert.equal(client.isOpen, false); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// testUtils.testWithClient('ConnectionTimeoutError', async client => { +// const promise = assert.rejects(client.connect(), ConnectionTimeoutError), +// start = process.hrtime.bigint(); + +// while (process.hrtime.bigint() - start < 1_000_000) { +// // block the event loop for 1ms, to make sure the connection will timeout +// } + +// await promise; +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// socket: { +// connectTimeout: 1 +// } +// }, +// disableClientSetup: true +// }); + +// testUtils.testWithClient('client.quit', async client => { +// await client.connect(); + +// const pingPromise = client.ping(), +// quitPromise = client.quit(); +// assert.equal(client.isOpen, false); + +// const [ping, quit] = await Promise.all([ +// pingPromise, +// quitPromise, +// assert.rejects(client.ping(), ClientClosedError) +// ]); + +// assert.equal(ping, 'PONG'); +// assert.equal(quit, 'OK'); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); + +// testUtils.testWithClient('client.disconnect', async client => { +// const pingPromise = client.ping(), +// disconnectPromise = client.disconnect(); +// assert.equal(client.isOpen, false); +// await Promise.all([ +// assert.rejects(pingPromise, DisconnectsClientError), +// assert.doesNotReject(disconnectPromise), +// assert.rejects(client.ping(), ClientClosedError) +// ]); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { +// await client.disconnect(); +// await client.connect(); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to use ref and unref', client => { +// client.unref(); +// client.ref(); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('pingInterval', async client => { +// assert.deepEqual( +// await once(client, 'ping-interval'), +// ['PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// pingInterval: 1 +// } +// }); + +// testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { +// const connectPromise = client.connect(); +// await assert.rejects( +// client.ping(), +// ClientOfflineError +// ); +// await connectPromise; +// await client.disconnect(); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// disableOfflineQueue: true +// }, +// disableClientSetup: true +// }); +// }); diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index 8200375056a..4c06dc8c917 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -1,362 +1,362 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; -import RedisCluster from '.'; -import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; -import { commandOptions } from '../command-options'; -import { SQUARE_SCRIPT } from '../client/index.spec'; -import { RootNodesUnavailableError } from '../errors'; -import { spy } from 'sinon'; -import { promiseTimeout } from '../utils'; -import RedisClient from '../client'; - -describe('Cluster', () => { - testUtils.testWithCluster('sendCommand', async cluster => { - assert.equal( - await cluster.sendCommand(undefined, true, ['PING']), - 'PONG' - ); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('isOpen', async cluster => { - assert.equal(cluster.isOpen, true); - await cluster.disconnect(); - assert.equal(cluster.isOpen, false); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('connect should throw if already connected', async cluster => { - await assert.rejects(cluster.connect()); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('multi', async cluster => { - const key = 'key'; - assert.deepEqual( - await cluster.multi() - .set(key, 'value') - .get(key) - .exec(), - ['OK', 'value'] - ); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('scripts', async cluster => { - assert.equal( - await cluster.square(2), - 4 - ); - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - scripts: { - square: SQUARE_SCRIPT - } - } - }); - - it('should throw RootNodesUnavailableError', async () => { - const cluster = RedisCluster.create({ - rootNodes: [] - }); - - try { - await assert.rejects( - cluster.connect(), - RootNodesUnavailableError - ); - } catch (err) { - await cluster.disconnect(); - throw err; - } - }); - - testUtils.testWithCluster('should handle live resharding', async cluster => { - const slot = 12539, - key = 'key', - value = 'value'; - await cluster.set(key, value); - - const importing = cluster.slots[0].master, - migrating = cluster.slots[slot].master, - [ importingClient, migratingClient ] = await Promise.all([ - cluster.nodeClient(importing), - cluster.nodeClient(migrating) - ]); - - await Promise.all([ - importingClient.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, migrating.id), - migratingClient.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, importing.id) - ]); - - // should be able to get the key from the migrating node - assert.equal( - await cluster.get(key), - value - ); - - await migratingClient.migrate( - importing.host, - importing.port, - key, - 0, - 10 - ); - - // should be able to get the key from the importing node using `ASKING` - assert.equal( - await cluster.get(key), - value - ); - - await Promise.all([ - importingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), - migratingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), - ]); - - // should handle `MOVED` errors - assert.equal( - await cluster.get(key), - value - ); - }, { - serverArguments: [], - numberOfMasters: 2 - }); - - testUtils.testWithCluster('getRandomNode should spread the the load evenly', async cluster => { - const totalNodes = cluster.masters.length + cluster.replicas.length, - ids = new Set(); - for (let i = 0; i < totalNodes; i++) { - ids.add(cluster.getRandomNode().id); - } +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; +// import RedisCluster from '.'; +// import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; +// import { commandOptions } from '../command-options'; +// import { SQUARE_SCRIPT } from '../client/index.spec'; +// import { RootNodesUnavailableError } from '../errors'; +// import { spy } from 'sinon'; +// import { promiseTimeout } from '../utils'; +// import RedisClient from '../client'; + +// describe('Cluster', () => { +// testUtils.testWithCluster('sendCommand', async cluster => { +// assert.equal( +// await cluster.sendCommand(undefined, true, ['PING']), +// 'PONG' +// ); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('isOpen', async cluster => { +// assert.equal(cluster.isOpen, true); +// await cluster.disconnect(); +// assert.equal(cluster.isOpen, false); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('connect should throw if already connected', async cluster => { +// await assert.rejects(cluster.connect()); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('multi', async cluster => { +// const key = 'key'; +// assert.deepEqual( +// await cluster.multi() +// .set(key, 'value') +// .get(key) +// .exec(), +// ['OK', 'value'] +// ); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('scripts', async cluster => { +// assert.equal( +// await cluster.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// scripts: { +// square: SQUARE_SCRIPT +// } +// } +// }); + +// it('should throw RootNodesUnavailableError', async () => { +// const cluster = RedisCluster.create({ +// rootNodes: [] +// }); + +// try { +// await assert.rejects( +// cluster.connect(), +// RootNodesUnavailableError +// ); +// } catch (err) { +// await cluster.disconnect(); +// throw err; +// } +// }); + +// testUtils.testWithCluster('should handle live resharding', async cluster => { +// const slot = 12539, +// key = 'key', +// value = 'value'; +// await cluster.set(key, value); + +// const importing = cluster.slots[0].master, +// migrating = cluster.slots[slot].master, +// [ importingClient, migratingClient ] = await Promise.all([ +// cluster.nodeClient(importing), +// cluster.nodeClient(migrating) +// ]); + +// await Promise.all([ +// importingClient.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, migrating.id), +// migratingClient.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, importing.id) +// ]); + +// // should be able to get the key from the migrating node +// assert.equal( +// await cluster.get(key), +// value +// ); + +// await migratingClient.migrate( +// importing.host, +// importing.port, +// key, +// 0, +// 10 +// ); + +// // should be able to get the key from the importing node using `ASKING` +// assert.equal( +// await cluster.get(key), +// value +// ); + +// await Promise.all([ +// importingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), +// migratingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), +// ]); + +// // should handle `MOVED` errors +// assert.equal( +// await cluster.get(key), +// value +// ); +// }, { +// serverArguments: [], +// numberOfMasters: 2 +// }); + +// testUtils.testWithCluster('getRandomNode should spread the the load evenly', async cluster => { +// const totalNodes = cluster.masters.length + cluster.replicas.length, +// ids = new Set(); +// for (let i = 0; i < totalNodes; i++) { +// ids.add(cluster.getRandomNode().id); +// } - assert.equal(ids.size, totalNodes); - }, GLOBAL.CLUSTERS.WITH_REPLICAS); - - testUtils.testWithCluster('getSlotRandomNode should spread the the load evenly', async cluster => { - const totalNodes = 1 + cluster.slots[0].replicas!.length, - ids = new Set(); - for (let i = 0; i < totalNodes; i++) { - ids.add(cluster.getSlotRandomNode(0).id); - } +// assert.equal(ids.size, totalNodes); +// }, GLOBAL.CLUSTERS.WITH_REPLICAS); + +// testUtils.testWithCluster('getSlotRandomNode should spread the the load evenly', async cluster => { +// const totalNodes = 1 + cluster.slots[0].replicas!.length, +// ids = new Set(); +// for (let i = 0; i < totalNodes; i++) { +// ids.add(cluster.getSlotRandomNode(0).id); +// } - assert.equal(ids.size, totalNodes); - }, GLOBAL.CLUSTERS.WITH_REPLICAS); - - testUtils.testWithCluster('cluster topology', async cluster => { - assert.equal(cluster.slots.length, 16384); - const { numberOfMasters, numberOfReplicas } = GLOBAL.CLUSTERS.WITH_REPLICAS; - assert.equal(cluster.shards.length, numberOfMasters); - assert.equal(cluster.masters.length, numberOfMasters); - assert.equal(cluster.replicas.length, numberOfReplicas * numberOfMasters); - assert.equal(cluster.nodeByAddress.size, numberOfMasters + numberOfMasters * numberOfReplicas); - }, GLOBAL.CLUSTERS.WITH_REPLICAS); - - testUtils.testWithCluster('getMasters should be backwards competiable (without `minimizeConnections`)', async cluster => { - const masters = cluster.getMasters(); - assert.ok(Array.isArray(masters)); - for (const master of masters) { - assert.equal(typeof master.id, 'string'); - assert.ok(master.client instanceof RedisClient); - } - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - minimizeConnections: undefined // reset to default - } - }); - - testUtils.testWithCluster('getSlotMaster should be backwards competiable (without `minimizeConnections`)', async cluster => { - const master = cluster.getSlotMaster(0); - assert.equal(typeof master.id, 'string'); - assert.ok(master.client instanceof RedisClient); - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - minimizeConnections: undefined // reset to default - } - }); - - testUtils.testWithCluster('should throw CROSSSLOT error', async cluster => { - await assert.rejects(cluster.mGet(['a', 'b'])); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('should send commands with commandOptions to correct cluster slot (without redirections)', async cluster => { - // 'a' and 'b' hash to different cluster slots (see previous unit test) - // -> maxCommandRedirections 0: rejects on MOVED/ASK reply - await cluster.set(commandOptions({ isolated: true }), 'a', '1'), - await cluster.set(commandOptions({ isolated: true }), 'b', '2'), - - assert.equal(await cluster.get('a'), '1'); - assert.equal(await cluster.get('b'), '2'); - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - maxCommandRedirections: 0 - } - }); - - describe('minimizeConnections', () => { - testUtils.testWithCluster('false', async cluster => { - for (const master of cluster.masters) { - assert.ok(master.client instanceof RedisClient); - } - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - minimizeConnections: false - } - }); - - testUtils.testWithCluster('true', async cluster => { - for (const master of cluster.masters) { - assert.equal(master.client, undefined); - } - }, { - ...GLOBAL.CLUSTERS.OPEN, - clusterConfiguration: { - minimizeConnections: true - } - }); - }); - - describe('PubSub', () => { - testUtils.testWithCluster('subscribe & unsubscribe', async cluster => { - const listener = spy(); - - await cluster.subscribe('channel', listener); - - await Promise.all([ - waitTillBeenCalled(listener), - cluster.publish('channel', 'message') - ]); +// assert.equal(ids.size, totalNodes); +// }, GLOBAL.CLUSTERS.WITH_REPLICAS); + +// testUtils.testWithCluster('cluster topology', async cluster => { +// assert.equal(cluster.slots.length, 16384); +// const { numberOfMasters, numberOfReplicas } = GLOBAL.CLUSTERS.WITH_REPLICAS; +// assert.equal(cluster.shards.length, numberOfMasters); +// assert.equal(cluster.masters.length, numberOfMasters); +// assert.equal(cluster.replicas.length, numberOfReplicas * numberOfMasters); +// assert.equal(cluster.nodeByAddress.size, numberOfMasters + numberOfMasters * numberOfReplicas); +// }, GLOBAL.CLUSTERS.WITH_REPLICAS); + +// testUtils.testWithCluster('getMasters should be backwards competiable (without `minimizeConnections`)', async cluster => { +// const masters = cluster.getMasters(); +// assert.ok(Array.isArray(masters)); +// for (const master of masters) { +// assert.equal(typeof master.id, 'string'); +// assert.ok(master.client instanceof RedisClient); +// } +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// minimizeConnections: undefined // reset to default +// } +// }); + +// testUtils.testWithCluster('getSlotMaster should be backwards competiable (without `minimizeConnections`)', async cluster => { +// const master = cluster.getSlotMaster(0); +// assert.equal(typeof master.id, 'string'); +// assert.ok(master.client instanceof RedisClient); +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// minimizeConnections: undefined // reset to default +// } +// }); + +// testUtils.testWithCluster('should throw CROSSSLOT error', async cluster => { +// await assert.rejects(cluster.mGet(['a', 'b'])); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('should send commands with commandOptions to correct cluster slot (without redirections)', async cluster => { +// // 'a' and 'b' hash to different cluster slots (see previous unit test) +// // -> maxCommandRedirections 0: rejects on MOVED/ASK reply +// await cluster.set(commandOptions({ isolated: true }), 'a', '1'), +// await cluster.set(commandOptions({ isolated: true }), 'b', '2'), + +// assert.equal(await cluster.get('a'), '1'); +// assert.equal(await cluster.get('b'), '2'); +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// maxCommandRedirections: 0 +// } +// }); + +// describe('minimizeConnections', () => { +// testUtils.testWithCluster('false', async cluster => { +// for (const master of cluster.masters) { +// assert.ok(master.client instanceof RedisClient); +// } +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// minimizeConnections: false +// } +// }); + +// testUtils.testWithCluster('true', async cluster => { +// for (const master of cluster.masters) { +// assert.equal(master.client, undefined); +// } +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// clusterConfiguration: { +// minimizeConnections: true +// } +// }); +// }); + +// describe('PubSub', () => { +// testUtils.testWithCluster('subscribe & unsubscribe', async cluster => { +// const listener = spy(); + +// await cluster.subscribe('channel', listener); + +// await Promise.all([ +// waitTillBeenCalled(listener), +// cluster.publish('channel', 'message') +// ]); - assert.ok(listener.calledOnceWithExactly('message', 'channel')); +// assert.ok(listener.calledOnceWithExactly('message', 'channel')); - await cluster.unsubscribe('channel', listener); +// await cluster.unsubscribe('channel', listener); - assert.equal(cluster.pubSubNode, undefined); - }, GLOBAL.CLUSTERS.OPEN); +// assert.equal(cluster.pubSubNode, undefined); +// }, GLOBAL.CLUSTERS.OPEN); - testUtils.testWithCluster('psubscribe & punsubscribe', async cluster => { - const listener = spy(); +// testUtils.testWithCluster('psubscribe & punsubscribe', async cluster => { +// const listener = spy(); - await cluster.pSubscribe('channe*', listener); +// await cluster.pSubscribe('channe*', listener); - await Promise.all([ - waitTillBeenCalled(listener), - cluster.publish('channel', 'message') - ]); +// await Promise.all([ +// waitTillBeenCalled(listener), +// cluster.publish('channel', 'message') +// ]); - assert.ok(listener.calledOnceWithExactly('message', 'channel')); - - await cluster.pUnsubscribe('channe*', listener); - - assert.equal(cluster.pubSubNode, undefined); - }, GLOBAL.CLUSTERS.OPEN); - - testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { - const listener = spy(); - await cluster.subscribe('channel', listener); - - assert.ok(cluster.pubSubNode); - const [ migrating, importing ] = cluster.masters[0].address === cluster.pubSubNode.address ? - cluster.masters : - [cluster.masters[1], cluster.masters[0]], - [ migratingClient, importingClient ] = await Promise.all([ - cluster.nodeClient(migrating), - cluster.nodeClient(importing) - ]); - - const range = cluster.slots[0].master === migrating ? { - key: 'bar', // 5061 - start: 0, - end: 8191 - } : { - key: 'foo', // 12182 - start: 8192, - end: 16383 - }; - - await Promise.all([ - migratingClient.clusterDelSlotsRange(range), - importingClient.clusterDelSlotsRange(range), - importingClient.clusterAddSlotsRange(range) - ]); - - // wait for migrating node to be notified about the new topology - while ((await migratingClient.clusterInfo()).state !== 'ok') { - await promiseTimeout(50); - } - - // make sure to cause `MOVED` error - await cluster.get(range.key); - - await Promise.all([ - cluster.publish('channel', 'message'), - waitTillBeenCalled(listener) - ]); +// assert.ok(listener.calledOnceWithExactly('message', 'channel')); + +// await cluster.pUnsubscribe('channe*', listener); + +// assert.equal(cluster.pubSubNode, undefined); +// }, GLOBAL.CLUSTERS.OPEN); + +// testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { +// const listener = spy(); +// await cluster.subscribe('channel', listener); + +// assert.ok(cluster.pubSubNode); +// const [ migrating, importing ] = cluster.masters[0].address === cluster.pubSubNode.address ? +// cluster.masters : +// [cluster.masters[1], cluster.masters[0]], +// [ migratingClient, importingClient ] = await Promise.all([ +// cluster.nodeClient(migrating), +// cluster.nodeClient(importing) +// ]); + +// const range = cluster.slots[0].master === migrating ? { +// key: 'bar', // 5061 +// start: 0, +// end: 8191 +// } : { +// key: 'foo', // 12182 +// start: 8192, +// end: 16383 +// }; + +// await Promise.all([ +// migratingClient.clusterDelSlotsRange(range), +// importingClient.clusterDelSlotsRange(range), +// importingClient.clusterAddSlotsRange(range) +// ]); + +// // wait for migrating node to be notified about the new topology +// while ((await migratingClient.clusterInfo()).state !== 'ok') { +// await promiseTimeout(50); +// } + +// // make sure to cause `MOVED` error +// await cluster.get(range.key); + +// await Promise.all([ +// cluster.publish('channel', 'message'), +// waitTillBeenCalled(listener) +// ]); - assert.ok(listener.calledOnceWithExactly('message', 'channel')); - }, { - serverArguments: [], - numberOfMasters: 2, - minimumDockerVersion: [7] - }); - - testUtils.testWithCluster('ssubscribe & sunsubscribe', async cluster => { - const listener = spy(); - - await cluster.sSubscribe('channel', listener); - - await Promise.all([ - waitTillBeenCalled(listener), - cluster.sPublish('channel', 'message') - ]); +// assert.ok(listener.calledOnceWithExactly('message', 'channel')); +// }, { +// serverArguments: [], +// numberOfMasters: 2, +// minimumDockerVersion: [7] +// }); + +// testUtils.testWithCluster('ssubscribe & sunsubscribe', async cluster => { +// const listener = spy(); + +// await cluster.sSubscribe('channel', listener); + +// await Promise.all([ +// waitTillBeenCalled(listener), +// cluster.sPublish('channel', 'message') +// ]); - assert.ok(listener.calledOnceWithExactly('message', 'channel')); - - await cluster.sUnsubscribe('channel', listener); - - // 10328 is the slot of `channel` - assert.equal(cluster.slots[10328].master.pubSubClient, undefined); - }, { - ...GLOBAL.CLUSTERS.OPEN, - minimumDockerVersion: [7] - }); - - testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { - const SLOT = 10328, - migrating = cluster.slots[SLOT].master, - importing = cluster.masters.find(master => master !== migrating)!, - [ migratingClient, importingClient ] = await Promise.all([ - cluster.nodeClient(migrating), - cluster.nodeClient(importing) - ]); - - await Promise.all([ - migratingClient.clusterDelSlots(SLOT), - importingClient.clusterDelSlots(SLOT), - importingClient.clusterAddSlots(SLOT) - ]); - - // wait for migrating node to be notified about the new topology - while ((await migratingClient.clusterInfo()).state !== 'ok') { - await promiseTimeout(50); - } - - const listener = spy(); - - // will trigger `MOVED` error - await cluster.sSubscribe('channel', listener); - - await Promise.all([ - waitTillBeenCalled(listener), - cluster.sPublish('channel', 'message') - ]); +// assert.ok(listener.calledOnceWithExactly('message', 'channel')); + +// await cluster.sUnsubscribe('channel', listener); + +// // 10328 is the slot of `channel` +// assert.equal(cluster.slots[10328].master.pubSubClient, undefined); +// }, { +// ...GLOBAL.CLUSTERS.OPEN, +// minimumDockerVersion: [7] +// }); + +// testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { +// const SLOT = 10328, +// migrating = cluster.slots[SLOT].master, +// importing = cluster.masters.find(master => master !== migrating)!, +// [ migratingClient, importingClient ] = await Promise.all([ +// cluster.nodeClient(migrating), +// cluster.nodeClient(importing) +// ]); + +// await Promise.all([ +// migratingClient.clusterDelSlots(SLOT), +// importingClient.clusterDelSlots(SLOT), +// importingClient.clusterAddSlots(SLOT) +// ]); + +// // wait for migrating node to be notified about the new topology +// while ((await migratingClient.clusterInfo()).state !== 'ok') { +// await promiseTimeout(50); +// } + +// const listener = spy(); + +// // will trigger `MOVED` error +// await cluster.sSubscribe('channel', listener); + +// await Promise.all([ +// waitTillBeenCalled(listener), +// cluster.sPublish('channel', 'message') +// ]); - assert.ok(listener.calledOnceWithExactly('message', 'channel')); - }, { - serverArguments: [], - minimumDockerVersion: [7] - }); - }); -}); +// assert.ok(listener.calledOnceWithExactly('message', 'channel')); +// }, { +// serverArguments: [], +// minimumDockerVersion: [7] +// }); +// }); +// }); diff --git a/packages/client/lib/commands/APPEND.spec.ts b/packages/client/lib/commands/APPEND.spec.ts index 4481c0571e9..c85501f4a0c 100644 --- a/packages/client/lib/commands/APPEND.spec.ts +++ b/packages/client/lib/commands/APPEND.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import APPEND from './APPEND'; -describe.only('APPEND', () => { +describe('APPEND', () => { it('transformArguments', () => { assert.deepEqual( APPEND.transformArguments('key', 'value'), diff --git a/packages/client/lib/commands/PING.spec.ts b/packages/client/lib/commands/PING.spec.ts index fa2a8b172fb..5ea68074d72 100644 --- a/packages/client/lib/commands/PING.spec.ts +++ b/packages/client/lib/commands/PING.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import PING from './PING'; -describe.only('PING', () => { +describe('PING', () => { describe('transformArguments', () => { it('default', () => { assert.deepEqual( From 7bacad2e6928315eac01cd7d914376b1f8b05eb2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Apr 2023 12:57:36 -0400 Subject: [PATCH 022/325] wip --- .github/release-drafter-base.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/release-drafter-base.yml b/.github/release-drafter-base.yml index cd99c28b1f8..9a98b1c08a3 100644 --- a/.github/release-drafter-base.yml +++ b/.github/release-drafter-base.yml @@ -1,7 +1,5 @@ name-template: 'Version $NEXT_PATCH_VERSION' tag-template: 'v$NEXT_PATCH_VERSION' -include-path: - - {{ }} autolabeler: - label: 'chore' files: From 53ac48f298673afa69e7960f26f35e449ca2df76 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Apr 2023 17:43:29 -0400 Subject: [PATCH 023/325] some tests --- packages/client/lib/commands/ZADD.spec.ts | 255 ++++++++++-------- packages/client/lib/commands/ZADD.ts | 79 +++--- packages/client/lib/commands/ZCARD.spec.ts | 29 +- packages/client/lib/commands/ZCOUNT.spec.ts | 29 +- packages/client/lib/commands/ZDIFF.spec.ts | 45 ++-- .../client/lib/commands/ZDIFFSTORE.spec.ts | 45 ++-- .../lib/commands/ZDIFF_WITHSCORES.spec.ts | 45 ++-- packages/client/lib/commands/ZINCRBY.spec.ts | 29 +- packages/client/lib/commands/ZINTER.spec.ts | 99 +++---- .../client/lib/commands/ZINTERCARD.spec.ts | 45 ++-- .../client/lib/commands/ZINTERSTORE.spec.ts | 97 +++---- .../lib/commands/ZINTER_WITHSCORES.spec.ts | 99 +++---- .../client/lib/commands/ZLEXCOUNT.spec.ts | 29 +- packages/client/lib/commands/ZMPOP.spec.ts | 56 ++-- packages/client/lib/commands/ZMSCORE.spec.ts | 45 ++-- packages/client/lib/commands/ZMSCORE.ts | 4 +- packages/client/lib/commands/ZPOPMAX.spec.ts | 72 ++--- .../client/lib/commands/ZPOPMAX_COUNT.spec.ts | 34 +-- packages/client/lib/commands/ZPOPMIN.spec.ts | 72 ++--- .../client/lib/commands/ZPOPMIN_COUNT.spec.ts | 34 +-- .../client/lib/commands/ZRANDMEMBER.spec.ts | 31 ++- .../lib/commands/ZRANDMEMBER_COUNT.spec.ts | 31 ++- .../ZRANDMEMBER_COUNT_WITHSCORES.spec.ts | 31 ++- packages/client/lib/commands/ZRANGE.spec.ts | 127 ++++----- packages/client/lib/commands/ZRANGE.ts | 2 +- .../client/lib/commands/ZRANGEBYLEX.spec.ts | 60 ++--- .../client/lib/commands/ZRANGEBYSCORE.spec.ts | 60 ++--- .../commands/ZRANGEBYSCORE_WITHSCORES.spec.ts | 60 ++--- .../client/lib/commands/ZRANGESTORE.spec.ts | 164 +++++------ .../lib/commands/ZRANGE_WITHSCORES.spec.ts | 118 ++++---- packages/client/lib/commands/ZRANK.spec.ts | 29 +- packages/client/lib/commands/ZREM.spec.ts | 43 +-- .../lib/commands/ZREMRANGEBYLEX.spec.ts | 34 +-- .../lib/commands/ZREMRANGEBYRANK.spec.ts | 34 +-- .../lib/commands/ZREMRANGEBYSCORE.spec.ts | 34 +-- packages/client/lib/commands/ZREVRANK.spec.ts | 29 +- packages/client/lib/commands/ZSCAN.spec.ts | 107 +++----- packages/client/lib/commands/ZSCORE.spec.ts | 29 +- packages/client/lib/commands/ZUNION.spec.ts | 84 +++--- .../client/lib/commands/ZUNIONSTORE.spec.ts | 100 +++---- .../lib/commands/ZUNION_WITHSCORES.spec.ts | 84 +++--- packages/client/lib/commands/index.ts | 67 ++++- 42 files changed, 1373 insertions(+), 1227 deletions(-) diff --git a/packages/client/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts index 4f497bdca90..722856caa81 100644 --- a/packages/client/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -1,127 +1,158 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZADD'; +import ZADD from './ZADD'; describe('ZADD', () => { - describe('transformArguments', () => { - it('single member', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }), - ['ZADD', 'key', '1', '1'] - ); - }); + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }), + ['ZADD', 'key', '1', '1'] + ); + }); + + it('multiple members', () => { + assert.deepEqual( + ZADD.transformArguments('key', [{ + value: '1', + score: 1 + }, { + value: '2', + score: 2 + }]), + ['ZADD', 'key', '1', '1', '2', '2'] + ); + }); - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', [{ - value: '1', - score: 1 - }, { - value: '2', - score: 2 - }]), - ['ZADD', 'key', '1', '1', '2', '2'] - ); - }); + describe('with condition', () => { + it('condition property', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'NX' + }), + ['ZADD', 'key', 'NX', '1', '1'] + ); + }); - it('with NX', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - NX: true - }), - ['ZADD', 'key', 'NX', '1', '1'] - ); - }); + it('with NX (backwards compatibility)', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + NX: true + }), + ['ZADD', 'key', 'NX', '1', '1'] + ); + }); + + it('with XX (backwards compatibility)', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + XX: true + }), + ['ZADD', 'key', 'XX', '1', '1'] + ); + }); + }); - it('with XX', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - XX: true - }), - ['ZADD', 'key', 'XX', '1', '1'] - ); - }); + describe('with comparison', () => { + it('with LT', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + comparison: 'LT' + }), + ['ZADD', 'key', 'LT', '1', '1'] + ); + }); - it('with GT', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - GT: true - }), - ['ZADD', 'key', 'GT', '1', '1'] - ); - }); + it('with LT (backwards compatibility)', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + LT: true + }), + ['ZADD', 'key', 'LT', '1', '1'] + ); + }); - it('with LT', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - LT: true - }), - ['ZADD', 'key', 'LT', '1', '1'] - ); - }); + it('with GT (backwards compatibility)', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + GT: true + }), + ['ZADD', 'key', 'GT', '1', '1'] + ); + }); + }); - it('with CH', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - CH: true - }), - ['ZADD', 'key', 'CH', '1', '1'] - ); - }); + it('with CH', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + CH: true + }), + ['ZADD', 'key', 'CH', '1', '1'] + ); + }); - it('with INCR', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - INCR: true - }), - ['ZADD', 'key', 'INCR', '1', '1'] - ); - }); + it('with INCR', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + INCR: true + }), + ['ZADD', 'key', 'INCR', '1', '1'] + ); + }); - it('with XX, GT, CH, INCR', () => { - assert.deepEqual( - transformArguments('key', { - value: '1', - score: 1 - }, { - XX: true, - GT: true, - CH: true, - INCR: true - }), - ['ZADD', 'key', 'XX', 'GT', 'CH', 'INCR', '1', '1'] - ); - }); + it('with condition, comparison, CH, INCR', () => { + assert.deepEqual( + ZADD.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'XX', + comparison: 'LT', + CH: true, + INCR: true + }), + ['ZADD', 'key', 'XX', 'LT', 'CH', 'INCR', '1', '1'] + ); }); + }); - testUtils.testWithClient('client.zAdd', async client => { - assert.equal( - await client.zAdd('key', { - value: '1', - score: 1 - }), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zAdd', async client => { + assert.equal( + await client.zAdd('key', { + value: '1', + score: 1 + }), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index 0c2a1e105d8..49a839fb6f3 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,32 +1,29 @@ import { RedisArgument, NumberReply, DoubleReply, Command } from '../RESP/types'; import { ZMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; -interface NX { +export interface ZAddOptions { + condition?: 'NX' | 'XX'; + /** + * @deprecated Use `{ condition: 'NX' }` instead. + */ NX?: boolean; -} - -interface XX { + /** + * @deprecated Use `{ condition: 'XX' }` instead. + */ XX?: boolean; -} - -interface LT { + comparison?: 'LT' | 'GT'; + /** + * @deprecated Use `{ comparison: 'LT' }` instead. + */ LT?: boolean; -} - -interface GT { + /** + * @deprecated Use `{ comparison: 'GT' }` instead. + */ GT?: boolean; -} - -interface CH { CH?: boolean; -} - -interface INCR { INCR?: boolean; } -export type ZAddOptions = (NX | (XX & LT & GT)) & CH & INCR; - export default { FIRST_KEY_INDEX: 1, transformArguments( @@ -36,35 +33,36 @@ export default { ) { const args = ['ZADD', key]; - if ((options)?.NX) { + if (options?.condition) { + args.push(options.condition); + } else if (options?.NX) { args.push('NX'); - } else { - if ((options)?.XX) { - args.push('XX'); - } - - if ((options)?.GT) { - args.push('GT'); - } + } else if (options?.XX) { + args.push('XX'); + } - if ((options)?.LT) { - args.push('LT'); - } + if (options?.comparison) { + args.push(options.comparison); + } else if (options?.LT) { + args.push('LT'); + } else if (options?.GT) { + args.push('GT'); } - if ((options)?.CH) { + if (options?.CH) { args.push('CH'); } - if ((options)?.INCR) { + if (options?.INCR) { args.push('INCR'); } - for (const { score, value } of (Array.isArray(members) ? members : [members])) { - args.push( - transformDoubleArgument(score), - value - ); + if (Array.isArray(members)) { + for (const member of members) { + pushMember(args, member); + } + } else { + pushMember(args, members); } return args; @@ -74,3 +72,10 @@ export default { 3: undefined as unknown as () => NumberReply | DoubleReply } } as const satisfies Command; + +function pushMember(args: Array, member: ZMember) { + args.push( + transformDoubleArgument(member.score), + member.value + ); +} diff --git a/packages/client/lib/commands/ZCARD.spec.ts b/packages/client/lib/commands/ZCARD.spec.ts index 2e90da772b6..f0c566832df 100644 --- a/packages/client/lib/commands/ZCARD.spec.ts +++ b/packages/client/lib/commands/ZCARD.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZCARD'; +import ZCARD from './ZCARD'; describe('ZCARD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['ZCARD', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZCARD.transformArguments('key'), + ['ZCARD', 'key'] + ); + }); - testUtils.testWithClient('client.zCard', async client => { - assert.equal( - await client.zCard('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zCard', async client => { + assert.equal( + await client.zCard('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZCOUNT.spec.ts b/packages/client/lib/commands/ZCOUNT.spec.ts index e185ed3cd45..dd2a7124d1f 100644 --- a/packages/client/lib/commands/ZCOUNT.spec.ts +++ b/packages/client/lib/commands/ZCOUNT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZCOUNT'; +import ZCOUNT from './ZCOUNT'; describe('ZCOUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 1), - ['ZCOUNT', 'key', '0', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZCOUNT.transformArguments('key', 0, 1), + ['ZCOUNT', 'key', '0', '1'] + ); + }); - testUtils.testWithClient('client.zCount', async client => { - assert.equal( - await client.zCount('key', 0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zCount', async client => { + assert.equal( + await client.zCount('key', 0, 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZDIFF.spec.ts b/packages/client/lib/commands/ZDIFF.spec.ts index 8bb1a101f53..6d4ed91df31 100644 --- a/packages/client/lib/commands/ZDIFF.spec.ts +++ b/packages/client/lib/commands/ZDIFF.spec.ts @@ -1,30 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZDIFF'; +import ZDIFF from './ZDIFF'; describe('ZDIFF', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['ZDIFF', '1', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ZDIFF.transformArguments('key'), + ['ZDIFF', '1', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZDIFF', '2', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + ZDIFF.transformArguments(['1', '2']), + ['ZDIFF', '2', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.zDiff', async client => { - assert.deepEqual( - await client.zDiff('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zDiff', async client => { + assert.deepEqual( + await client.zDiff('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZDIFFSTORE.spec.ts b/packages/client/lib/commands/ZDIFFSTORE.spec.ts index c63902b2666..4901c5b1e14 100644 --- a/packages/client/lib/commands/ZDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/ZDIFFSTORE.spec.ts @@ -1,30 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZDIFFSTORE'; +import ZDIFFSTORE from './ZDIFFSTORE'; describe('ZDIFFSTORE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['ZDIFFSTORE', 'destination', '1', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ZDIFFSTORE.transformArguments('destination', 'key'), + ['ZDIFFSTORE', 'destination', '1', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['ZDIFFSTORE', 'destination', '2', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + ZDIFFSTORE.transformArguments('destination', ['1', '2']), + ['ZDIFFSTORE', 'destination', '2', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.zDiffStore', async client => { - assert.equal( - await client.zDiffStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zDiffStore', async client => { + assert.equal( + await client.zDiffStore('{tag}destination', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts index 3b9cb725aaa..0082be3cf86 100644 --- a/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts @@ -1,30 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZDIFF_WITHSCORES'; +import ZDIFF_WITHSCORES from './ZDIFF_WITHSCORES'; describe('ZDIFF WITHSCORES', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['ZDIFF', '1', 'key', 'WITHSCORES'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ZDIFF_WITHSCORES.transformArguments('key'), + ['ZDIFF', '1', 'key', 'WITHSCORES'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZDIFF', '2', '1', '2', 'WITHSCORES'] - ); - }); + it('array', () => { + assert.deepEqual( + ZDIFF_WITHSCORES.transformArguments(['1', '2']), + ['ZDIFF', '2', '1', '2', 'WITHSCORES'] + ); }); + }); - testUtils.testWithClient('client.zDiffWithScores', async client => { - assert.deepEqual( - await client.zDiffWithScores('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zDiffWithScores', async client => { + assert.deepEqual( + await client.zDiffWithScores('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZINCRBY.spec.ts b/packages/client/lib/commands/ZINCRBY.spec.ts index bf2a34b0965..531f39cc3f8 100644 --- a/packages/client/lib/commands/ZINCRBY.spec.ts +++ b/packages/client/lib/commands/ZINCRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZINCRBY'; +import ZINCRBY from './ZINCRBY'; describe('ZINCRBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1, 'member'), - ['ZINCRBY', 'key', '1', 'member'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZINCRBY.transformArguments('key', 1, 'member'), + ['ZINCRBY', 'key', '1', 'member'] + ); + }); - testUtils.testWithClient('client.zIncrBy', async client => { - assert.equal( - await client.zIncrBy('destination', 1, 'member'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zIncrBy', async client => { + assert.equal( + await client.zIncrBy('destination', 1, 'member'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZINTER.spec.ts b/packages/client/lib/commands/ZINTER.spec.ts index 4d2d86c8869..d90a0074f25 100644 --- a/packages/client/lib/commands/ZINTER.spec.ts +++ b/packages/client/lib/commands/ZINTER.spec.ts @@ -1,58 +1,65 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZINTER'; +import ZINTER from './ZINTER'; describe('ZINTER', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('key'), - ['ZINTER', '1', 'key'] - ); - }); + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZINTER.transformArguments('key'), + ['ZINTER', '1', 'key'] + ); + }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZINTER', '2', '1', '2'] - ); - }); + it('keys (Array)', () => { + assert.deepEqual( + ZINTER.transformArguments(['1', '2']), + ['ZINTER', '2', '1', '2'] + ); + }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1] - }), - ['ZINTER', '1', 'key', 'WEIGHTS', '1'] - ); - }); + it('key & weight', () => { + assert.deepEqual( + ZINTER.transformArguments({ + key: 'key', + weight: 1 + }), + ['ZINTER', '1', 'key', 'WEIGHTS', '1'] + ); + }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - AGGREGATE: 'SUM' - }), - ['ZINTER', '1', 'key', 'AGGREGATE', 'SUM'] - ); - }); + it('keys & weights', () => { + assert.deepEqual( + ZINTER.transformArguments([{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZINTER', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ); + }); - it('with WEIGHTS, AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1], - AGGREGATE: 'SUM' - }), - ['ZINTER', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] - ); - }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZINTER.transformArguments('key', { + AGGREGATE: 'SUM' + }), + ['ZINTER', '1', 'key', 'AGGREGATE', 'SUM'] + ); }); + }); - testUtils.testWithClient('client.zInter', async client => { - assert.deepEqual( - await client.zInter('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zInter', async client => { + assert.deepEqual( + await client.zInter('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZINTERCARD.spec.ts b/packages/client/lib/commands/ZINTERCARD.spec.ts index 492c1a90433..10b88cbed76 100644 --- a/packages/client/lib/commands/ZINTERCARD.spec.ts +++ b/packages/client/lib/commands/ZINTERCARD.spec.ts @@ -1,30 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZINTERCARD'; +import ZINTERCARD from './ZINTERCARD'; describe('ZINTERCARD', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZINTERCARD', '2', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZINTERCARD.transformArguments(['1', '2']), + ['ZINTERCARD', '2', '1', '2'] + ); + }); - it('with limit', () => { - assert.deepEqual( - transformArguments(['1', '2'], 1), - ['ZINTERCARD', '2', '1', '2', 'LIMIT', '1'] - ); - }); + it('with limit', () => { + assert.deepEqual( + ZINTERCARD.transformArguments(['1', '2'], 1), + ['ZINTERCARD', '2', '1', '2', 'LIMIT', '1'] + ); }); + }); - testUtils.testWithClient('client.zInterCard', async client => { - assert.deepEqual( - await client.zInterCard('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zInterCard', async client => { + assert.deepEqual( + await client.zInterCard('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZINTERSTORE.spec.ts b/packages/client/lib/commands/ZINTERSTORE.spec.ts index 224961f0786..6c7a534e3db 100644 --- a/packages/client/lib/commands/ZINTERSTORE.spec.ts +++ b/packages/client/lib/commands/ZINTERSTORE.spec.ts @@ -1,56 +1,63 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZINTERSTORE'; +import ZINTERSTORE from './ZINTERSTORE'; describe('ZINTERSTORE', () => { - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['ZINTERSTORE', 'destination', '1', 'key'] - ); - }); + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZINTERSTORE.transformArguments('destination', 'key'), + ['ZINTERSTORE', 'destination', '1', 'key'] + ); + }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['ZINTERSTORE', 'destination', '2', '1', '2'] - ); - }); + it('keys (Array)', () => { + assert.deepEqual( + ZINTERSTORE.transformArguments('destination', ['1', '2']), + ['ZINTERSTORE', 'destination', '2', '1', '2'] + ); + }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - WEIGHTS: [1] - }), - ['ZINTERSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] - ); - }); + it('key & weight', () => { + assert.deepEqual( + ZINTERSTORE.transformArguments('destination', { + key: 'key', + weight: 1 + }), + ['ZINTERSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] + ); + }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - AGGREGATE: 'SUM' - }), - ['ZINTERSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] - ); - }); + it('keys & weights', () => { + assert.deepEqual( + ZINTERSTORE.transformArguments('destination', [{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZINTERSTORE', 'destination', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ); + }); - it('with WEIGHTS, AGGREGATE', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - WEIGHTS: [1], - AGGREGATE: 'SUM' - }), - ['ZINTERSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] - ); - }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZINTERSTORE.transformArguments('destination', 'key', { + AGGREGATE: 'SUM' + }), + ['ZINTERSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] + ); }); + }); - testUtils.testWithClient('client.zInterStore', async client => { - assert.equal( - await client.zInterStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zInterStore', async client => { + assert.equal( + await client.zInterStore('{tag}destination', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts index 0eaeb26a244..e2689733b13 100644 --- a/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts @@ -1,58 +1,65 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZINTER_WITHSCORES'; +import ZINTER_WITHSCORES from './ZINTER_WITHSCORES'; describe('ZINTER WITHSCORES', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('key'), - ['ZINTER', '1', 'key', 'WITHSCORES'] - ); - }); + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZINTER_WITHSCORES.transformArguments('key'), + ['ZINTER', '1', 'key', 'WITHSCORES'] + ); + }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZINTER', '2', '1', '2', 'WITHSCORES'] - ); - }); + it('keys (Array)', () => { + assert.deepEqual( + ZINTER_WITHSCORES.transformArguments(['1', '2']), + ['ZINTER', '2', '1', '2', 'WITHSCORES'] + ); + }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1] - }), - ['ZINTER', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] - ); - }); + it('key & weight', () => { + assert.deepEqual( + ZINTER_WITHSCORES.transformArguments({ + key: 'key', + weight: 1 + }), + ['ZINTER', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] + ); + }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - AGGREGATE: 'SUM' - }), - ['ZINTER', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] - ); - }); + it('keys & weights', () => { + assert.deepEqual( + ZINTER_WITHSCORES.transformArguments([{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZINTER', '2', 'a', 'b', 'WEIGHTS', '1', '2', 'WITHSCORES'] + ); + }); - it('with WEIGHTS, AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1], - AGGREGATE: 'SUM' - }), - ['ZINTER', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM', 'WITHSCORES'] - ); - }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZINTER_WITHSCORES.transformArguments('key', { + AGGREGATE: 'SUM' + }), + ['ZINTER', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] + ); }); + }); - testUtils.testWithClient('client.zInterWithScores', async client => { - assert.deepEqual( - await client.zInterWithScores('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zInterWithScores', async client => { + assert.deepEqual( + await client.zInterWithScores('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZLEXCOUNT.spec.ts b/packages/client/lib/commands/ZLEXCOUNT.spec.ts index 85809f1a9a9..b787f70cf86 100644 --- a/packages/client/lib/commands/ZLEXCOUNT.spec.ts +++ b/packages/client/lib/commands/ZLEXCOUNT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZLEXCOUNT'; +import ZLEXCOUNT from './ZLEXCOUNT'; describe('ZLEXCOUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '[a', '[b'), - ['ZLEXCOUNT', 'key', '[a', '[b'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZLEXCOUNT.transformArguments('key', '[a', '[b'), + ['ZLEXCOUNT', 'key', '[a', '[b'] + ); + }); - testUtils.testWithClient('client.zLexCount', async client => { - assert.equal( - await client.zLexCount('key', '[a', '[b'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zLexCount', async client => { + assert.equal( + await client.zLexCount('key', '[a', '[b'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZMPOP.spec.ts b/packages/client/lib/commands/ZMPOP.spec.ts index 9a0c9676c20..d99cceb41ca 100644 --- a/packages/client/lib/commands/ZMPOP.spec.ts +++ b/packages/client/lib/commands/ZMPOP.spec.ts @@ -1,32 +1,32 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZMPOP'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZMPOP'; -describe('ZMPOP', () => { - testUtils.isVersionGreaterThanHook([7]); +// describe('ZMPOP', () => { +// testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'MIN'), - ['ZMPOP', '1', 'key', 'MIN'] - ); - }); +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', 'MIN'), +// ['ZMPOP', '1', 'key', 'MIN'] +// ); +// }); - it('with score and count', () => { - assert.deepEqual( - transformArguments('key', 'MIN', { - COUNT: 2 - }), - ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] - ); - }); - }); +// it('with score and count', () => { +// assert.deepEqual( +// transformArguments('key', 'MIN', { +// COUNT: 2 +// }), +// ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] +// ); +// }); +// }); - testUtils.testWithClient('client.zmPop', async client => { - assert.deepEqual( - await client.zmPop('key', 'MIN'), - null - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zmPop', async client => { +// assert.deepEqual( +// await client.zmPop('key', 'MIN'), +// null +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZMSCORE.spec.ts b/packages/client/lib/commands/ZMSCORE.spec.ts index 228c8e9d6f6..96cea5d5f78 100644 --- a/packages/client/lib/commands/ZMSCORE.spec.ts +++ b/packages/client/lib/commands/ZMSCORE.spec.ts @@ -1,30 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZMSCORE'; +import ZMSCORE from './ZMSCORE'; describe('ZMSCORE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['ZMSCORE', 'key', 'member'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ZMSCORE.transformArguments('key', 'member'), + ['ZMSCORE', 'key', 'member'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['ZMSCORE', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + ZMSCORE.transformArguments('key', ['1', '2']), + ['ZMSCORE', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.zmScore', async client => { - assert.deepEqual( - await client.zmScore('key', 'member'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zmScore', async client => { + assert.deepEqual( + await client.zmScore('key', 'member'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts index 55f71e0d3af..f5a8fac0d7b 100644 --- a/packages/client/lib/commands/ZMSCORE.ts +++ b/packages/client/lib/commands/ZMSCORE.ts @@ -1,5 +1,5 @@ import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; -import { pushVariadicArgument, RedisVariadicArgument } from './generic-transformers'; +import { pushVariadicArguments, RedisVariadicArgument } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -8,7 +8,7 @@ export default { key: RedisArgument, member: RedisVariadicArgument ) { - return pushVariadicArgument(['ZMSCORE', key], member); + return pushVariadicArguments(['ZMSCORE', key], member); }, transformReply: { 2: (reply: ArrayReply) => { diff --git a/packages/client/lib/commands/ZPOPMAX.spec.ts b/packages/client/lib/commands/ZPOPMAX.spec.ts index 18fba23a3e9..46b7cf1df84 100644 --- a/packages/client/lib/commands/ZPOPMAX.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX.spec.ts @@ -1,41 +1,41 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './ZPOPMAX'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './ZPOPMAX'; -describe('ZPOPMAX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['ZPOPMAX', 'key'] - ); - }); +// describe('ZPOPMAX', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['ZPOPMAX', 'key'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply(['value', '1']), - { - value: 'value', - score: 1 - } - ); - }); +// it('transformReply', () => { +// assert.deepEqual( +// transformReply(['value', '1']), +// { +// value: 'value', +// score: 1 +// } +// ); +// }); - describe('client.zPopMax', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.zPopMax('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); +// describe('client.zPopMax', () => { +// testUtils.testWithClient('null', async client => { +// assert.equal( +// await client.zPopMax('key'), +// null +// ); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('member', async client => { - const member = { score: 1, value: 'value' }, - [, zPopMaxReply] = await Promise.all([ - client.zAdd('key', member), - client.zPopMax('key') - ]); +// testUtils.testWithClient('member', async client => { +// const member = { score: 1, value: 'value' }, +// [, zPopMaxReply] = await Promise.all([ +// client.zAdd('key', member), +// client.zPopMax('key') +// ]); - assert.deepEqual(zPopMaxReply, member); - }, GLOBAL.SERVERS.OPEN); - }); -}); +// assert.deepEqual(zPopMaxReply, member); +// }, GLOBAL.SERVERS.OPEN); +// }); +// }); diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts index b282d0d3199..1214c8b2c29 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZPOPMAX_COUNT'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZPOPMAX_COUNT'; -describe('ZPOPMAX COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['ZPOPMAX', 'key', '1'] - ); - }); +// describe('ZPOPMAX COUNT', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 1), +// ['ZPOPMAX', 'key', '1'] +// ); +// }); - testUtils.testWithClient('client.zPopMaxCount', async client => { - assert.deepEqual( - await client.zPopMaxCount('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zPopMaxCount', async client => { +// assert.deepEqual( +// await client.zPopMaxCount('key', 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZPOPMIN.spec.ts b/packages/client/lib/commands/ZPOPMIN.spec.ts index 624b7054404..575149632cc 100644 --- a/packages/client/lib/commands/ZPOPMIN.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN.spec.ts @@ -1,41 +1,41 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './ZPOPMIN'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './ZPOPMIN'; -describe('ZPOPMIN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['ZPOPMIN', 'key'] - ); - }); +// describe('ZPOPMIN', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['ZPOPMIN', 'key'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply(['value', '1']), - { - value: 'value', - score: 1 - } - ); - }); +// it('transformReply', () => { +// assert.deepEqual( +// transformReply(['value', '1']), +// { +// value: 'value', +// score: 1 +// } +// ); +// }); - describe('client.zPopMin', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.zPopMin('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); +// describe('client.zPopMin', () => { +// testUtils.testWithClient('null', async client => { +// assert.equal( +// await client.zPopMin('key'), +// null +// ); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('member', async client => { - const member = { score: 1, value: 'value' }, - [, zPopMinReply] = await Promise.all([ - client.zAdd('key', member), - client.zPopMin('key') - ]); +// testUtils.testWithClient('member', async client => { +// const member = { score: 1, value: 'value' }, +// [, zPopMinReply] = await Promise.all([ +// client.zAdd('key', member), +// client.zPopMin('key') +// ]); - assert.deepEqual(zPopMinReply, member); - }, GLOBAL.SERVERS.OPEN); - }); -}); +// assert.deepEqual(zPopMinReply, member); +// }, GLOBAL.SERVERS.OPEN); +// }); +// }); diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts index 6d40002ab72..3d199c15384 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZPOPMIN_COUNT'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZPOPMIN_COUNT'; -describe('ZPOPMIN COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['ZPOPMIN', 'key', '1'] - ); - }); +// describe('ZPOPMIN COUNT', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 1), +// ['ZPOPMIN', 'key', '1'] +// ); +// }); - testUtils.testWithClient('client.zPopMinCount', async client => { - assert.deepEqual( - await client.zPopMinCount('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zPopMinCount', async client => { +// assert.deepEqual( +// await client.zPopMinCount('key', 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANDMEMBER.spec.ts b/packages/client/lib/commands/ZRANDMEMBER.spec.ts index c57d26f830e..5249399c427 100644 --- a/packages/client/lib/commands/ZRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANDMEMBER'; +import ZRANDMEMBER from './ZRANDMEMBER'; describe('ZRANDMEMBER', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['ZRANDMEMBER', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZRANDMEMBER.transformArguments('key'), + ['ZRANDMEMBER', 'key'] + ); + }); - testUtils.testWithClient('client.zRandMember', async client => { - assert.equal( - await client.zRandMember('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRandMember', async client => { + assert.equal( + await client.zRandMember('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts index 10db0727b23..f108eb91ba8 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANDMEMBER_COUNT'; +import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; describe('ZRANDMEMBER COUNT', () => { - testUtils.isVersionGreaterThanHook([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['ZRANDMEMBER', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZRANDMEMBER_COUNT.transformArguments('key', 1), + ['ZRANDMEMBER', 'key', '1'] + ); + }); - testUtils.testWithClient('client.zRandMemberCount', async client => { - assert.deepEqual( - await client.zRandMemberCount('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRandMemberCount', async client => { + assert.deepEqual( + await client.zRandMemberCount('key', 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts index 5b5ec1f500f..7ea438e1df3 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANDMEMBER_COUNT_WITHSCORES'; +import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; describe('ZRANDMEMBER COUNT WITHSCORES', () => { - testUtils.isVersionGreaterThanHook([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['ZRANDMEMBER', 'key', '1', 'WITHSCORES'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZRANDMEMBER_COUNT_WITHSCORES.transformArguments('key', 1), + ['ZRANDMEMBER', 'key', '1', 'WITHSCORES'] + ); + }); - testUtils.testWithClient('client.zRandMemberCountWithScores', async client => { - assert.deepEqual( - await client.zRandMemberCountWithScores('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRandMemberCountWithScores', async client => { + assert.deepEqual( + await client.zRandMemberCountWithScores('key', 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZRANGE.spec.ts b/packages/client/lib/commands/ZRANGE.spec.ts index a280aff0033..f147cfaa1b1 100644 --- a/packages/client/lib/commands/ZRANGE.spec.ts +++ b/packages/client/lib/commands/ZRANGE.spec.ts @@ -1,74 +1,77 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANGE'; +import ZRANGE from './ZRANGE'; describe('ZRANGE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('src', 0, 1), - ['ZRANGE', 'src', '0', '1'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1), + ['ZRANGE', 'src', '0', '1'] + ); + }); - it('with BYSCORE', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - BY: 'SCORE' - }), - ['ZRANGE', 'src', '0', '1', 'BYSCORE'] - ); - }); + it('with BYSCORE', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1, { + BY: 'SCORE' + }), + ['ZRANGE', 'src', '0', '1', 'BYSCORE'] + ); + }); - it('with BYLEX', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - BY: 'LEX' - }), - ['ZRANGE', 'src', '0', '1', 'BYLEX'] - ); - }); + it('with BYLEX', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1, { + BY: 'LEX' + }), + ['ZRANGE', 'src', '0', '1', 'BYLEX'] + ); + }); - it('with REV', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - REV: true - }), - ['ZRANGE', 'src', '0', '1', 'REV'] - ); - }); + it('with REV', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1, { + REV: true + }), + ['ZRANGE', 'src', '0', '1', 'REV'] + ); + }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1'] - ); - }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1'] + ); + }); - it('with BY & REV & LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - BY: 'SCORE', - REV: true, - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1'] - ); - }); + it('with BY & REV & LIMIT', () => { + assert.deepEqual( + ZRANGE.transformArguments('src', 0, 1, { + BY: 'SCORE', + REV: true, + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1'] + ); }); + }); - testUtils.testWithClient('client.zRange', async client => { - assert.deepEqual( - await client.zRange('src', 0, 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRange', async client => { + assert.deepEqual( + await client.zRange('src', 0, 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZRANGE.ts b/packages/client/lib/commands/ZRANGE.ts index 9683c09ab5e..557044b67da 100644 --- a/packages/client/lib/commands/ZRANGE.ts +++ b/packages/client/lib/commands/ZRANGE.ts @@ -1,7 +1,7 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; import { transformStringDoubleArgument } from './generic-transformers'; -interface ZRangeOptions { +export interface ZRangeOptions { BY?: 'SCORE' | 'LEX'; REV?: boolean; LIMIT?: { diff --git a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts index fe7b7d5a16e..40b779eac2c 100644 --- a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts @@ -1,33 +1,33 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANGEBYLEX'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZRANGEBYLEX'; -describe('ZRANGEBYLEX', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('src', '-', '+'), - ['ZRANGEBYLEX', 'src', '-', '+'] - ); - }); +// describe('ZRANGEBYLEX', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('src', '-', '+'), +// ['ZRANGEBYLEX', 'src', '-', '+'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('src', '-', '+', { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGEBYLEX', 'src', '-', '+', 'LIMIT', '0', '1'] - ); - }); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('src', '-', '+', { +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGEBYLEX', 'src', '-', '+', 'LIMIT', '0', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.zRangeByLex', async client => { - assert.deepEqual( - await client.zRangeByLex('src', '-', '+'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRangeByLex', async client => { +// assert.deepEqual( +// await client.zRangeByLex('src', '-', '+'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts index a3484326306..1d064c37c12 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts @@ -1,33 +1,33 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANGEBYSCORE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZRANGEBYSCORE'; -describe('ZRANGEBYSCORE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('src', 0, 1), - ['ZRANGEBYSCORE', 'src', '0', '1'] - ); - }); +// describe('ZRANGEBYSCORE', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1), +// ['ZRANGEBYSCORE', 'src', '0', '1'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1'] - ); - }); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.zRangeByScore', async client => { - assert.deepEqual( - await client.zRangeByScore('src', 0, 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRangeByScore', async client => { +// assert.deepEqual( +// await client.zRangeByScore('src', 0, 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts index 3552d3e2535..2a90a6af3f7 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts @@ -1,33 +1,33 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANGEBYSCORE_WITHSCORES'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZRANGEBYSCORE_WITHSCORES'; -describe('ZRANGEBYSCORE WITHSCORES', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('src', 0, 1), - ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] - ); - }); +// describe('ZRANGEBYSCORE WITHSCORES', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1), +// ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] - ); - }); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] +// ); +// }); +// }); - testUtils.testWithClient('client.zRangeByScoreWithScores', async client => { - assert.deepEqual( - await client.zRangeByScoreWithScores('src', 0, 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRangeByScoreWithScores', async client => { +// assert.deepEqual( +// await client.zRangeByScoreWithScores('src', 0, 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANGESTORE.spec.ts b/packages/client/lib/commands/ZRANGESTORE.spec.ts index 7af253e539f..c617f38e9ae 100644 --- a/packages/client/lib/commands/ZRANGESTORE.spec.ts +++ b/packages/client/lib/commands/ZRANGESTORE.spec.ts @@ -1,92 +1,92 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './ZRANGESTORE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './ZRANGESTORE'; -describe('ZRANGESTORE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('ZRANGESTORE', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1), - ['ZRANGESTORE', 'dst', 'src', '0', '1'] - ); - }); +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1), +// ['ZRANGESTORE', 'dst', 'src', '0', '1'] +// ); +// }); - it('with BYSCORE', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1, { - BY: 'SCORE' - }), - ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE'] - ); - }); +// it('with BYSCORE', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1, { +// BY: 'SCORE' +// }), +// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE'] +// ); +// }); - it('with BYLEX', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1, { - BY: 'LEX' - }), - ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYLEX'] - ); - }); +// it('with BYLEX', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1, { +// BY: 'LEX' +// }), +// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYLEX'] +// ); +// }); - it('with REV', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1, { - REV: true - }), - ['ZRANGESTORE', 'dst', 'src', '0', '1', 'REV'] - ); - }); +// it('with REV', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1, { +// REV: true +// }), +// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'REV'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1, { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGESTORE', 'dst', 'src', '0', '1', 'LIMIT', '0', '1'] - ); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1, { +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'LIMIT', '0', '1'] +// ); +// }); - it('with BY & REV & LIMIT', () => { - assert.deepEqual( - transformArguments('dst', 'src', 0, 1, { - BY: 'SCORE', - REV: true, - LIMIT: { - offset: 0, - count: 1 - }, - WITHSCORES: true - }), - ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] - ); - }); - }); +// it('with BY & REV & LIMIT', () => { +// assert.deepEqual( +// transformArguments('dst', 'src', 0, 1, { +// BY: 'SCORE', +// REV: true, +// LIMIT: { +// offset: 0, +// count: 1 +// }, +// WITHSCORES: true +// }), +// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] +// ); +// }); +// }); - describe('transformReply', () => { - it('should throw TypeError when reply is not a number', () => { - assert.throws( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - () => (transformReply as any)([]), - TypeError - ); - }); - }); +// describe('transformReply', () => { +// it('should throw TypeError when reply is not a number', () => { +// assert.throws( +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// () => (transformReply as any)([]), +// TypeError +// ); +// }); +// }); - testUtils.testWithClient('client.zRangeStore', async client => { - await client.zAdd('src', { - score: 0.5, - value: 'value' - }); +// testUtils.testWithClient('client.zRangeStore', async client => { +// await client.zAdd('src', { +// score: 0.5, +// value: 'value' +// }); - assert.equal( - await client.zRangeStore('dst', 'src', 0, 1), - 1 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.equal( +// await client.zRangeStore('dst', 'src', 0, 1), +// 1 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts index d9b07e19dda..0f106910f5f 100644 --- a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts @@ -1,65 +1,65 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANGE_WITHSCORES'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZRANGE_WITHSCORES'; -describe('ZRANGE WITHSCORES', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('src', 0, 1), - ['ZRANGE', 'src', '0', '1', 'WITHSCORES'] - ); - }); +// describe('ZRANGE WITHSCORES', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1), +// ['ZRANGE', 'src', '0', '1', 'WITHSCORES'] +// ); +// }); - it('with BY', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - BY: 'SCORE' - }), - ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'WITHSCORES'] - ); - }); +// it('with BY', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// BY: 'SCORE' +// }), +// ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'WITHSCORES'] +// ); +// }); - it('with REV', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - REV: true - }), - ['ZRANGE', 'src', '0', '1', 'REV', 'WITHSCORES'] - ); - }); +// it('with REV', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// REV: true +// }), +// ['ZRANGE', 'src', '0', '1', 'REV', 'WITHSCORES'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] - ); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] +// ); +// }); - it('with BY & REV & LIMIT', () => { - assert.deepEqual( - transformArguments('src', 0, 1, { - BY: 'SCORE', - REV: true, - LIMIT: { - offset: 0, - count: 1 - } - }), - ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] - ); - }); - }); +// it('with BY & REV & LIMIT', () => { +// assert.deepEqual( +// transformArguments('src', 0, 1, { +// BY: 'SCORE', +// REV: true, +// LIMIT: { +// offset: 0, +// count: 1 +// } +// }), +// ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] +// ); +// }); +// }); - testUtils.testWithClient('client.zRangeWithScores', async client => { - assert.deepEqual( - await client.zRangeWithScores('src', 0, 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRangeWithScores', async client => { +// assert.deepEqual( +// await client.zRangeWithScores('src', 0, 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZRANK.spec.ts b/packages/client/lib/commands/ZRANK.spec.ts index 0c81517a7d6..cd3d1725b0e 100644 --- a/packages/client/lib/commands/ZRANK.spec.ts +++ b/packages/client/lib/commands/ZRANK.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZRANK'; +import ZRANK from './ZRANK'; describe('ZRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['ZRANK', 'key', 'member'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZRANK.transformArguments('key', 'member'), + ['ZRANK', 'key', 'member'] + ); + }); - testUtils.testWithClient('client.zRank', async client => { - assert.equal( - await client.zRank('key', 'member'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRank', async client => { + assert.equal( + await client.zRank('key', 'member'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZREM.spec.ts b/packages/client/lib/commands/ZREM.spec.ts index 3ac001708a0..ac52b171a8f 100644 --- a/packages/client/lib/commands/ZREM.spec.ts +++ b/packages/client/lib/commands/ZREM.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZREM'; +import ZREM from './ZREM'; describe('ZREM', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['ZREM', 'key', 'member'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ZREM.transformArguments('key', 'member'), + ['ZREM', 'key', 'member'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['ZREM', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + ZREM.transformArguments('key', ['1', '2']), + ['ZREM', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.zRem', async client => { - assert.equal( - await client.zRem('key', 'member'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRem', async client => { + assert.equal( + await client.zRem('key', 'member'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts index b59c9e9f3b0..5b9f74fbe42 100644 --- a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZREMRANGEBYLEX'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZREMRANGEBYLEX'; -describe('ZREMRANGEBYLEX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '[a', '[b'), - ['ZREMRANGEBYLEX', 'key', '[a', '[b'] - ); - }); +// describe('ZREMRANGEBYLEX', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', '[a', '[b'), +// ['ZREMRANGEBYLEX', 'key', '[a', '[b'] +// ); +// }); - testUtils.testWithClient('client.zRemRangeByLex', async client => { - assert.equal( - await client.zRemRangeByLex('key', '[a', '[b'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRemRangeByLex', async client => { +// assert.equal( +// await client.zRemRangeByLex('key', '[a', '[b'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts index c659dadb790..4dd660af742 100644 --- a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZREMRANGEBYRANK'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZREMRANGEBYRANK'; -describe('ZREMRANGEBYRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 1), - ['ZREMRANGEBYRANK', 'key', '0', '1'] - ); - }); +// describe('ZREMRANGEBYRANK', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 0, 1), +// ['ZREMRANGEBYRANK', 'key', '0', '1'] +// ); +// }); - testUtils.testWithClient('client.zRemRangeByRank', async client => { - assert.equal( - await client.zRemRangeByRank('key', 0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRemRangeByRank', async client => { +// assert.equal( +// await client.zRemRangeByRank('key', 0, 1), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts index 988fd7690c9..8d4bbf5286a 100644 --- a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZREMRANGEBYSCORE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZREMRANGEBYSCORE'; -describe('ZREMRANGEBYSCORE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 1), - ['ZREMRANGEBYSCORE', 'key', '0', '1'] - ); - }); +// describe('ZREMRANGEBYSCORE', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 0, 1), +// ['ZREMRANGEBYSCORE', 'key', '0', '1'] +// ); +// }); - testUtils.testWithClient('client.zRemRangeByScore', async client => { - assert.equal( - await client.zRemRangeByScore('key', 0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zRemRangeByScore', async client => { +// assert.equal( +// await client.zRemRangeByScore('key', 0, 1), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZREVRANK.spec.ts b/packages/client/lib/commands/ZREVRANK.spec.ts index d9fef0d70a4..f7e104bca3b 100644 --- a/packages/client/lib/commands/ZREVRANK.spec.ts +++ b/packages/client/lib/commands/ZREVRANK.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZREVRANK'; +import ZREVRANK from './ZREVRANK'; describe('ZREVRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['ZREVRANK', 'key', 'member'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZREVRANK.transformArguments('key', 'member'), + ['ZREVRANK', 'key', 'member'] + ); + }); - testUtils.testWithClient('client.zRevRank', async client => { - assert.equal( - await client.zRevRank('key', 'member'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zRevRank', async client => { + assert.equal( + await client.zRevRank('key', 'member'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZSCAN.spec.ts b/packages/client/lib/commands/ZSCAN.spec.ts index afa221a1ef3..f420fc0806a 100644 --- a/packages/client/lib/commands/ZSCAN.spec.ts +++ b/packages/client/lib/commands/ZSCAN.spec.ts @@ -1,77 +1,52 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './ZSCAN'; +import ZSCAN from './ZSCAN'; describe('ZSCAN', () => { - describe('transformArguments', () => { - it('cusror only', () => { - assert.deepEqual( - transformArguments('key', 0), - ['ZSCAN', 'key', '0'] - ); - }); - - it('with MATCH', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern' - }), - ['ZSCAN', 'key', '0', 'MATCH', 'pattern'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - COUNT: 1 - }), - ['ZSCAN', 'key', '0', 'COUNT', '1'] - ); - }); + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + ZSCAN.transformArguments('key', 0), + ['ZSCAN', 'key', '0'] + ); + }); - it('with MATCH & COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern', - COUNT: 1 - }), - ['ZSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] - ); - }); + it('with MATCH', () => { + assert.deepEqual( + ZSCAN.transformArguments('key', 0, { + MATCH: 'pattern' + }), + ['ZSCAN', 'key', '0', 'MATCH', 'pattern'] + ); }); - describe('transformReply', () => { - it('without members', () => { - assert.deepEqual( - transformReply(['0', []]), - { - cursor: 0, - members: [] - } - ); - }); + it('with COUNT', () => { + assert.deepEqual( + ZSCAN.transformArguments('key', 0, { + COUNT: 1 + }), + ['ZSCAN', 'key', '0', 'COUNT', '1'] + ); + }); - it('with members', () => { - assert.deepEqual( - transformReply(['0', ['member', '-inf']]), - { - cursor: 0, - members: [{ - value: 'member', - score: -Infinity - }] - } - ); - }); + it('with MATCH & COUNT', () => { + assert.deepEqual( + ZSCAN.transformArguments('key', 0, { + MATCH: 'pattern', + COUNT: 1 + }), + ['ZSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] + ); }); + }); - testUtils.testWithClient('client.zScan', async client => { - assert.deepEqual( - await client.zScan('key', 0), - { - cursor: 0, - members: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('zScan', async client => { + assert.deepEqual( + await client.zScan('key', 0), + { + cursor: 0, + members: [] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ZSCORE.spec.ts b/packages/client/lib/commands/ZSCORE.spec.ts index fe2a1c6a7c5..55c6d51cd05 100644 --- a/packages/client/lib/commands/ZSCORE.spec.ts +++ b/packages/client/lib/commands/ZSCORE.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZSCORE'; +import ZSCORE from './ZSCORE'; describe('ZSCORE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['ZSCORE', 'key', 'member'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ZSCORE.transformArguments('key', 'member'), + ['ZSCORE', 'key', 'member'] + ); + }); - testUtils.testWithClient('client.zScore', async client => { - assert.equal( - await client.zScore('key', 'member'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zScore', async client => { + assert.equal( + await client.zScore('key', 'member'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts index c53498cbf65..b9882906047 100644 --- a/packages/client/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -1,48 +1,48 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZUNION'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZUNION'; -describe('ZUNION', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('ZUNION', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('key'), - ['ZUNION', '1', 'key'] - ); - }); +// describe('transformArguments', () => { +// it('key (string)', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['ZUNION', '1', 'key'] +// ); +// }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZUNION', '2', '1', '2'] - ); - }); +// it('keys (array)', () => { +// assert.deepEqual( +// transformArguments(['1', '2']), +// ['ZUNION', '2', '1', '2'] +// ); +// }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1] - }), - ['ZUNION', '1', 'key', 'WEIGHTS', '1'] - ); - }); +// it('with WEIGHTS', () => { +// assert.deepEqual( +// transformArguments('key', { +// WEIGHTS: [1] +// }), +// ['ZUNION', '1', 'key', 'WEIGHTS', '1'] +// ); +// }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - AGGREGATE: 'SUM' - }), - ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM'] - ); - }); - }); +// it('with AGGREGATE', () => { +// assert.deepEqual( +// transformArguments('key', { +// AGGREGATE: 'SUM' +// }), +// ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM'] +// ); +// }); +// }); - testUtils.testWithClient('client.zUnion', async client => { - assert.deepEqual( - await client.zUnion('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zUnion', async client => { +// assert.deepEqual( +// await client.zUnion('key'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index 8f11828b221..4458dcb648c 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -1,56 +1,56 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZUNIONSTORE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZUNIONSTORE'; -describe('ZUNIONSTORE', () => { - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['ZUNIONSTORE', 'destination', '1', 'key'] - ); - }); +// describe('ZUNIONSTORE', () => { +// describe('transformArguments', () => { +// it('key (string)', () => { +// assert.deepEqual( +// transformArguments('destination', 'key'), +// ['ZUNIONSTORE', 'destination', '1', 'key'] +// ); +// }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['ZUNIONSTORE', 'destination', '2', '1', '2'] - ); - }); +// it('keys (array)', () => { +// assert.deepEqual( +// transformArguments('destination', ['1', '2']), +// ['ZUNIONSTORE', 'destination', '2', '1', '2'] +// ); +// }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - WEIGHTS: [1] - }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] - ); - }); +// it('with WEIGHTS', () => { +// assert.deepEqual( +// transformArguments('destination', 'key', { +// WEIGHTS: [1] +// }), +// ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] +// ); +// }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - AGGREGATE: 'SUM' - }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] - ); - }); +// it('with AGGREGATE', () => { +// assert.deepEqual( +// transformArguments('destination', 'key', { +// AGGREGATE: 'SUM' +// }), +// ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] +// ); +// }); - it('with WEIGHTS, AGGREGATE', () => { - assert.deepEqual( - transformArguments('destination', 'key', { - WEIGHTS: [1], - AGGREGATE: 'SUM' - }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] - ); - }); - }); +// it('with WEIGHTS, AGGREGATE', () => { +// assert.deepEqual( +// transformArguments('destination', 'key', { +// WEIGHTS: [1], +// AGGREGATE: 'SUM' +// }), +// ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] +// ); +// }); +// }); - testUtils.testWithClient('client.zUnionStore', async client => { - assert.equal( - await client.zUnionStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zUnionStore', async client => { +// assert.equal( +// await client.zUnionStore('destination', 'key'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index 3786a97963d..6076801367c 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -1,48 +1,48 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ZUNION_WITHSCORES'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './ZUNION_WITHSCORES'; -describe('ZUNION WITHSCORES', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('ZUNION WITHSCORES', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('key (string)', () => { - assert.deepEqual( - transformArguments('key'), - ['ZUNION', '1', 'key', 'WITHSCORES'] - ); - }); +// describe('transformArguments', () => { +// it('key (string)', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['ZUNION', '1', 'key', 'WITHSCORES'] +// ); +// }); - it('keys (array)', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['ZUNION', '2', '1', '2', 'WITHSCORES'] - ); - }); +// it('keys (array)', () => { +// assert.deepEqual( +// transformArguments(['1', '2']), +// ['ZUNION', '2', '1', '2', 'WITHSCORES'] +// ); +// }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('key', { - WEIGHTS: [1] - }), - ['ZUNION', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] - ); - }); +// it('with WEIGHTS', () => { +// assert.deepEqual( +// transformArguments('key', { +// WEIGHTS: [1] +// }), +// ['ZUNION', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] +// ); +// }); - it('with AGGREGATE', () => { - assert.deepEqual( - transformArguments('key', { - AGGREGATE: 'SUM' - }), - ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] - ); - }); - }); +// it('with AGGREGATE', () => { +// assert.deepEqual( +// transformArguments('key', { +// AGGREGATE: 'SUM' +// }), +// ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] +// ); +// }); +// }); - testUtils.testWithClient('client.zUnionWithScores', async client => { - assert.deepEqual( - await client.zUnionWithScores('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.zUnionWithScores', async client => { +// assert.deepEqual( +// await client.zUnionWithScores('key'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index db7ca279a7c..83a83c76de7 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -106,7 +106,28 @@ import SETRANGE from './SETRANGE'; import SMEMBERS from './SMEMBERS'; import SSCAN from './SSCAN'; import STRLEN from './STRLEN'; +import ZADD from './ZADD'; +import ZCARD from './ZCARD'; +import ZCOUNT from './ZCOUNT'; +import ZDIFF_WITHSCORES from './ZDIFF_WITHSCORES'; +import ZDIFF from './ZDIFF'; +import ZDIFFSTORE from './ZDIFFSTORE'; +import ZINCRBY from './ZINCRBY'; +import ZINTER_WITHSCORES from './ZINTER_WITHSCORES'; +import ZINTER from './ZINTER'; +import ZINTERCARD from './ZINTERCARD'; +import ZINTERSTORE from './ZINTERSTORE'; +import ZLEXCOUNT from './ZLEXCOUNT'; +import ZMSCORE from './ZMSCORE'; +import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; +import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; +import ZRANDMEMBER from './ZRANDMEMBER'; +import ZRANGE from './ZRANGE'; +import ZRANK from './ZRANK'; +import ZREM from './ZREM'; +import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; +import ZSCORE from './ZSCORE'; import { Command } from '../RESP/types'; export default { @@ -326,7 +347,49 @@ export default { SSCAN, sScan: SSCAN, STRLEN, - strLen: STRLEN, + strLen: STRLEN, + ZADD, + zAdd: ZADD, + ZCARD, + zCard: ZCARD, + ZCOUNT, + zCount: ZCOUNT, + ZDIFF_WITHSCORES, + zDiffWithScores: ZDIFF_WITHSCORES, + ZDIFF, + zDiff: ZDIFF, + ZDIFFSTORE, + zDiffStore: ZDIFFSTORE, + ZINCRBY, + zIncrBy: ZINCRBY, + ZINTER_WITHSCORES, + zInterWithScores: ZINTER_WITHSCORES, + ZINTER, + zInter: ZINTER, + ZINTERCARD, + zInterCard: ZINTERCARD, + ZINTERSTORE, + zInterStore: ZINTERSTORE, + ZLEXCOUNT, + zLexCount: ZLEXCOUNT, + ZMSCORE, + zmScore: ZMSCORE, + ZRANDMEMBER_COUNT_WITHSCORES, + zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES, + ZRANDMEMBER_COUNT, + zRandMemberCount: ZRANDMEMBER_COUNT, + ZRANDMEMBER, + zRandMember: ZRANDMEMBER, + ZRANGE, + zRange: ZRANGE, + ZRANK, + zRank: ZRANK, + ZREM, + zRem: ZREM, + ZREVRANK, + zRevRank: ZREVRANK, ZSCAN, - zScan: ZSCAN + zScan: ZSCAN, + ZSCORE, + zScore: ZSCORE } as const satisfies Record; From 69767d40f82d0ee43b60f2424c54c26b85a7c34a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Apr 2023 17:46:46 -0400 Subject: [PATCH 024/325] tests.yml --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5b23cdfba8c..93f0fdff96b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,8 +16,8 @@ jobs: strategy: fail-fast: false matrix: - node-version: ['14', '16', '18', '19'] - redis-version: ['5', '6.0', '6.2', '7.0'] + node-version: ['16', '18', '19', '20'] + redis-version: ['5', '6.0', '6.2', '7.0', '7.2-rc'] steps: - uses: actions/checkout@v3 with: From ab3973aca3644efd2070b4b3acf7dc962d9d29fc Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Apr 2023 18:41:32 -0400 Subject: [PATCH 025/325] wip --- packages/client/lib/RESP/decoder.ts | 2 +- packages/client/lib/commands/SORT.ts | 1 - packages/client/lib/commands/SPOP.spec.ts | 50 ++-- packages/client/lib/commands/SPUBLISH.spec.ts | 33 ++- .../client/lib/commands/SRANDMEMBER.spec.ts | 29 +- .../lib/commands/SRANDMEMBER_COUNT.spec.ts | 29 +- .../client/lib/commands/SRANDMEMBER_COUNT.ts | 27 +- packages/client/lib/commands/SREM.spec.ts | 43 +-- packages/client/lib/commands/SSCAN.spec.ts | 104 +++---- packages/client/lib/commands/STRLEN.spec.ts | 36 +-- packages/client/lib/commands/SUNION.spec.ts | 50 ++-- .../client/lib/commands/SUNIONSTORE.spec.ts | 50 ++-- packages/client/lib/commands/SWAPDB.spec.ts | 34 +-- packages/client/lib/commands/SWAPDB.ts | 8 +- packages/client/lib/commands/TIME.spec.ts | 32 +- packages/client/lib/commands/TIME.ts | 26 +- packages/client/lib/commands/TOUCH.spec.ts | 43 +-- packages/client/lib/commands/TTL.spec.ts | 30 +- packages/client/lib/commands/TYPE.spec.ts | 29 +- packages/client/lib/commands/UNLINK.spec.ts | 43 +-- packages/client/lib/commands/UNWATCH.spec.ts | 26 +- packages/client/lib/commands/UNWATCH.ts | 5 +- packages/client/lib/commands/WAIT.spec.ts | 26 +- packages/client/lib/commands/WAIT.ts | 1 + packages/client/lib/commands/WATCH.spec.ts | 28 +- packages/client/lib/commands/WATCH.ts | 2 +- packages/client/lib/commands/XACK.spec.ts | 50 ++-- packages/client/lib/commands/XADD.spec.ts | 218 +++++++------- .../client/lib/commands/XAUTOCLAIM.spec.ts | 74 ++--- .../lib/commands/XAUTOCLAIM_JUSTID.spec.ts | 54 ++-- packages/client/lib/commands/XCLAIM.spec.ts | 160 +++++----- .../client/lib/commands/XCLAIM_JUSTID.spec.ts | 40 +-- packages/client/lib/commands/XDEL.spec.ts | 50 ++-- .../client/lib/commands/XGROUP_CREATE.spec.ts | 58 ++-- .../commands/XGROUP_CREATECONSUMER.spec.ts | 42 +-- .../lib/commands/XGROUP_DELCONSUMER.spec.ts | 40 +-- .../lib/commands/XGROUP_DESTROY.spec.ts | 40 +-- .../client/lib/commands/XGROUP_SETID.spec.ts | 40 +-- .../lib/commands/XINFO_CONSUMERS.spec.ts | 74 ++--- .../client/lib/commands/XINFO_GROUPS.spec.ts | 88 +++--- .../client/lib/commands/XINFO_STREAM.spec.ts | 136 ++++----- packages/client/lib/commands/XLEN.spec.ts | 29 +- packages/client/lib/commands/XPENDING.spec.ts | 114 +++---- .../lib/commands/XPENDING_RANGE.spec.ts | 94 +++--- packages/client/lib/commands/XRANGE.spec.ts | 54 ++-- packages/client/lib/commands/XREAD.spec.ts | 188 ++++++------ .../client/lib/commands/XREADGROUP.spec.ts | 278 +++++++++--------- .../client/lib/commands/XREVRANGE.spec.ts | 54 ++-- packages/client/lib/commands/XTRIM.spec.ts | 88 +++--- packages/client/lib/commands/index.ts | 36 +++ packages/test-utils/lib/index.ts | 2 +- 51 files changed, 1462 insertions(+), 1426 deletions(-) diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 950387966ee..49f04a2191b 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -242,7 +242,7 @@ export class Decoder { private _maybeDecodeNumberValue(isNegative, chunk) { const cb = this._decodeUnsingedNumber.bind(this, 0); - return this._cursor === chunk.length ? + return ++this._cursor === chunk.length ? this._decodeNumberValue.bind(isNegative, cb) : this._decodeNumberValue(isNegative, cb, chunk); } diff --git a/packages/client/lib/commands/SORT.ts b/packages/client/lib/commands/SORT.ts index e04466cdf67..8d112e17e0f 100644 --- a/packages/client/lib/commands/SORT.ts +++ b/packages/client/lib/commands/SORT.ts @@ -56,4 +56,3 @@ export default { transformArguments: transformSortArguments.bind(undefined, 'SORT'), transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; - diff --git a/packages/client/lib/commands/SPOP.spec.ts b/packages/client/lib/commands/SPOP.spec.ts index 6a384d181fc..1800d08622d 100644 --- a/packages/client/lib/commands/SPOP.spec.ts +++ b/packages/client/lib/commands/SPOP.spec.ts @@ -1,28 +1,28 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SPOP'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './SPOP'; -describe('SPOP', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key'), - ['SPOP', 'key'] - ); - }); +// describe('SPOP', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['SPOP', 'key'] +// ); +// }); - it('with count', () => { - assert.deepEqual( - transformArguments('key', 2), - ['SPOP', 'key', '2'] - ); - }); - }); +// it('with count', () => { +// assert.deepEqual( +// transformArguments('key', 2), +// ['SPOP', 'key', '2'] +// ); +// }); +// }); - testUtils.testWithClient('client.sPop', async client => { - assert.equal( - await client.sPop('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.sPop', async client => { +// assert.equal( +// await client.sPop('key'), +// null +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/SPUBLISH.spec.ts b/packages/client/lib/commands/SPUBLISH.spec.ts index 60b6ce2dad0..0b1391774b0 100644 --- a/packages/client/lib/commands/SPUBLISH.spec.ts +++ b/packages/client/lib/commands/SPUBLISH.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SPUBLISH'; +import SPUBLISH from './SPUBLISH'; describe('SPUBLISH', () => { - testUtils.isVersionGreaterThanHook([7]); - - it('transformArguments', () => { - assert.deepEqual( - transformArguments('channel', 'message'), - ['SPUBLISH', 'channel', 'message'] - ); - }); + testUtils.isVersionGreaterThanHook([7]); - testUtils.testWithClient('client.sPublish', async client => { - assert.equal( - await client.sPublish('channel', 'message'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + it('transformArguments', () => { + assert.deepEqual( + SPUBLISH.transformArguments('channel', 'message'), + ['SPUBLISH', 'channel', 'message'] + ); + }); + + testUtils.testAll('sPublish', async client => { + assert.equal( + await client.sPublish('channel', 'message'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SRANDMEMBER.spec.ts b/packages/client/lib/commands/SRANDMEMBER.spec.ts index 291271540be..a0983e4480d 100644 --- a/packages/client/lib/commands/SRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SRANDMEMBER'; +import SRANDMEMBER from './SRANDMEMBER'; describe('SRANDMEMBER', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['SRANDMEMBER', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SRANDMEMBER.transformArguments('key'), + ['SRANDMEMBER', 'key'] + ); + }); - testUtils.testWithClient('client.sRandMember', async client => { - assert.equal( - await client.sRandMember('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sRandMember', async client => { + assert.equal( + await client.sRandMember('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts index d3d787b3e63..6ed30cd14ab 100644 --- a/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SRANDMEMBER_COUNT'; +import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; describe('SRANDMEMBER COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['SRANDMEMBER', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SRANDMEMBER_COUNT.transformArguments('key', 1), + ['SRANDMEMBER', 'key', '1'] + ); + }); - testUtils.testWithClient('client.sRandMemberCount', async client => { - assert.deepEqual( - await client.sRandMemberCount('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sRandMemberCount', async client => { + assert.deepEqual( + await client.sRandMemberCount('key', 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SRANDMEMBER_COUNT.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.ts index 54c3e96f238..778f3d8f629 100644 --- a/packages/client/lib/commands/SRANDMEMBER_COUNT.ts +++ b/packages/client/lib/commands/SRANDMEMBER_COUNT.ts @@ -1,16 +1,13 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformArguments as transformSRandMemberArguments } from './SRANDMEMBER'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import SRANDMEMBER from './SRANDMEMBER'; -// export { FIRST_KEY_INDEX } from './SRANDMEMBER'; - -// export function transformArguments( -// key: RedisCommandArgument, -// count: number -// ): RedisCommandArguments { -// return [ -// ...transformSRandMemberArguments(key), -// count.toString() -// ]; -// } - -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: SRANDMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: SRANDMEMBER.IS_READ_ONLY, + transformArguments(key: RedisArgument, count: number) { + const args = SRANDMEMBER.transformArguments(key); + args.push(count.toString()); + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SREM.spec.ts b/packages/client/lib/commands/SREM.spec.ts index d53d7b0334d..8df39102bc7 100644 --- a/packages/client/lib/commands/SREM.spec.ts +++ b/packages/client/lib/commands/SREM.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SREM'; +import SREM from './SREM'; describe('SREM', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['SREM', 'key', 'member'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SREM.transformArguments('key', 'member'), + ['SREM', 'key', 'member'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['SREM', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SREM.transformArguments('key', ['1', '2']), + ['SREM', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sRem', async client => { - assert.equal( - await client.sRem('key', 'member'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.sRem', async client => { + assert.equal( + await client.sRem('key', 'member'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SSCAN.spec.ts b/packages/client/lib/commands/SSCAN.spec.ts index 71a90bf81d8..4cfb59445d1 100644 --- a/packages/client/lib/commands/SSCAN.spec.ts +++ b/packages/client/lib/commands/SSCAN.spec.ts @@ -1,74 +1,52 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './SSCAN'; +import SSCAN from './SSCAN'; describe('SSCAN', () => { - describe('transformArguments', () => { - it('cusror only', () => { - assert.deepEqual( - transformArguments('key', 0), - ['SSCAN', 'key', '0'] - ); - }); - - it('with MATCH', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern' - }), - ['SSCAN', 'key', '0', 'MATCH', 'pattern'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - COUNT: 1 - }), - ['SSCAN', 'key', '0', 'COUNT', '1'] - ); - }); + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + SSCAN.transformArguments('key', 0), + ['SSCAN', 'key', '0'] + ); + }); - it('with MATCH & COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern', - COUNT: 1 - }), - ['SSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] - ); - }); + it('with MATCH', () => { + assert.deepEqual( + SSCAN.transformArguments('key', 0, { + MATCH: 'pattern' + }), + ['SSCAN', 'key', '0', 'MATCH', 'pattern'] + ); }); - describe('transformReply', () => { - it('without members', () => { - assert.deepEqual( - transformReply(['0', []]), - { - cursor: 0, - members: [] - } - ); - }); + it('with COUNT', () => { + assert.deepEqual( + SSCAN.transformArguments('key', 0, { + COUNT: 1 + }), + ['SSCAN', 'key', '0', 'COUNT', '1'] + ); + }); - it('with members', () => { - assert.deepEqual( - transformReply(['0', ['member']]), - { - cursor: 0, - members: ['member'] - } - ); - }); + it('with MATCH & COUNT', () => { + assert.deepEqual( + SSCAN.transformArguments('key', 0, { + MATCH: 'pattern', + COUNT: 1 + }), + ['SSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] + ); }); + }); - testUtils.testWithClient('client.sScan', async client => { - assert.deepEqual( - await client.sScan('key', 0), - { - cursor: 0, - members: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.sScan', async client => { + assert.deepEqual( + await client.sScan('key', 0), + { + cursor: 0, + members: [] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/STRLEN.spec.ts b/packages/client/lib/commands/STRLEN.spec.ts index 519c68d3e5d..b80a84a010d 100644 --- a/packages/client/lib/commands/STRLEN.spec.ts +++ b/packages/client/lib/commands/STRLEN.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './STRLEN'; +import STRLEN from './STRLEN'; describe('STRLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['STRLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + STRLEN.transformArguments('key'), + ['STRLEN', 'key'] + ); + }); - testUtils.testWithClient('client.strLen', async client => { - assert.equal( - await client.strLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.strLen', async cluster => { - assert.equal( - await cluster.strLen('key'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('strLen', async client => { + assert.equal( + await client.strLen('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SUNION.spec.ts b/packages/client/lib/commands/SUNION.spec.ts index 2918607c1d6..b0ddf782f9d 100644 --- a/packages/client/lib/commands/SUNION.spec.ts +++ b/packages/client/lib/commands/SUNION.spec.ts @@ -1,28 +1,28 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUNION'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './SUNION'; -describe('SUNION', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['SUNION', 'key'] - ); - }); +// describe('SUNION', () => { +// describe('transformArguments', () => { +// it('string', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['SUNION', 'key'] +// ); +// }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['SUNION', '1', '2'] - ); - }); - }); +// it('array', () => { +// assert.deepEqual( +// transformArguments(['1', '2']), +// ['SUNION', '1', '2'] +// ); +// }); +// }); - testUtils.testWithClient('client.sUnion', async client => { - assert.deepEqual( - await client.sUnion('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.sUnion', async client => { +// assert.deepEqual( +// await client.sUnion('key'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/SUNIONSTORE.spec.ts b/packages/client/lib/commands/SUNIONSTORE.spec.ts index 142533eea2b..4cf50132aa2 100644 --- a/packages/client/lib/commands/SUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/SUNIONSTORE.spec.ts @@ -1,28 +1,28 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUNIONSTORE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './SUNIONSTORE'; -describe('SUNIONSTORE', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['SUNIONSTORE', 'destination', 'key'] - ); - }); +// describe('SUNIONSTORE', () => { +// describe('transformArguments', () => { +// it('string', () => { +// assert.deepEqual( +// transformArguments('destination', 'key'), +// ['SUNIONSTORE', 'destination', 'key'] +// ); +// }); - it('array', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['SUNIONSTORE', 'destination', '1', '2'] - ); - }); - }); +// it('array', () => { +// assert.deepEqual( +// transformArguments('destination', ['1', '2']), +// ['SUNIONSTORE', 'destination', '1', '2'] +// ); +// }); +// }); - testUtils.testWithClient('client.sUnionStore', async client => { - assert.equal( - await client.sUnionStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.sUnionStore', async client => { +// assert.equal( +// await client.sUnionStore('destination', 'key'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/SWAPDB.spec.ts b/packages/client/lib/commands/SWAPDB.spec.ts index add87512a64..dee881b5dc5 100644 --- a/packages/client/lib/commands/SWAPDB.spec.ts +++ b/packages/client/lib/commands/SWAPDB.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SWAPDB'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './SWAPDB'; -describe('SWAPDB', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(0, 1), - ['SWAPDB', '0', '1'] - ); - }); +// describe('SWAPDB', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(0, 1), +// ['SWAPDB', '0', '1'] +// ); +// }); - testUtils.testWithClient('client.swapDb', async client => { - assert.equal( - await client.swapDb(0, 1), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.swapDb', async client => { +// assert.equal( +// await client.swapDb(0, 1), +// 'OK' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/SWAPDB.ts b/packages/client/lib/commands/SWAPDB.ts index 7f13d6b008e..0ab785fb594 100644 --- a/packages/client/lib/commands/SWAPDB.ts +++ b/packages/client/lib/commands/SWAPDB.ts @@ -1,5 +1,5 @@ -export function transformArguments(index1: number, index2: number): Array { - return ['SWAPDB', index1.toString(), index2.toString()]; -} +// export function transformArguments(index1: number, index2: number): Array { +// return ['SWAPDB', index1.toString(), index2.toString()]; +// } -export declare function transformReply(): string; +// export declare function transformReply(): string; diff --git a/packages/client/lib/commands/TIME.spec.ts b/packages/client/lib/commands/TIME.spec.ts index bbaa7942db0..5bfd1e50d9c 100644 --- a/packages/client/lib/commands/TIME.spec.ts +++ b/packages/client/lib/commands/TIME.spec.ts @@ -1,18 +1,18 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './TIME'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './TIME'; -describe('TIME', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['TIME'] - ); - }); +// describe('TIME', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(), +// ['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/packages/client/lib/commands/TIME.ts b/packages/client/lib/commands/TIME.ts index 1a364d6d8be..298a4d5aee2 100644 --- a/packages/client/lib/commands/TIME.ts +++ b/packages/client/lib/commands/TIME.ts @@ -1,15 +1,15 @@ -export function transformArguments(): Array { - return ['TIME']; -} +// export function transformArguments(): Array { +// return ['TIME']; +// } -interface TimeReply extends Date { - microseconds: number; -} +// interface TimeReply extends Date { +// microseconds: number; +// } -export function transformReply(reply: [string, string]): TimeReply { - const seconds = Number(reply[0]), - microseconds = Number(reply[1]), - d: Partial = new Date(seconds * 1000 + microseconds / 1000); - d.microseconds = microseconds; - return d as TimeReply; -} +// export function transformReply(reply: [string, string]): TimeReply { +// const seconds = Number(reply[0]), +// microseconds = Number(reply[1]), +// d: Partial = new Date(seconds * 1000 + microseconds / 1000); +// d.microseconds = microseconds; +// return d as TimeReply; +// } diff --git a/packages/client/lib/commands/TOUCH.spec.ts b/packages/client/lib/commands/TOUCH.spec.ts index 578c49587d7..01c5ed9454b 100644 --- a/packages/client/lib/commands/TOUCH.spec.ts +++ b/packages/client/lib/commands/TOUCH.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './TOUCH'; +import TOUCH from './TOUCH'; describe('TOUCH', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['TOUCH', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + TOUCH.transformArguments('key'), + ['TOUCH', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['TOUCH', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + TOUCH.transformArguments(['1', '2']), + ['TOUCH', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.touch', async client => { - assert.equal( - await client.touch('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('touch', async client => { + assert.equal( + await client.touch('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/TTL.spec.ts b/packages/client/lib/commands/TTL.spec.ts index e37a6ab714b..05c75851ee8 100644 --- a/packages/client/lib/commands/TTL.spec.ts +++ b/packages/client/lib/commands/TTL.spec.ts @@ -1,19 +1,23 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './TTL'; +import TTL from './TTL'; describe('TTL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TTL', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + TTL.transformArguments('key'), + ['TTL', 'key'] + ); + }); - testUtils.testWithClient('client.ttl', async client => { - assert.equal( - await client.ttl('key'), - -2 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('ttl', async client => { + console.log(await client.get('key'), await client.ttl('key')); + assert.equal( + await client.ttl('key'), + -2 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/TYPE.spec.ts b/packages/client/lib/commands/TYPE.spec.ts index 1040bf979b3..01beef42e1c 100644 --- a/packages/client/lib/commands/TYPE.spec.ts +++ b/packages/client/lib/commands/TYPE.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './TYPE'; +import TYPE from './TYPE'; describe('TYPE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TYPE', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + TYPE.transformArguments('key'), + ['TYPE', 'key'] + ); + }); - testUtils.testWithClient('client.type', async client => { - assert.equal( - await client.type('key'), - 'none' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('type', async client => { + assert.equal( + await client.type('key'), + 'none' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/UNLINK.spec.ts b/packages/client/lib/commands/UNLINK.spec.ts index e8355407d8f..726c05223a3 100644 --- a/packages/client/lib/commands/UNLINK.spec.ts +++ b/packages/client/lib/commands/UNLINK.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './UNLINK'; +import UNLINK from './UNLINK'; describe('UNLINK', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['UNLINK', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + UNLINK.transformArguments('key'), + ['UNLINK', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['UNLINK', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + UNLINK.transformArguments(['1', '2']), + ['UNLINK', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.unlink', async client => { - assert.equal( - await client.unlink('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('unlink', async client => { + assert.equal( + await client.unlink('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/UNWATCH.spec.ts b/packages/client/lib/commands/UNWATCH.spec.ts index 109ed0fa7c0..75bac71d853 100644 --- a/packages/client/lib/commands/UNWATCH.spec.ts +++ b/packages/client/lib/commands/UNWATCH.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './UNWATCH'; +import UNWATCH from './UNWATCH'; describe('UNWATCH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['UNWATCH'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + UNWATCH.transformArguments(), + ['UNWATCH'] + ); + }); - testUtils.testWithClient('client.unwatch', async client => { - assert.equal( - await client.unwatch(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.unwatch', async client => { + assert.equal( + await client.unwatch(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts index 3e80adeb1dc..9dd83b9aee7 100644 --- a/packages/client/lib/commands/UNWATCH.ts +++ b/packages/client/lib/commands/UNWATCH.ts @@ -1,9 +1,10 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(key: RedisArgument) { - return ['WATCH', key]; + transformArguments() { + return ['UNWATCH']; }, transformReply: undefined as unknown as () => SimpleStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/WAIT.spec.ts b/packages/client/lib/commands/WAIT.spec.ts index c85ef598612..8a8fb3a36c4 100644 --- a/packages/client/lib/commands/WAIT.spec.ts +++ b/packages/client/lib/commands/WAIT.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './WAIT'; +import WAIT from './WAIT'; describe('WAIT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(0, 1), - ['WAIT', '0', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + WAIT.transformArguments(0, 1), + ['WAIT', '0', '1'] + ); + }); - testUtils.testWithClient('client.wait', async client => { - assert.equal( - await client.wait(0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.wait', async client => { + assert.equal( + await client.wait(0, 1), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/WAIT.ts b/packages/client/lib/commands/WAIT.ts index da9df89ff0a..5c4bd156a62 100644 --- a/packages/client/lib/commands/WAIT.ts +++ b/packages/client/lib/commands/WAIT.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(numberOfReplicas: number, timeout: number) { return ['WAIT', numberOfReplicas.toString(), timeout.toString()]; diff --git a/packages/client/lib/commands/WATCH.spec.ts b/packages/client/lib/commands/WATCH.spec.ts index acaa062874f..d533a0b3e13 100644 --- a/packages/client/lib/commands/WATCH.spec.ts +++ b/packages/client/lib/commands/WATCH.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './WATCH'; +import WATCH from './WATCH'; describe('WATCH', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['WATCH', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + WATCH.transformArguments('key'), + ['WATCH', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['WATCH', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + WATCH.transformArguments(['1', '2']), + ['WATCH', '1', '2'] + ); }); + }); }); diff --git a/packages/client/lib/commands/WATCH.ts b/packages/client/lib/commands/WATCH.ts index b4fd86b37ab..339642bf991 100644 --- a/packages/client/lib/commands/WATCH.ts +++ b/packages/client/lib/commands/WATCH.ts @@ -2,7 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { - FIRST_KEY_INDEX: 1, + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(key: RedisVariadicArgument) { return pushVariadicArguments(['WATCH'], key); diff --git a/packages/client/lib/commands/XACK.spec.ts b/packages/client/lib/commands/XACK.spec.ts index 0586a5921fd..fdfaee5fb59 100644 --- a/packages/client/lib/commands/XACK.spec.ts +++ b/packages/client/lib/commands/XACK.spec.ts @@ -1,28 +1,28 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XACK'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XACK'; -describe('XACK', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'group', '1-0'), - ['XACK', 'key', 'group', '1-0'] - ); - }); +// describe('XACK', () => { +// describe('transformArguments', () => { +// it('string', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '1-0'), +// ['XACK', 'key', 'group', '1-0'] +// ); +// }); - it('array', () => { - assert.deepEqual( - transformArguments('key', 'group', ['1-0', '2-0']), - ['XACK', 'key', 'group', '1-0', '2-0'] - ); - }); - }); +// it('array', () => { +// assert.deepEqual( +// transformArguments('key', 'group', ['1-0', '2-0']), +// ['XACK', 'key', 'group', '1-0', '2-0'] +// ); +// }); +// }); - testUtils.testWithClient('client.xAck', async client => { - assert.equal( - await client.xAck('key', 'group', '1-0'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xAck', async client => { +// assert.equal( +// await client.xAck('key', 'group', '1-0'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XADD.spec.ts b/packages/client/lib/commands/XADD.spec.ts index 4b556ecc27c..c2b9c4f7bbe 100644 --- a/packages/client/lib/commands/XADD.spec.ts +++ b/packages/client/lib/commands/XADD.spec.ts @@ -1,118 +1,118 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XADD'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XADD'; -describe('XADD', () => { - describe('transformArguments', () => { - it('single field', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }), - ['XADD', 'key', '*', 'field', 'value'] - ); - }); +// describe('XADD', () => { +// describe('transformArguments', () => { +// it('single field', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }), +// ['XADD', 'key', '*', 'field', 'value'] +// ); +// }); - it('multiple fields', () => { - assert.deepEqual( - transformArguments('key', '*', { - '1': 'I', - '2': 'II' - }), - ['XADD', 'key', '*', '1', 'I', '2', 'II'] - ); - }); +// it('multiple fields', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// '1': 'I', +// '2': 'II' +// }), +// ['XADD', 'key', '*', '1', 'I', '2', 'II'] +// ); +// }); - it('with NOMKSTREAM', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - NOMKSTREAM: true - }), - ['XADD', 'key', 'NOMKSTREAM', '*', 'field', 'value'] - ); - }); +// it('with NOMKSTREAM', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// NOMKSTREAM: true +// }), +// ['XADD', 'key', 'NOMKSTREAM', '*', 'field', 'value'] +// ); +// }); - it('with TRIM', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - TRIM: { - threshold: 1000 - } - }), - ['XADD', 'key', '1000', '*', 'field', 'value'] - ); - }); +// it('with TRIM', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// TRIM: { +// threshold: 1000 +// } +// }), +// ['XADD', 'key', '1000', '*', 'field', 'value'] +// ); +// }); - it('with TRIM.strategy', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - TRIM: { - strategy: 'MAXLEN', - threshold: 1000 - } - }), - ['XADD', 'key', 'MAXLEN', '1000', '*','field', 'value'] - ); - }); +// it('with TRIM.strategy', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// TRIM: { +// strategy: 'MAXLEN', +// threshold: 1000 +// } +// }), +// ['XADD', 'key', 'MAXLEN', '1000', '*','field', 'value'] +// ); +// }); - it('with TRIM.strategyModifier', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - TRIM: { - strategyModifier: '=', - threshold: 1000 - } - }), - ['XADD', 'key', '=', '1000', '*', 'field', 'value'] - ); - }); +// it('with TRIM.strategyModifier', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// TRIM: { +// strategyModifier: '=', +// threshold: 1000 +// } +// }), +// ['XADD', 'key', '=', '1000', '*', 'field', 'value'] +// ); +// }); - it('with TRIM.limit', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - TRIM: { - threshold: 1000, - limit: 1 - } - }), - ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value'] - ); - }); +// it('with TRIM.limit', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// TRIM: { +// threshold: 1000, +// limit: 1 +// } +// }), +// ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value'] +// ); +// }); - it('with NOMKSTREAM, TRIM, TRIM.*', () => { - assert.deepEqual( - transformArguments('key', '*', { - field: 'value' - }, { - NOMKSTREAM: true, - TRIM: { - strategy: 'MAXLEN', - strategyModifier: '=', - threshold: 1000, - limit: 1 - } - }), - ['XADD', 'key', 'NOMKSTREAM', 'MAXLEN', '=', '1000', 'LIMIT', '1', '*', 'field', 'value'] - ); - }); - }); +// it('with NOMKSTREAM, TRIM, TRIM.*', () => { +// assert.deepEqual( +// transformArguments('key', '*', { +// field: 'value' +// }, { +// NOMKSTREAM: true, +// TRIM: { +// strategy: 'MAXLEN', +// strategyModifier: '=', +// threshold: 1000, +// limit: 1 +// } +// }), +// ['XADD', 'key', 'NOMKSTREAM', 'MAXLEN', '=', '1000', 'LIMIT', '1', '*', 'field', 'value'] +// ); +// }); +// }); - testUtils.testWithClient('client.xAdd', async client => { - assert.equal( - typeof await client.xAdd('key', '*', { - field: 'value' - }), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xAdd', async client => { +// assert.equal( +// typeof await client.xAdd('key', '*', { +// field: 'value' +// }), +// 'string' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index 4447a06d773..80382db8d22 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -1,42 +1,42 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XAUTOCLAIM'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XAUTOCLAIM'; -describe('XAUTOCLAIM', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('XAUTOCLAIM', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0'), - ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0'] - ); - }); +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0'), +// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0'] +// ); +// }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - COUNT: 1 - }), - ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'COUNT', '1'] - ); - }); - }); +// it('with COUNT', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// COUNT: 1 +// }), +// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'COUNT', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.xAutoClaim', async client => { - await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), - ]); +// testUtils.testWithClient('client.xAutoClaim', async client => { +// await Promise.all([ +// client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// client.xGroupCreateConsumer('key', 'group', 'consumer'), +// ]); - assert.deepEqual( - await client.xAutoClaim('key', 'group', 'consumer', 1, '0-0'), - { - nextId: '0-0', - messages: [] - } - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xAutoClaim('key', 'group', 'consumer', 1, '0-0'), +// { +// nextId: '0-0', +// messages: [] +// } +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts index 9aa24cd04a4..ed7b80cabfc 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts @@ -1,31 +1,31 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XAUTOCLAIM_JUSTID'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XAUTOCLAIM_JUSTID'; -describe('XAUTOCLAIM JUSTID', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('XAUTOCLAIM JUSTID', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0'), - ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] - ); - }); +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0'), +// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] +// ); +// }); - testUtils.testWithClient('client.xAutoClaimJustId', async client => { - await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), - ]); +// testUtils.testWithClient('client.xAutoClaimJustId', async client => { +// await Promise.all([ +// client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// client.xGroupCreateConsumer('key', 'group', 'consumer'), +// ]); - assert.deepEqual( - await client.xAutoClaimJustId('key', 'group', 'consumer', 1, '0-0'), - { - nextId: '0-0', - messages: [] - } - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xAutoClaimJustId('key', 'group', 'consumer', 1, '0-0'), +// { +// nextId: '0-0', +// messages: [] +// } +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XCLAIM.spec.ts b/packages/client/lib/commands/XCLAIM.spec.ts index 141a62ab77a..a9f6879cfa1 100644 --- a/packages/client/lib/commands/XCLAIM.spec.ts +++ b/packages/client/lib/commands/XCLAIM.spec.ts @@ -1,90 +1,90 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XCLAIM'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XCLAIM'; -describe('XCLAIM', () => { - describe('transformArguments', () => { - it('single id (string)', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0'), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0'] - ); - }); +// describe('XCLAIM', () => { +// describe('transformArguments', () => { +// it('single id (string)', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0'), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0'] +// ); +// }); - it('multiple ids (array)', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0'] - ); - }); +// it('multiple ids (array)', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0'] +// ); +// }); - it('with IDLE', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - IDLE: 1 - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1'] - ); - }); +// it('with IDLE', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// IDLE: 1 +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1'] +// ); +// }); - it('with TIME (number)', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - TIME: 1 - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1'] - ); - }); +// it('with TIME (number)', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// TIME: 1 +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1'] +// ); +// }); - it('with TIME (date)', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - TIME: d - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()] - ); - }); +// it('with TIME (date)', () => { +// const d = new Date(); +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// TIME: d +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()] +// ); +// }); - it('with RETRYCOUNT', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - RETRYCOUNT: 1 - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1'] - ); - }); +// it('with RETRYCOUNT', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// RETRYCOUNT: 1 +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1'] +// ); +// }); - it('with FORCE', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - FORCE: true - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE'] - ); - }); +// it('with FORCE', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// FORCE: true +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE'] +// ); +// }); - it('with IDLE, TIME, RETRYCOUNT, FORCE, JUSTID', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0', { - IDLE: 1, - TIME: 1, - RETRYCOUNT: 1, - FORCE: true - }), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE'] - ); - }); - }); +// it('with IDLE, TIME, RETRYCOUNT, FORCE, JUSTID', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0', { +// IDLE: 1, +// TIME: 1, +// RETRYCOUNT: 1, +// FORCE: true +// }), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE'] +// ); +// }); +// }); - testUtils.testWithClient('client.xClaim', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xClaim', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xClaim('key', 'group', 'consumer', 1, '0-0'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xClaim('key', 'group', 'consumer', 1, '0-0'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts index 619f876d53d..88fe59084b5 100644 --- a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts @@ -1,23 +1,23 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XCLAIM_JUSTID'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XCLAIM_JUSTID'; -describe('XCLAIM JUSTID', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer', 1, '0-0'), - ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] - ); - }); +// describe('XCLAIM JUSTID', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer', 1, '0-0'), +// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] +// ); +// }); - testUtils.testWithClient('client.xClaimJustId', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xClaimJustId', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xClaimJustId('key', 'group', 'consumer', 1, '0-0'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xClaimJustId('key', 'group', 'consumer', 1, '0-0'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XDEL.spec.ts b/packages/client/lib/commands/XDEL.spec.ts index 00f9e2f9c67..4f7d48aa0ee 100644 --- a/packages/client/lib/commands/XDEL.spec.ts +++ b/packages/client/lib/commands/XDEL.spec.ts @@ -1,28 +1,28 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XDEL'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XDEL'; -describe('XDEL', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', '0-0'), - ['XDEL', 'key', '0-0'] - ); - }); +// describe('XDEL', () => { +// describe('transformArguments', () => { +// it('string', () => { +// assert.deepEqual( +// transformArguments('key', '0-0'), +// ['XDEL', 'key', '0-0'] +// ); +// }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['0-0', '1-0']), - ['XDEL', 'key', '0-0', '1-0'] - ); - }); - }); +// it('array', () => { +// assert.deepEqual( +// transformArguments('key', ['0-0', '1-0']), +// ['XDEL', 'key', '0-0', '1-0'] +// ); +// }); +// }); - testUtils.testWithClient('client.xDel', async client => { - assert.equal( - await client.xDel('key', '0-0'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xDel', async client => { +// assert.equal( +// await client.xDel('key', '0-0'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XGROUP_CREATE.spec.ts b/packages/client/lib/commands/XGROUP_CREATE.spec.ts index 57516e44cc8..831db73e682 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.spec.ts @@ -1,32 +1,32 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_CREATE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XGROUP_CREATE'; -describe('XGROUP CREATE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'group', '$'), - ['XGROUP', 'CREATE', 'key', 'group', '$'] - ); - }); +// describe('XGROUP CREATE', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '$'), +// ['XGROUP', 'CREATE', 'key', 'group', '$'] +// ); +// }); - it('with MKSTREAM', () => { - assert.deepEqual( - transformArguments('key', 'group', '$', { - MKSTREAM: true - }), - ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM'] - ); - }); - }); +// it('with MKSTREAM', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '$', { +// MKSTREAM: true +// }), +// ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM'] +// ); +// }); +// }); - testUtils.testWithClient('client.xGroupCreate', async client => { - assert.equal( - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xGroupCreate', async client => { +// assert.equal( +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// 'OK' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts index 62443345188..1338b8837a6 100644 --- a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts @@ -1,25 +1,25 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_CREATECONSUMER'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XGROUP_CREATECONSUMER'; -describe('XGROUP CREATECONSUMER', () => { - testUtils.isVersionGreaterThanHook([6, 2]); +// describe('XGROUP CREATECONSUMER', () => { +// testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer'), - ['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer'] - ); - }); +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer'), +// ['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer'] +// ); +// }); - testUtils.testWithClient('client.xGroupCreateConsumer', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xGroupCreateConsumer', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.equal( - await client.xGroupCreateConsumer('key', 'group', 'consumer'), - true - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.equal( +// await client.xGroupCreateConsumer('key', 'group', 'consumer'), +// true +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts index d071aedf64f..c1704b56192 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts @@ -1,23 +1,23 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_DELCONSUMER'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XGROUP_DELCONSUMER'; -describe('XGROUP DELCONSUMER', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group', 'consumer'), - ['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer'] - ); - }); +// describe('XGROUP DELCONSUMER', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group', 'consumer'), +// ['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer'] +// ); +// }); - testUtils.testWithClient('client.xGroupDelConsumer', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xGroupDelConsumer', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.equal( - await client.xGroupDelConsumer('key', 'group', 'consumer'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.equal( +// await client.xGroupDelConsumer('key', 'group', 'consumer'), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts index ea8e7b7be98..3e729337aee 100644 --- a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts @@ -1,23 +1,23 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_DESTROY'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XGROUP_DESTROY'; -describe('XGROUP DESTROY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group'), - ['XGROUP', 'DESTROY', 'key', 'group'] - ); - }); +// describe('XGROUP DESTROY', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group'), +// ['XGROUP', 'DESTROY', 'key', 'group'] +// ); +// }); - testUtils.testWithClient('client.xGroupDestroy', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xGroupDestroy', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.equal( - await client.xGroupDestroy('key', 'group'), - true - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.equal( +// await client.xGroupDestroy('key', 'group'), +// true +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XGROUP_SETID.spec.ts b/packages/client/lib/commands/XGROUP_SETID.spec.ts index 8df51f5401d..6f05802ab00 100644 --- a/packages/client/lib/commands/XGROUP_SETID.spec.ts +++ b/packages/client/lib/commands/XGROUP_SETID.spec.ts @@ -1,23 +1,23 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_SETID'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XGROUP_SETID'; -describe('XGROUP SETID', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group', '0'), - ['XGROUP', 'SETID', 'key', 'group', '0'] - ); - }); +// describe('XGROUP SETID', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '0'), +// ['XGROUP', 'SETID', 'key', 'group', '0'] +// ); +// }); - testUtils.testWithClient('client.xGroupSetId', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xGroupSetId', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.equal( - await client.xGroupSetId('key', 'group', '0'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.equal( +// await client.xGroupSetId('key', 'group', '0'), +// 'OK' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts index 87c82b34f29..bfbd946bba5 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts @@ -1,41 +1,41 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './XINFO_CONSUMERS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './XINFO_CONSUMERS'; -describe('XINFO CONSUMERS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group'), - ['XINFO', 'CONSUMERS', 'key', 'group'] - ); - }); +// describe('XINFO CONSUMERS', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group'), +// ['XINFO', 'CONSUMERS', 'key', 'group'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - ['name', 'Alice', 'pending', 1, 'idle', 9104628], - ['name', 'Bob', 'pending', 1, 'idle', 83841983] - ]), - [{ - name: 'Alice', - pending: 1, - idle: 9104628 - }, { - name: 'Bob', - pending: 1, - idle: 83841983 - }] - ); - }); +// it('transformReply', () => { +// assert.deepEqual( +// transformReply([ +// ['name', 'Alice', 'pending', 1, 'idle', 9104628], +// ['name', 'Bob', 'pending', 1, 'idle', 83841983] +// ]), +// [{ +// name: 'Alice', +// pending: 1, +// idle: 9104628 +// }, { +// name: 'Bob', +// pending: 1, +// idle: 83841983 +// }] +// ); +// }); - testUtils.testWithClient('client.xInfoConsumers', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xInfoConsumers', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xInfoConsumers('key', 'group'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xInfoConsumers('key', 'group'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts index dea8ac58d9c..7380251db6d 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -1,48 +1,48 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './XINFO_GROUPS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './XINFO_GROUPS'; -describe('XINFO GROUPS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['XINFO', 'GROUPS', 'key'] - ); - }); +// describe('XINFO GROUPS', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['XINFO', 'GROUPS', 'key'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - ['name', 'mygroup', 'consumers', 2, 'pending', 2, 'last-delivered-id', '1588152489012-0'], - ['name', 'some-other-group', 'consumers', 1, 'pending', 0, 'last-delivered-id', '1588152498034-0'] - ]), - [{ - name: 'mygroup', - consumers: 2, - pending: 2, - lastDeliveredId: '1588152489012-0' - }, { - name: 'some-other-group', - consumers: 1, - pending: 0, - lastDeliveredId: '1588152498034-0' - }] - ); - }); +// it('transformReply', () => { +// assert.deepEqual( +// transformReply([ +// ['name', 'mygroup', 'consumers', 2, 'pending', 2, 'last-delivered-id', '1588152489012-0'], +// ['name', 'some-other-group', 'consumers', 1, 'pending', 0, 'last-delivered-id', '1588152498034-0'] +// ]), +// [{ +// name: 'mygroup', +// consumers: 2, +// pending: 2, +// lastDeliveredId: '1588152489012-0' +// }, { +// name: 'some-other-group', +// consumers: 1, +// pending: 0, +// lastDeliveredId: '1588152498034-0' +// }] +// ); +// }); - testUtils.testWithClient('client.xInfoGroups', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xInfoGroups', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xInfoGroups('key'), - [{ - name: 'group', - consumers: 0, - pending: 0, - lastDeliveredId: '0-0' - }] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xInfoGroups('key'), +// [{ +// name: 'group', +// consumers: 0, +// pending: 0, +// lastDeliveredId: '0-0' +// }] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts index ca8d44f2875..a73c4607080 100644 --- a/packages/client/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -1,72 +1,72 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './XINFO_STREAM'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, transformReply } from './XINFO_STREAM'; -describe('XINFO STREAM', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['XINFO', 'STREAM', 'key'] - ); - }); +// describe('XINFO STREAM', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['XINFO', 'STREAM', 'key'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - 'length', 2, - 'radix-tree-keys', 1, - 'radix-tree-nodes', 2, - 'last-generated-id', '1538385846314-0', - 'groups', 2, - 'first-entry', ['1538385820729-0', ['foo', 'bar']], - 'last-entry', ['1538385846314-0', ['field', 'value']] - ]), - { - length: 2, - radixTreeKeys: 1, - radixTreeNodes: 2, - groups: 2, - lastGeneratedId: '1538385846314-0', - firstEntry: { - id: '1538385820729-0', - message: Object.create(null, { - foo: { - value: 'bar', - configurable: true, - enumerable: true - } - }) - }, - lastEntry: { - id: '1538385846314-0', - message: Object.create(null, { - field: { - value: 'value', - configurable: true, - enumerable: true - } - }) - } - } - ); - }); +// it('transformReply', () => { +// assert.deepEqual( +// transformReply([ +// 'length', 2, +// 'radix-tree-keys', 1, +// 'radix-tree-nodes', 2, +// 'last-generated-id', '1538385846314-0', +// 'groups', 2, +// 'first-entry', ['1538385820729-0', ['foo', 'bar']], +// 'last-entry', ['1538385846314-0', ['field', 'value']] +// ]), +// { +// length: 2, +// radixTreeKeys: 1, +// radixTreeNodes: 2, +// groups: 2, +// lastGeneratedId: '1538385846314-0', +// firstEntry: { +// id: '1538385820729-0', +// message: Object.create(null, { +// foo: { +// value: 'bar', +// configurable: true, +// enumerable: true +// } +// }) +// }, +// lastEntry: { +// id: '1538385846314-0', +// message: Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true +// } +// }) +// } +// } +// ); +// }); - testUtils.testWithClient('client.xInfoStream', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xInfoStream', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xInfoStream('key'), - { - length: 0, - radixTreeKeys: 0, - radixTreeNodes: 1, - groups: 1, - lastGeneratedId: '0-0', - firstEntry: null, - lastEntry: null - } - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xInfoStream('key'), +// { +// length: 0, +// radixTreeKeys: 0, +// radixTreeNodes: 1, +// groups: 1, +// lastGeneratedId: '0-0', +// firstEntry: null, +// lastEntry: null +// } +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XLEN.spec.ts b/packages/client/lib/commands/XLEN.spec.ts index 178024ba89e..8f2bf1a8c77 100644 --- a/packages/client/lib/commands/XLEN.spec.ts +++ b/packages/client/lib/commands/XLEN.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XLEN'; +import XLEN from './XLEN'; describe('XLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['XLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + XLEN.transformArguments('key'), + ['XLEN', 'key'] + ); + }); - testUtils.testWithClient('client.xLen', async client => { - assert.equal( - await client.xLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('xLen', async client => { + assert.equal( + await client.xLen('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/XPENDING.spec.ts b/packages/client/lib/commands/XPENDING.spec.ts index b1fef2a217f..bfa36d01e34 100644 --- a/packages/client/lib/commands/XPENDING.spec.ts +++ b/packages/client/lib/commands/XPENDING.spec.ts @@ -1,62 +1,62 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XPENDING'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XPENDING'; -describe('XPENDING', () => { - describe('transformArguments', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'group'), - ['XPENDING', 'key', 'group'] - ); - }); - }); +// describe('XPENDING', () => { +// describe('transformArguments', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key', 'group'), +// ['XPENDING', 'key', 'group'] +// ); +// }); +// }); - describe('client.xPending', () => { - testUtils.testWithClient('simple', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// describe('client.xPending', () => { +// testUtils.testWithClient('simple', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xPending('key', 'group'), - { - pending: 0, - firstId: null, - lastId: null, - consumers: null - } - ); - }, GLOBAL.SERVERS.OPEN); +// assert.deepEqual( +// await client.xPending('key', 'group'), +// { +// pending: 0, +// firstId: null, +// lastId: null, +// consumers: null +// } +// ); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('with consumers', async client => { - const [,, id] = await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), - client.xAdd('key', '*', { field: 'value' }), - client.xReadGroup('group', 'consumer', { - key: 'key', - id: '>' - }) - ]); +// testUtils.testWithClient('with consumers', async client => { +// const [,, id] = await Promise.all([ +// client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// client.xGroupCreateConsumer('key', 'group', 'consumer'), +// client.xAdd('key', '*', { field: 'value' }), +// client.xReadGroup('group', 'consumer', { +// key: 'key', +// id: '>' +// }) +// ]); - assert.deepEqual( - await client.xPending('key', 'group'), - { - pending: 1, - firstId: id, - lastId: id, - consumers: [{ - name: 'consumer', - deliveriesCounter: 1 - }] - } - ); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [6, 2] - }); - }); -}); +// assert.deepEqual( +// await client.xPending('key', 'group'), +// { +// pending: 1, +// firstId: id, +// lastId: id, +// consumers: [{ +// name: 'consumer', +// deliveriesCounter: 1 +// }] +// } +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [6, 2] +// }); +// }); +// }); diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index 0b57c704bb0..b08f71d88a2 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -1,53 +1,53 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XPENDING_RANGE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XPENDING_RANGE'; -describe('XPENDING RANGE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'group', '-', '+', 1), - ['XPENDING', 'key', 'group', '-', '+', '1'] - ); - }); +// describe('XPENDING RANGE', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '-', '+', 1), +// ['XPENDING', 'key', 'group', '-', '+', '1'] +// ); +// }); - it('with IDLE', () => { - assert.deepEqual( - transformArguments('key', 'group', '-', '+', 1, { - IDLE: 1, - }), - ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1'] - ); - }); +// it('with IDLE', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '-', '+', 1, { +// IDLE: 1, +// }), +// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1'] +// ); +// }); - it('with consumer', () => { - assert.deepEqual( - transformArguments('key', 'group', '-', '+', 1, { - consumer: 'consumer' - }), - ['XPENDING', 'key', 'group', '-', '+', '1', 'consumer'] - ); - }); +// it('with consumer', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '-', '+', 1, { +// consumer: 'consumer' +// }), +// ['XPENDING', 'key', 'group', '-', '+', '1', 'consumer'] +// ); +// }); - it('with IDLE, consumer', () => { - assert.deepEqual( - transformArguments('key', 'group', '-', '+', 1, { - IDLE: 1, - consumer: 'consumer' - }), - ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer'] - ); - }); - }); +// it('with IDLE, consumer', () => { +// assert.deepEqual( +// transformArguments('key', 'group', '-', '+', 1, { +// IDLE: 1, +// consumer: 'consumer' +// }), +// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer'] +// ); +// }); +// }); - testUtils.testWithClient('client.xPendingRange', async client => { - await client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }); +// testUtils.testWithClient('client.xPendingRange', async client => { +// await client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }); - assert.deepEqual( - await client.xPendingRange('key', 'group', '-', '+', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// assert.deepEqual( +// await client.xPendingRange('key', 'group', '-', '+', 1), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts index 01c713e9595..4d937c4e32a 100644 --- a/packages/client/lib/commands/XRANGE.spec.ts +++ b/packages/client/lib/commands/XRANGE.spec.ts @@ -1,30 +1,30 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XRANGE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XRANGE'; -describe('XRANGE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', '-', '+'), - ['XRANGE', 'key', '-', '+'] - ); - }); +// describe('XRANGE', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', '-', '+'), +// ['XRANGE', 'key', '-', '+'] +// ); +// }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - COUNT: 1 - }), - ['XRANGE', 'key', '-', '+', 'COUNT', '1'] - ); - }); - }); +// it('with COUNT', () => { +// assert.deepEqual( +// transformArguments('key', '-', '+', { +// COUNT: 1 +// }), +// ['XRANGE', 'key', '-', '+', 'COUNT', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.xRange', async client => { - assert.deepEqual( - await client.xRange('key', '+', '-'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xRange', async client => { +// assert.deepEqual( +// await client.xRange('key', '+', '-'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XREAD.spec.ts b/packages/client/lib/commands/XREAD.spec.ts index b607f53532e..13aa35b83fc 100644 --- a/packages/client/lib/commands/XREAD.spec.ts +++ b/packages/client/lib/commands/XREAD.spec.ts @@ -1,103 +1,103 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { FIRST_KEY_INDEX, transformArguments } from './XREAD'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { FIRST_KEY_INDEX, transformArguments } from './XREAD'; -describe('XREAD', () => { - describe('FIRST_KEY_INDEX', () => { - it('single stream', () => { - assert.equal( - FIRST_KEY_INDEX({ key: 'key', id: '' }), - 'key' - ); - }); +// describe('XREAD', () => { +// describe('FIRST_KEY_INDEX', () => { +// it('single stream', () => { +// assert.equal( +// FIRST_KEY_INDEX({ key: 'key', id: '' }), +// 'key' +// ); +// }); - it('multiple streams', () => { - assert.equal( - FIRST_KEY_INDEX([{ key: '1', id: '' }, { key: '2', id: '' }]), - '1' - ); - }); - }); +// it('multiple streams', () => { +// assert.equal( +// FIRST_KEY_INDEX([{ key: '1', id: '' }, { key: '2', id: '' }]), +// '1' +// ); +// }); +// }); - describe('transformArguments', () => { - it('single stream', () => { - assert.deepEqual( - transformArguments({ - key: 'key', - id: '0' - }), - ['XREAD', 'STREAMS', 'key', '0'] - ); - }); +// describe('transformArguments', () => { +// it('single stream', () => { +// assert.deepEqual( +// transformArguments({ +// key: 'key', +// id: '0' +// }), +// ['XREAD', 'STREAMS', 'key', '0'] +// ); +// }); - it('multiple streams', () => { - assert.deepEqual( - transformArguments([{ - key: '1', - id: '0' - }, { - key: '2', - id: '0' - }]), - ['XREAD', 'STREAMS', '1', '2', '0', '0'] - ); - }); +// it('multiple streams', () => { +// assert.deepEqual( +// transformArguments([{ +// key: '1', +// id: '0' +// }, { +// key: '2', +// id: '0' +// }]), +// ['XREAD', 'STREAMS', '1', '2', '0', '0'] +// ); +// }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments({ - key: 'key', - id: '0' - }, { - COUNT: 1 - }), - ['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0'] - ); - }); +// it('with COUNT', () => { +// assert.deepEqual( +// transformArguments({ +// key: 'key', +// id: '0' +// }, { +// COUNT: 1 +// }), +// ['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0'] +// ); +// }); - it('with BLOCK', () => { - assert.deepEqual( - transformArguments({ - key: 'key', - id: '0' - }, { - BLOCK: 0 - }), - ['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0'] - ); - }); +// it('with BLOCK', () => { +// assert.deepEqual( +// transformArguments({ +// key: 'key', +// id: '0' +// }, { +// BLOCK: 0 +// }), +// ['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0'] +// ); +// }); - it('with COUNT, BLOCK', () => { - assert.deepEqual( - transformArguments({ - key: 'key', - id: '0' - }, { - COUNT: 1, - BLOCK: 0 - }), - ['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0'] - ); - }); - }); +// it('with COUNT, BLOCK', () => { +// assert.deepEqual( +// transformArguments({ +// key: 'key', +// id: '0' +// }, { +// COUNT: 1, +// BLOCK: 0 +// }), +// ['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0'] +// ); +// }); +// }); - testUtils.testWithClient('client.xRead', async client => { - assert.equal( - await client.xRead({ - key: 'key', - id: '0' - }), - null - ); - }, GLOBAL.SERVERS.OPEN); +// testUtils.testWithClient('client.xRead', async client => { +// assert.equal( +// await client.xRead({ +// key: 'key', +// id: '0' +// }), +// null +// ); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithCluster('cluster.xRead', async cluster => { - assert.equal( - await cluster.xRead({ - key: 'key', - id: '0' - }), - null - ); - }, GLOBAL.CLUSTERS.OPEN); -}); +// testUtils.testWithCluster('cluster.xRead', async cluster => { +// assert.equal( +// await cluster.xRead({ +// key: 'key', +// id: '0' +// }), +// null +// ); +// }, GLOBAL.CLUSTERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XREADGROUP.spec.ts b/packages/client/lib/commands/XREADGROUP.spec.ts index fa196d504ad..1cccdb79e65 100644 --- a/packages/client/lib/commands/XREADGROUP.spec.ts +++ b/packages/client/lib/commands/XREADGROUP.spec.ts @@ -1,153 +1,153 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { FIRST_KEY_INDEX, transformArguments } from './XREADGROUP'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { FIRST_KEY_INDEX, transformArguments } from './XREADGROUP'; -describe('XREADGROUP', () => { - describe('FIRST_KEY_INDEX', () => { - it('single stream', () => { - assert.equal( - FIRST_KEY_INDEX('', '', { key: 'key', id: '' }), - 'key' - ); - }); +// describe('XREADGROUP', () => { +// describe('FIRST_KEY_INDEX', () => { +// it('single stream', () => { +// assert.equal( +// FIRST_KEY_INDEX('', '', { key: 'key', id: '' }), +// 'key' +// ); +// }); - it('multiple streams', () => { - assert.equal( - FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]), - '1' - ); - }); - }); +// it('multiple streams', () => { +// assert.equal( +// FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]), +// '1' +// ); +// }); +// }); - describe('transformArguments', () => { - it('single stream', () => { - assert.deepEqual( - transformArguments('group', 'consumer', { - key: 'key', - id: '0' - }), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0'] - ); - }); +// describe('transformArguments', () => { +// it('single stream', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', { +// key: 'key', +// id: '0' +// }), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0'] +// ); +// }); - it('multiple streams', () => { - assert.deepEqual( - transformArguments('group', 'consumer', [{ - key: '1', - id: '0' - }, { - key: '2', - id: '0' - }]), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0', '0'] - ); - }); +// it('multiple streams', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', [{ +// key: '1', +// id: '0' +// }, { +// key: '2', +// id: '0' +// }]), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0', '0'] +// ); +// }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('group', 'consumer', { - key: 'key', - id: '0' - }, { - COUNT: 1 - }), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0'] - ); - }); +// it('with COUNT', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', { +// key: 'key', +// id: '0' +// }, { +// COUNT: 1 +// }), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0'] +// ); +// }); - it('with BLOCK', () => { - assert.deepEqual( - transformArguments('group', 'consumer', { - key: 'key', - id: '0' - }, { - BLOCK: 0 - }), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0'] - ); - }); +// it('with BLOCK', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', { +// key: 'key', +// id: '0' +// }, { +// BLOCK: 0 +// }), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0'] +// ); +// }); - it('with NOACK', () => { - assert.deepEqual( - transformArguments('group', 'consumer', { - key: 'key', - id: '0' - }, { - NOACK: true - }), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0'] - ); - }); +// it('with NOACK', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', { +// key: 'key', +// id: '0' +// }, { +// NOACK: true +// }), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0'] +// ); +// }); - it('with COUNT, BLOCK, NOACK', () => { - assert.deepEqual( - transformArguments('group', 'consumer', { - key: 'key', - id: '0' - }, { - COUNT: 1, - BLOCK: 0, - NOACK: true - }), - ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0'] - ); - }); - }); +// it('with COUNT, BLOCK, NOACK', () => { +// assert.deepEqual( +// transformArguments('group', 'consumer', { +// key: 'key', +// id: '0' +// }, { +// COUNT: 1, +// BLOCK: 0, +// NOACK: true +// }), +// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0'] +// ); +// }); +// }); - describe('client.xReadGroup', () => { - testUtils.testWithClient('null', async client => { - const [, readGroupReply] = await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xReadGroup('group', 'consumer', { - key: 'key', - id: '>' - }) - ]); +// describe('client.xReadGroup', () => { +// testUtils.testWithClient('null', async client => { +// const [, readGroupReply] = await Promise.all([ +// client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// client.xReadGroup('group', 'consumer', { +// key: 'key', +// id: '>' +// }) +// ]); - assert.equal(readGroupReply, null); - }, GLOBAL.SERVERS.OPEN); +// assert.equal(readGroupReply, null); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('with a message', async client => { - const [, id, readGroupReply] = await Promise.all([ - client.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - client.xAdd('key', '*', { field: 'value' }), - client.xReadGroup('group', 'consumer', { - key: 'key', - id: '>' - }) - ]); +// testUtils.testWithClient('with a message', async client => { +// const [, id, readGroupReply] = await Promise.all([ +// client.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// client.xAdd('key', '*', { field: 'value' }), +// client.xReadGroup('group', 'consumer', { +// key: 'key', +// id: '>' +// }) +// ]); - assert.deepEqual(readGroupReply, [{ - name: 'key', - messages: [{ - id, - message: Object.create(null, { - field: { - value: 'value', - configurable: true, - enumerable: true - } - }) - }] - }]); - }, GLOBAL.SERVERS.OPEN); - }); +// assert.deepEqual(readGroupReply, [{ +// name: 'key', +// messages: [{ +// id, +// message: Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true +// } +// }) +// }] +// }]); +// }, GLOBAL.SERVERS.OPEN); +// }); - testUtils.testWithCluster('cluster.xReadGroup', async cluster => { - const [, readGroupReply] = await Promise.all([ - cluster.xGroupCreate('key', 'group', '$', { - MKSTREAM: true - }), - cluster.xReadGroup('group', 'consumer', { - key: 'key', - id: '>' - }) - ]); +// testUtils.testWithCluster('cluster.xReadGroup', async cluster => { +// const [, readGroupReply] = await Promise.all([ +// cluster.xGroupCreate('key', 'group', '$', { +// MKSTREAM: true +// }), +// cluster.xReadGroup('group', 'consumer', { +// key: 'key', +// id: '>' +// }) +// ]); - assert.equal(readGroupReply, null); - }, GLOBAL.CLUSTERS.OPEN); -}); +// assert.equal(readGroupReply, null); +// }, GLOBAL.CLUSTERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts index fd6e1a3adfe..344edd62e58 100644 --- a/packages/client/lib/commands/XREVRANGE.spec.ts +++ b/packages/client/lib/commands/XREVRANGE.spec.ts @@ -1,30 +1,30 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XREVRANGE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XREVRANGE'; -describe('XREVRANGE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', '-', '+'), - ['XREVRANGE', 'key', '-', '+'] - ); - }); +// describe('XREVRANGE', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', '-', '+'), +// ['XREVRANGE', 'key', '-', '+'] +// ); +// }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - COUNT: 1 - }), - ['XREVRANGE', 'key', '-', '+', 'COUNT', '1'] - ); - }); - }); +// it('with COUNT', () => { +// assert.deepEqual( +// transformArguments('key', '-', '+', { +// COUNT: 1 +// }), +// ['XREVRANGE', 'key', '-', '+', 'COUNT', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.xRevRange', async client => { - assert.deepEqual( - await client.xRevRange('key', '+', '-'), - [] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xRevRange', async client => { +// assert.deepEqual( +// await client.xRevRange('key', '+', '-'), +// [] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/XTRIM.spec.ts b/packages/client/lib/commands/XTRIM.spec.ts index a8f8078eb28..bcbb1c928c5 100644 --- a/packages/client/lib/commands/XTRIM.spec.ts +++ b/packages/client/lib/commands/XTRIM.spec.ts @@ -1,49 +1,49 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XTRIM'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './XTRIM'; -describe('XTRIM', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'MAXLEN', 1), - ['XTRIM', 'key', 'MAXLEN', '1'] - ); - }); +// describe('XTRIM', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments('key', 'MAXLEN', 1), +// ['XTRIM', 'key', 'MAXLEN', '1'] +// ); +// }); - it('with strategyModifier', () => { - assert.deepEqual( - transformArguments('key', 'MAXLEN', 1, { - strategyModifier: '=' - }), - ['XTRIM', 'key', 'MAXLEN', '=', '1'] - ); - }); +// it('with strategyModifier', () => { +// assert.deepEqual( +// transformArguments('key', 'MAXLEN', 1, { +// strategyModifier: '=' +// }), +// ['XTRIM', 'key', 'MAXLEN', '=', '1'] +// ); +// }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('key', 'MAXLEN', 1, { - LIMIT: 1 - }), - ['XTRIM', 'key', 'MAXLEN', '1', 'LIMIT', '1'] - ); - }); +// it('with LIMIT', () => { +// assert.deepEqual( +// transformArguments('key', 'MAXLEN', 1, { +// LIMIT: 1 +// }), +// ['XTRIM', 'key', 'MAXLEN', '1', 'LIMIT', '1'] +// ); +// }); - it('with strategyModifier, LIMIT', () => { - assert.deepEqual( - transformArguments('key', 'MAXLEN', 1, { - strategyModifier: '=', - LIMIT: 1 - }), - ['XTRIM', 'key', 'MAXLEN', '=', '1', 'LIMIT', '1'] - ); - }); - }); +// it('with strategyModifier, LIMIT', () => { +// assert.deepEqual( +// transformArguments('key', 'MAXLEN', 1, { +// strategyModifier: '=', +// LIMIT: 1 +// }), +// ['XTRIM', 'key', 'MAXLEN', '=', '1', 'LIMIT', '1'] +// ); +// }); +// }); - testUtils.testWithClient('client.xTrim', async client => { - assert.equal( - await client.xTrim('key', 'MAXLEN', 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.xTrim', async client => { +// assert.equal( +// await client.xTrim('key', 'MAXLEN', 1), +// 0 +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 83a83c76de7..394d2159545 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -104,8 +104,20 @@ import SETEX from './SETEX'; import SETNX from './SETNX'; import SETRANGE from './SETRANGE'; import SMEMBERS from './SMEMBERS'; +import SPUBLISH from './SPUBLISH'; +import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; +import SRANDMEMBER from './SRANDMEMBER'; +import SREM from './SREM'; import SSCAN from './SSCAN'; import STRLEN from './STRLEN'; +import TOUCH from './TOUCH'; +import TTL from './TTL'; +import TYPE from './TYPE'; +import UNLINK from './UNLINK'; +import UNWATCH from './UNWATCH'; +import WAIT from './WAIT'; +import WATCH from './WATCH'; +import XLEN from './XLEN'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; import ZCOUNT from './ZCOUNT'; @@ -344,10 +356,34 @@ export default { setRange: SETRANGE, SMEMBERS, sMembers: SMEMBERS, + SPUBLISH, + sPublish: SPUBLISH, + SRANDMEMBER_COUNT, + sRandMemberCount: SRANDMEMBER_COUNT, + SRANDMEMBER, + sRandMember: SRANDMEMBER, + SREM, + sRem: SREM, SSCAN, sScan: SSCAN, STRLEN, strLen: STRLEN, + TOUCH, + touch: TOUCH, + TTL, + ttl: TTL, + TYPE, + type: TYPE, + UNLINK, + unlink: UNLINK, + UNWATCH, + unwatch: UNWATCH, + WAIT, + wait: WAIT, + WATCH, + watch: WATCH, + XLEN, + xLen: XLEN, ZADD, zAdd: ZADD, ZCARD, diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 7a783792ecd..0fb311bff8b 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -13,7 +13,7 @@ import { createCluster, RedisClusterOptions, RedisClusterType -} from '@redis/client'; +} from '@redis/client/index'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; From 8d615e99ed01acc8d20a7ef245d269980cc77364 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Apr 2023 19:17:11 -0400 Subject: [PATCH 026/325] wip --- packages/client/lib/commands/SHUTDOWN.spec.ts | 48 ++--- packages/client/lib/commands/SHUTDOWN.ts | 16 +- packages/client/lib/commands/SINTER.spec.ts | 43 ++--- .../client/lib/commands/SINTERCARD.spec.ts | 54 +++--- packages/client/lib/commands/SINTERCARD.ts | 4 +- .../client/lib/commands/SINTERSTORE.spec.ts | 43 ++--- .../client/lib/commands/SISMEMBER.spec.ts | 29 +-- packages/client/lib/commands/SMEMBERS.spec.ts | 29 +-- .../client/lib/commands/SMISMEMBER.spec.ts | 31 ++-- packages/client/lib/commands/SMOVE.spec.ts | 34 ++-- packages/client/lib/commands/SORT.spec.ts | 167 ++++++++--------- packages/client/lib/commands/SORT.ts | 17 +- packages/client/lib/commands/SORT_RO.spec.ts | 169 +++++++++--------- .../client/lib/commands/SORT_STORE.spec.ts | 167 ++++++++--------- packages/client/lib/commands/SORT_STORE.ts | 4 +- packages/client/lib/commands/index.ts | 28 ++- 16 files changed, 471 insertions(+), 412 deletions(-) diff --git a/packages/client/lib/commands/SHUTDOWN.spec.ts b/packages/client/lib/commands/SHUTDOWN.spec.ts index d58cf4443c7..caa3a5dfd0d 100644 --- a/packages/client/lib/commands/SHUTDOWN.spec.ts +++ b/packages/client/lib/commands/SHUTDOWN.spec.ts @@ -1,27 +1,27 @@ -import { strict as assert } from 'assert'; -import { transformArguments } from './SHUTDOWN'; +// import { strict as assert } from 'assert'; +// import { transformArguments } from './SHUTDOWN'; -describe('SHUTDOWN', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['SHUTDOWN'] - ); - }); +// describe('SHUTDOWN', () => { +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments(), +// ['SHUTDOWN'] +// ); +// }); - it('NOSAVE', () => { - assert.deepEqual( - transformArguments('NOSAVE'), - ['SHUTDOWN', 'NOSAVE'] - ); - }); +// it('NOSAVE', () => { +// assert.deepEqual( +// transformArguments('NOSAVE'), +// ['SHUTDOWN', 'NOSAVE'] +// ); +// }); - it('SAVE', () => { - assert.deepEqual( - transformArguments('SAVE'), - ['SHUTDOWN', 'SAVE'] - ); - }); - }); -}); +// it('SAVE', () => { +// assert.deepEqual( +// transformArguments('SAVE'), +// ['SHUTDOWN', 'SAVE'] +// ); +// }); +// }); +// }); diff --git a/packages/client/lib/commands/SHUTDOWN.ts b/packages/client/lib/commands/SHUTDOWN.ts index 1990d05a2ed..e2c544c389d 100644 --- a/packages/client/lib/commands/SHUTDOWN.ts +++ b/packages/client/lib/commands/SHUTDOWN.ts @@ -1,11 +1,11 @@ -export function transformArguments(mode?: 'NOSAVE' | 'SAVE'): Array { - const args = ['SHUTDOWN']; +// export function transformArguments(mode?: 'NOSAVE' | 'SAVE'): Array { +// const args = ['SHUTDOWN']; - if (mode) { - args.push(mode); - } +// if (mode) { +// args.push(mode); +// } - return args; -} +// return args; +// } -export declare function transformReply(): void; +// export declare function transformReply(): void; diff --git a/packages/client/lib/commands/SINTER.spec.ts b/packages/client/lib/commands/SINTER.spec.ts index 2324eac3ee8..f147abbdbb9 100644 --- a/packages/client/lib/commands/SINTER.spec.ts +++ b/packages/client/lib/commands/SINTER.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SINTER'; +import SINTER from './SINTER'; describe('SINTER', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['SINTER', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SINTER.transformArguments('key'), + ['SINTER', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['SINTER', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SINTER.transformArguments(['1', '2']), + ['SINTER', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sInter', async client => { - assert.deepEqual( - await client.sInter('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sInter', async client => { + assert.deepEqual( + await client.sInter('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SINTERCARD.spec.ts b/packages/client/lib/commands/SINTERCARD.spec.ts index a93699f6a13..643e5114064 100644 --- a/packages/client/lib/commands/SINTERCARD.spec.ts +++ b/packages/client/lib/commands/SINTERCARD.spec.ts @@ -1,30 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SINTERCARD'; +import SINTERCARD from './SINTERCARD'; describe('SINTERCARD', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['SINTERCARD', '2', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SINTERCARD.transformArguments(['1', '2']), + ['SINTERCARD', '2', '1', '2'] + ); + }); + + it('with limit (backwards compatibility)', () => { + assert.deepEqual( + SINTERCARD.transformArguments(['1', '2'], 1), + ['SINTERCARD', '2', '1', '2', 'LIMIT', '1'] + ); + }); - it('with limit', () => { - assert.deepEqual( - transformArguments(['1', '2'], 1), - ['SINTERCARD', '2', '1', '2', 'LIMIT', '1'] - ); - }); + it('with LIMIT', () => { + assert.deepEqual( + SINTERCARD.transformArguments(['1', '2'], { + LIMIT: 1 + }), + ['SINTERCARD', '2', '1', '2', 'LIMIT', '1'] + ); }); + }); - testUtils.testWithClient('client.sInterCard', async client => { - assert.deepEqual( - await client.sInterCard('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sInterCard', async client => { + assert.deepEqual( + await client.sInterCard('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SINTERCARD.ts b/packages/client/lib/commands/SINTERCARD.ts index 967db96110a..41d4626249e 100644 --- a/packages/client/lib/commands/SINTERCARD.ts +++ b/packages/client/lib/commands/SINTERCARD.ts @@ -1,5 +1,5 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { pushVariadicArgument } from './generic-transformers'; export interface SInterCardOptions { LIMIT?: number; @@ -12,7 +12,7 @@ export default { keys: Array | RedisArgument, options?: SInterCardOptions | number // `number` for backwards compatibility ) { - const args = pushVariadicArguments(['SINTERCARD'], keys); + const args = pushVariadicArgument(['SINTERCARD'], keys); if (typeof options === 'number') { // backwards compatibility args.push('LIMIT', options.toString()); diff --git a/packages/client/lib/commands/SINTERSTORE.spec.ts b/packages/client/lib/commands/SINTERSTORE.spec.ts index c4a6a095e7d..7a78f5a0992 100644 --- a/packages/client/lib/commands/SINTERSTORE.spec.ts +++ b/packages/client/lib/commands/SINTERSTORE.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SINTERSTORE'; +import SINTERSTORE from './SINTERSTORE'; describe('SINTERSTORE', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['SINTERSTORE', 'destination', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SINTERSTORE.transformArguments('destination', 'key'), + ['SINTERSTORE', 'destination', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['SINTERSTORE', 'destination', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SINTERSTORE.transformArguments('destination', ['1', '2']), + ['SINTERSTORE', 'destination', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sInterStore', async client => { - assert.equal( - await client.sInterStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sInterStore', async client => { + assert.equal( + await client.sInterStore('{tag}destination', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SISMEMBER.spec.ts b/packages/client/lib/commands/SISMEMBER.spec.ts index 8d18c83697a..c4b1502230e 100644 --- a/packages/client/lib/commands/SISMEMBER.spec.ts +++ b/packages/client/lib/commands/SISMEMBER.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SISMEMBER'; +import SISMEMBER from './SISMEMBER'; describe('SISMEMBER', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['SISMEMBER', 'key', 'member'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SISMEMBER.transformArguments('key', 'member'), + ['SISMEMBER', 'key', 'member'] + ); + }); - testUtils.testWithClient('client.sIsMember', async client => { - assert.equal( - await client.sIsMember('key', 'member'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sIsMember', async client => { + assert.equal( + await client.sIsMember('key', 'member'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SMEMBERS.spec.ts b/packages/client/lib/commands/SMEMBERS.spec.ts index b9c58c9eebb..6ca8ce6597f 100644 --- a/packages/client/lib/commands/SMEMBERS.spec.ts +++ b/packages/client/lib/commands/SMEMBERS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SMEMBERS'; +import SMEMBERS from './SMEMBERS'; describe('SMEMBERS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['SMEMBERS', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SMEMBERS.transformArguments('key'), + ['SMEMBERS', 'key'] + ); + }); - testUtils.testWithClient('client.sMembers', async client => { - assert.deepEqual( - await client.sMembers('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sMembers', async client => { + assert.deepEqual( + await client.sMembers('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SMISMEMBER.spec.ts b/packages/client/lib/commands/SMISMEMBER.spec.ts index e3728134029..92619820d63 100644 --- a/packages/client/lib/commands/SMISMEMBER.spec.ts +++ b/packages/client/lib/commands/SMISMEMBER.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SMISMEMBER'; +import SMISMEMBER from './SMISMEMBER'; describe('SMISMEMBER', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['SMISMEMBER', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SMISMEMBER.transformArguments('key', ['1', '2']), + ['SMISMEMBER', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.smIsMember', async client => { - assert.deepEqual( - await client.smIsMember('key', ['1', '2']), - [false, false] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('smIsMember', async client => { + assert.deepEqual( + await client.smIsMember('key', ['1', '2']), + [0, 0] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SMOVE.spec.ts b/packages/client/lib/commands/SMOVE.spec.ts index e3308ee8143..d3a9ca6eda6 100644 --- a/packages/client/lib/commands/SMOVE.spec.ts +++ b/packages/client/lib/commands/SMOVE.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SMOVE'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './SMOVE'; -describe('SMOVE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination', 'member'), - ['SMOVE', 'source', 'destination', 'member'] - ); - }); +// describe('SMOVE', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('source', 'destination', 'member'), +// ['SMOVE', 'source', 'destination', 'member'] +// ); +// }); - testUtils.testWithClient('client.sMove', async client => { - assert.equal( - await client.sMove('source', 'destination', 'member'), - false - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.sMove', async client => { +// assert.equal( +// await client.sMove('source', 'destination', 'member'), +// false +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/SORT.spec.ts b/packages/client/lib/commands/SORT.spec.ts index 4967b020ad5..58540b3f2f8 100644 --- a/packages/client/lib/commands/SORT.spec.ts +++ b/packages/client/lib/commands/SORT.spec.ts @@ -1,96 +1,99 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SORT'; +import SORT from './SORT'; describe('SORT', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key'), - ['SORT', 'key'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SORT.transformArguments('key'), + ['SORT', 'key'] + ); + }); - it('with BY', () => { - assert.deepEqual( - transformArguments('key', { - BY: 'pattern' - }), - ['SORT', 'key', 'BY', 'pattern'] - ); - }); + it('with BY', () => { + assert.deepEqual( + SORT.transformArguments('key', { + BY: 'pattern' + }), + ['SORT', 'key', 'BY', 'pattern'] + ); + }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('key', { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['SORT', 'key', 'LIMIT', '0', '1'] - ); - }); + it('with LIMIT', () => { + assert.deepEqual( + SORT.transformArguments('key', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['SORT', 'key', 'LIMIT', '0', '1'] + ); + }); - describe('with GET', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', { - GET: 'pattern' - }), - ['SORT', 'key', 'GET', 'pattern'] - ); - }); + describe('with GET', () => { + it('string', () => { + assert.deepEqual( + SORT.transformArguments('key', { + GET: 'pattern' + }), + ['SORT', 'key', 'GET', 'pattern'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', { - GET: ['1', '2'] - }), - ['SORT', 'key', 'GET', '1', 'GET', '2'] - ); - }); - }); + it('array', () => { + assert.deepEqual( + SORT.transformArguments('key', { + GET: ['1', '2'] + }), + ['SORT', 'key', 'GET', '1', 'GET', '2'] + ); + }); + }); - it('with DIRECTION', () => { - assert.deepEqual( - transformArguments('key', { - DIRECTION: 'ASC' - }), - ['SORT', 'key', 'ASC'] - ); - }); + it('with DIRECTION', () => { + assert.deepEqual( + SORT.transformArguments('key', { + DIRECTION: 'ASC' + }), + ['SORT', 'key', 'ASC'] + ); + }); - it('with ALPHA', () => { - assert.deepEqual( - transformArguments('key', { - ALPHA: true - }), - ['SORT', 'key', 'ALPHA'] - ); - }); + it('with ALPHA', () => { + assert.deepEqual( + SORT.transformArguments('key', { + ALPHA: true + }), + ['SORT', 'key', 'ALPHA'] + ); + }); - it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { - assert.deepEqual( - transformArguments('key', { - BY: 'pattern', - LIMIT: { - offset: 0, - count: 1 - }, - GET: 'pattern', - DIRECTION: 'ASC', - ALPHA: true - }), - ['SORT', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] - ); - }); + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { + assert.deepEqual( + SORT.transformArguments('key', { + BY: 'pattern', + LIMIT: { + offset: 0, + count: 1 + }, + GET: 'pattern', + DIRECTION: 'ASC', + ALPHA: true + }), + ['SORT', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] + ); }); + }); - testUtils.testWithClient('client.sort', async client => { - assert.deepEqual( - await client.sort('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sort', async client => { + assert.deepEqual( + await client.sort('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SORT.ts b/packages/client/lib/commands/SORT.ts index 8d112e17e0f..b71383943e9 100644 --- a/packages/client/lib/commands/SORT.ts +++ b/packages/client/lib/commands/SORT.ts @@ -1,21 +1,22 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export interface SortOptions { - BY?: string; + BY?: RedisArgument; LIMIT?: { offset: number; count: number; - }, - GET?: string | Array; + }; + GET?: RedisArgument | Array; DIRECTION?: 'ASC' | 'DESC'; - ALPHA?: true; + ALPHA?: boolean; } export function transformSortArguments( command: RedisArgument, + key: RedisArgument, options?: SortOptions ) { - const args = [command]; + const args: Array = [command, key]; if (options?.BY) { args.push('BY', options.BY); @@ -30,12 +31,12 @@ export function transformSortArguments( } if (options?.GET) { - if (typeof options.GET === 'string') { - args.push('GET', options.GET); - } else { + if (Array.isArray(options.GET)) { for (const pattern of options.GET) { args.push('GET', pattern); } + } else { + args.push('GET', options.GET); } } diff --git a/packages/client/lib/commands/SORT_RO.spec.ts b/packages/client/lib/commands/SORT_RO.spec.ts index fe3ca1240d7..d1349df2274 100644 --- a/packages/client/lib/commands/SORT_RO.spec.ts +++ b/packages/client/lib/commands/SORT_RO.spec.ts @@ -1,98 +1,101 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SORT_RO'; +import SORT_RO from './SORT_RO'; describe('SORT_RO', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key'), - ['SORT_RO', 'key'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SORT_RO.transformArguments('key'), + ['SORT_RO', 'key'] + ); + }); - it('with BY', () => { - assert.deepEqual( - transformArguments('key', { - BY: 'pattern' - }), - ['SORT_RO', 'key', 'BY', 'pattern'] - ); - }); + it('with BY', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + BY: 'pattern' + }), + ['SORT_RO', 'key', 'BY', 'pattern'] + ); + }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('key', { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['SORT_RO', 'key', 'LIMIT', '0', '1'] - ); - }); + it('with LIMIT', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['SORT_RO', 'key', 'LIMIT', '0', '1'] + ); + }); - describe('with GET', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', { - GET: 'pattern' - }), - ['SORT_RO', 'key', 'GET', 'pattern'] - ); - }); + describe('with GET', () => { + it('string', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + GET: 'pattern' + }), + ['SORT_RO', 'key', 'GET', 'pattern'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', { - GET: ['1', '2'] - }), - ['SORT_RO', 'key', 'GET', '1', 'GET', '2'] - ); - }); - }); + it('array', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + GET: ['1', '2'] + }), + ['SORT_RO', 'key', 'GET', '1', 'GET', '2'] + ); + }); + }); - it('with DIRECTION', () => { - assert.deepEqual( - transformArguments('key', { - DIRECTION: 'ASC' - }), - ['SORT_RO', 'key', 'ASC'] - ); - }); + it('with DIRECTION', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + DIRECTION: 'ASC' + }), + ['SORT_RO', 'key', 'ASC'] + ); + }); - it('with ALPHA', () => { - assert.deepEqual( - transformArguments('key', { - ALPHA: true - }), - ['SORT_RO', 'key', 'ALPHA'] - ); - }); + it('with ALPHA', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + ALPHA: true + }), + ['SORT_RO', 'key', 'ALPHA'] + ); + }); - it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { - assert.deepEqual( - transformArguments('key', { - BY: 'pattern', - LIMIT: { - offset: 0, - count: 1 - }, - GET: 'pattern', - DIRECTION: 'ASC', - ALPHA: true, - }), - ['SORT_RO', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] - ); - }); + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { + assert.deepEqual( + SORT_RO.transformArguments('key', { + BY: 'pattern', + LIMIT: { + offset: 0, + count: 1 + }, + GET: 'pattern', + DIRECTION: 'ASC', + ALPHA: true, + }), + ['SORT_RO', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] + ); }); + }); - testUtils.testWithClient('client.sortRo', async client => { - assert.deepEqual( - await client.sortRo('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.sortRo', async client => { + assert.deepEqual( + await client.sortRo('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SORT_STORE.spec.ts b/packages/client/lib/commands/SORT_STORE.spec.ts index d078135255d..1d1152852b2 100644 --- a/packages/client/lib/commands/SORT_STORE.spec.ts +++ b/packages/client/lib/commands/SORT_STORE.spec.ts @@ -1,96 +1,99 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SORT_STORE'; +import SORT_STORE from './SORT_STORE'; describe('SORT STORE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('source', 'destination'), - ['SORT', 'source', 'STORE', 'destination'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination'), + ['SORT', 'source', 'STORE', 'destination'] + ); + }); - it('with BY', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - BY: 'pattern' - }), - ['SORT', 'source', 'BY', 'pattern', 'STORE', 'destination'] - ); - }); + it('with BY', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + BY: 'pattern' + }), + ['SORT', 'source', 'BY', 'pattern', 'STORE', 'destination'] + ); + }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - LIMIT: { - offset: 0, - count: 1 - } - }), - ['SORT', 'source', 'LIMIT', '0', '1', 'STORE', 'destination'] - ); - }); + it('with LIMIT', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['SORT', 'source', 'LIMIT', '0', '1', 'STORE', 'destination'] + ); + }); - describe('with GET', () => { - it('string', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - GET: 'pattern' - }), - ['SORT', 'source', 'GET', 'pattern', 'STORE', 'destination'] - ); - }); + describe('with GET', () => { + it('string', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + GET: 'pattern' + }), + ['SORT', 'source', 'GET', 'pattern', 'STORE', 'destination'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - GET: ['1', '2'] - }), - ['SORT', 'source', 'GET', '1', 'GET', '2', 'STORE', 'destination'] - ); - }); - }); + it('array', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + GET: ['1', '2'] + }), + ['SORT', 'source', 'GET', '1', 'GET', '2', 'STORE', 'destination'] + ); + }); + }); - it('with DIRECTION', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - DIRECTION: 'ASC' - }), - ['SORT', 'source', 'ASC', 'STORE', 'destination'] - ); - }); + it('with DIRECTION', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + DIRECTION: 'ASC' + }), + ['SORT', 'source', 'ASC', 'STORE', 'destination'] + ); + }); - it('with ALPHA', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - ALPHA: true - }), - ['SORT', 'source', 'ALPHA', 'STORE', 'destination'] - ); - }); + it('with ALPHA', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + ALPHA: true + }), + ['SORT', 'source', 'ALPHA', 'STORE', 'destination'] + ); + }); - it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - BY: 'pattern', - LIMIT: { - offset: 0, - count: 1 - }, - GET: 'pattern', - DIRECTION: 'ASC', - ALPHA: true - }), - ['SORT', 'source', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA', 'STORE', 'destination'] - ); - }); + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { + assert.deepEqual( + SORT_STORE.transformArguments('source', 'destination', { + BY: 'pattern', + LIMIT: { + offset: 0, + count: 1 + }, + GET: 'pattern', + DIRECTION: 'ASC', + ALPHA: true + }), + ['SORT', 'source', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA', 'STORE', 'destination'] + ); }); + }); - testUtils.testWithClient('client.sortStore', async client => { - assert.equal( - await client.sortStore('source', 'destination'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sortStore', async client => { + assert.equal( + await client.sortStore('{tag}source', '{tag}destination'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SORT_STORE.ts b/packages/client/lib/commands/SORT_STORE.ts index 5af19d50cba..b6ad709fb60 100644 --- a/packages/client/lib/commands/SORT_STORE.ts +++ b/packages/client/lib/commands/SORT_STORE.ts @@ -1,5 +1,5 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { SortOptions, transformSortArguments } from './SORT'; +import SORT, { SortOptions } from './SORT'; export default { FIRST_KEY_INDEX: 1, @@ -9,7 +9,7 @@ export default { destination: RedisArgument, options?: SortOptions ) { - const args = transformSortArguments(source, options); + const args = SORT.transformArguments(source, options); args.push('STORE', destination); return args; }, diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 394d2159545..1a6faaa4042 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -103,7 +103,15 @@ import SET from './SET'; import SETEX from './SETEX'; import SETNX from './SETNX'; import SETRANGE from './SETRANGE'; +import SINTER from './SINTER'; +import SINTERCARD from './SINTERCARD'; +import SINTERSTORE from './SINTERSTORE'; +import SISMEMBER from './SISMEMBER'; import SMEMBERS from './SMEMBERS'; +import SMISMEMBER from './SMISMEMBER'; +import SORT_RO from './SORT_RO'; +import SORT_STORE from './SORT_STORE'; +import SORT from './SORT'; import SPUBLISH from './SPUBLISH'; import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; import SRANDMEMBER from './SRANDMEMBER'; @@ -351,11 +359,25 @@ export default { SETEX, setEx: SETEX, SETNX, - setNx: SETNX, - SETRANGE, - setRange: SETRANGE, + setNx: SETNX, + SINTER, + sInter: SINTER, + SINTERCARD, + sInterCard: SINTERCARD, + SINTERSTORE, + sInterStore: SINTERSTORE, + SISMEMBER, + sIsMember: SISMEMBER, SMEMBERS, sMembers: SMEMBERS, + SMISMEMBER, + smIsMember: SMISMEMBER, + SORT_RO, + sortRo: SORT_RO, + SORT_STORE, + sortStore: SORT_STORE, + SORT, + sort: SORT, SPUBLISH, sPublish: SPUBLISH, SRANDMEMBER_COUNT, From 547132a08060af56fea030653788df323fe90016 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 30 Apr 2023 09:51:29 -0400 Subject: [PATCH 027/325] merge master into v5 --- benchmark/package-lock.json | 142 ++++++++++++++++++++++------------- package-lock.json | 6 +- packages/client/package.json | 2 +- packages/redis/package.json | 4 +- 4 files changed, 97 insertions(+), 57 deletions(-) diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index 4ec89ea2f98..30114847134 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -16,22 +16,26 @@ }, "node_modules/@assemblyscript/loader": { "version": "0.19.23", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz", + "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==" }, "node_modules/@ioredis/commands": { "version": "1.2.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" }, "node_modules/@redis/bloom": { "version": "1.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/client": { - "version": "1.5.6", - "license": "MIT", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz", + "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -43,42 +47,48 @@ }, "node_modules/@redis/graph": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/json": { "version": "1.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/search": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz", + "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/time-series": { "version": "1.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/ansi-regex": { "version": "5.0.1", - "license": "MIT", + "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", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { "color-convert": "^2.0.1" }, @@ -91,6 +101,8 @@ }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -104,12 +116,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/cliui": { "version": "8.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -121,14 +133,16 @@ }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { "node": ">=0.10.0" } }, "node_modules/color-convert": { "version": "2.0.1", - "license": "MIT", + "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" }, @@ -138,11 +152,13 @@ }, "node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/debug": { "version": "4.3.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -157,39 +173,45 @@ }, "node_modules/denque": { "version": "2.1.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "engines": { "node": ">=0.10" } }, "node_modules/emoji-regex": { "version": "8.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/escalade": { "version": "3.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { "node": ">=6" } }, "node_modules/generic-pool": { "version": "3.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "license": "ISC", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/hdr-histogram-js": { "version": "3.0.0", - "license": "BSD", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-3.0.0.tgz", + "integrity": "sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==", "dependencies": { "@assemblyscript/loader": "^0.19.21", "base64-js": "^1.2.0", @@ -200,8 +222,9 @@ } }, "node_modules/ioredis": { - "version": "5.3.1", - "license": "MIT", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", + "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", @@ -223,34 +246,41 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "license": "MIT", + "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/lodash.defaults": { "version": "4.2.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, "node_modules/lodash.isarguments": { "version": "3.1.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" }, "node_modules/ms": { "version": "2.1.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/pako": { "version": "1.0.11", - "license": "(MIT AND Zlib)" + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/redis-commands": { "version": "1.7.0", - "license": "MIT" + "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", - "license": "MIT", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", "engines": { "node": ">=4" } @@ -271,7 +301,8 @@ }, "node_modules/redis-parser": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", "dependencies": { "redis-errors": "^1.0.0" }, @@ -282,7 +313,8 @@ "node_modules/redis-v3": { "name": "redis", "version": "3.1.2", - "license": "MIT", + "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", @@ -299,21 +331,20 @@ }, "node_modules/redis-v3/node_modules/denque": { "version": "1.5.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", "engines": { "node": ">=0.10" } }, "node_modules/redis-v4": { "name": "redis", - "version": "4.6.5", - "license": "MIT", - "workspaces": [ - "./packages/*" - ], + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz", + "integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.6", + "@redis/client": "1.5.7", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", "@redis/search": "1.1.2", @@ -322,18 +353,21 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { "node": ">=0.10.0" } }, "node_modules/standard-as-callback": { "version": "2.1.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" }, "node_modules/string-width": { "version": "4.2.3", - "license": "MIT", + "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", @@ -345,7 +379,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -355,7 +390,8 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -370,18 +406,21 @@ }, "node_modules/y18n": { "version": "5.0.8", - "license": "ISC", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.7.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -397,7 +436,8 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { "node": ">=12" } diff --git a/package-lock.json b/package-lock.json index 7e5c35a257f..50671184fd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8616,7 +8616,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "1.5.6", + "version": "1.5.7", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -8683,11 +8683,11 @@ } }, "packages/redis": { - "version": "4.6.5", + "version": "4.6.6", "license": "MIT", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.6", + "@redis/client": "1.5.7", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", "@redis/search": "1.1.2", diff --git a/packages/client/package.json b/packages/client/package.json index 90f4ebf5e0f..d7c52a20438 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.6", + "version": "1.5.7", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/redis/package.json b/packages/redis/package.json index 461e4808e87..35fc2eb028b 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "4.6.5", + "version": "4.6.6", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -13,7 +13,7 @@ }, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.6", + "@redis/client": "1.5.7", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", "@redis/search": "1.1.2", From 53b9397a7882636eacbb655bda9e0a1ace631b97 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 30 Apr 2023 10:08:25 -0400 Subject: [PATCH 028/325] some more commands --- packages/client/lib/commands/SDIFF.spec.ts | 43 ++-- .../client/lib/commands/SDIFFSTORE.spec.ts | 43 ++-- packages/client/lib/commands/SET.spec.ts | 237 ++++++++++-------- packages/client/lib/commands/SETBIT.spec.ts | 36 ++- packages/client/lib/commands/SETEX.spec.ts | 36 ++- packages/client/lib/commands/SETNX .spec.ts | 36 ++- packages/client/lib/commands/SETRANGE.spec.ts | 36 ++- packages/client/lib/commands/index.ts | 13 +- 8 files changed, 248 insertions(+), 232 deletions(-) diff --git a/packages/client/lib/commands/SDIFF.spec.ts b/packages/client/lib/commands/SDIFF.spec.ts index 340906e9350..8c614a04143 100644 --- a/packages/client/lib/commands/SDIFF.spec.ts +++ b/packages/client/lib/commands/SDIFF.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SDIFF'; +import SDIFF from './SDIFF'; describe('SDIFF', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['SDIFF', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SDIFF.transformArguments('key'), + ['SDIFF', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['SDIFF', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SDIFF.transformArguments(['1', '2']), + ['SDIFF', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sDiff', async client => { - assert.deepEqual( - await client.sDiff('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sDiff', async client => { + assert.deepEqual( + await client.sDiff('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SDIFFSTORE.spec.ts b/packages/client/lib/commands/SDIFFSTORE.spec.ts index 263b4f43f64..27b03266d9b 100644 --- a/packages/client/lib/commands/SDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/SDIFFSTORE.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SDIFFSTORE'; +import SDIFFSTORE from './SDIFFSTORE'; describe('SDIFFSTORE', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('destination', 'key'), - ['SDIFFSTORE', 'destination', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SDIFFSTORE.transformArguments('destination', 'key'), + ['SDIFFSTORE', 'destination', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['SDIFFSTORE', 'destination', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SDIFFSTORE.transformArguments('destination', ['1', '2']), + ['SDIFFSTORE', 'destination', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sDiffStore', async client => { - assert.equal( - await client.sDiffStore('destination', 'key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sDiffStore', async client => { + assert.equal( + await client.sDiffStore('{tag}destination', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SET.spec.ts b/packages/client/lib/commands/SET.spec.ts index 0b3331fd3a4..acd3de046dd 100644 --- a/packages/client/lib/commands/SET.spec.ts +++ b/packages/client/lib/commands/SET.spec.ts @@ -1,129 +1,144 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SET'; +import SET from './SET'; describe('SET', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'value'), - ['SET', 'key', 'value'] - ); - }); - - it('number', () => { - assert.deepEqual( - transformArguments('key', 0), - ['SET', 'key', '0'] - ); - }); + describe('transformArguments', () => { + describe('value', () => { + it('string', () => { + assert.deepEqual( + SET.transformArguments('key', 'value'), + ['SET', 'key', 'value'] + ); + }); + + it('number', () => { + assert.deepEqual( + SET.transformArguments('key', 0), + ['SET', 'key', '0'] + ); + }); + }); - describe('TTL', () => { - it('with EX', () => { - assert.deepEqual( - transformArguments('key', 'value', { - EX: 0 - }), - ['SET', 'key', 'value', 'EX', '0'] - ); - }); + describe('expiration', () => { + it('with expiration', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + expiration: { + type: 'EX', + value: 0 + } + }), + ['SET', 'key', 'value', 'EX', '0'] + ); + }); - it('with PX', () => { - assert.deepEqual( - transformArguments('key', 'value', { - PX: 0 - }), - ['SET', 'key', 'value', 'PX', '0'] - ); - }); + it('with EX (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + EX: 0 + }), + ['SET', 'key', 'value', 'EX', '0'] + ); + }); - it('with EXAT', () => { - assert.deepEqual( - transformArguments('key', 'value', { - EXAT: 0 - }), - ['SET', 'key', 'value', 'EXAT', '0'] - ); - }); + it('with PX (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + PX: 0 + }), + ['SET', 'key', 'value', 'PX', '0'] + ); + }); - it('with PXAT', () => { - assert.deepEqual( - transformArguments('key', 'value', { - PXAT: 0 - }), - ['SET', 'key', 'value', 'PXAT', '0'] - ); - }); + it('with EXAT (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + EXAT: 0 + }), + ['SET', 'key', 'value', 'EXAT', '0'] + ); + }); - it('with KEEPTTL', () => { - assert.deepEqual( - transformArguments('key', 'value', { - KEEPTTL: true - }), - ['SET', 'key', 'value', 'KEEPTTL'] - ); - }); - }); + it('with PXAT (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + PXAT: 0 + }), + ['SET', 'key', 'value', 'PXAT', '0'] + ); + }); - describe('Guards', () => { - it('with NX', () => { - assert.deepEqual( - transformArguments('key', 'value', { - NX: true - }), - ['SET', 'key', 'value', 'NX'] - ); - }); + it('with KEEPTTL (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + KEEPTTL: true + }), + ['SET', 'key', 'value', 'KEEPTTL'] + ); + }); + }); - it('with XX', () => { - assert.deepEqual( - transformArguments('key', 'value', { - XX: true - }), - ['SET', 'key', 'value', 'XX'] - ); - }); - }); + describe('condition', () => { + it('with condition', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + condition: 'NX' + }), + ['SET', 'key', 'value', 'NX'] + ); + }); - it('with GET', () => { - assert.deepEqual( - transformArguments('key', 'value', { - GET: true - }), - ['SET', 'key', 'value', 'GET'] - ); - }); + it('with NX (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + NX: true + }), + ['SET', 'key', 'value', 'NX'] + ); + }); - it('with EX, NX, GET', () => { - assert.deepEqual( - transformArguments('key', 'value', { - EX: 1, - NX: true, - GET: true - }), - ['SET', 'key', 'value', 'EX', '1', 'NX', 'GET'] - ); - }); + it('with XX (backwards compatibility)', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + XX: true + }), + ['SET', 'key', 'value', 'XX'] + ); + }); }); - describe('client.set', () => { - testUtils.testWithClient('simple', async client => { - assert.equal( - await client.set('key', 'value'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + it('with GET', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + GET: true + }), + ['SET', 'key', 'value', 'GET'] + ); + }); - testUtils.testWithClient('with GET on empty key', async client => { - assert.equal( - await client.set('key', 'value', { - GET: true - }), - null - ); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [6, 2] - }); + it('with expiration, condition, GET', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + expiration: { + type: 'EX', + value: 0 + }, + condition: 'NX', + GET: true + }), + ['SET', 'key', 'value', 'EX', '0', 'NX', 'GET'] + ); }); + }); + + testUtils.testAll('set', async client => { + assert.equal( + await client.set('key', 'value'), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SETBIT.spec.ts b/packages/client/lib/commands/SETBIT.spec.ts index 43fbff7c2d9..05b817501ee 100644 --- a/packages/client/lib/commands/SETBIT.spec.ts +++ b/packages/client/lib/commands/SETBIT.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SETBIT'; +import SETBIT from './SETBIT'; describe('SETBIT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 1), - ['SETBIT', 'key', '0', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SETBIT.transformArguments('key', 0, 1), + ['SETBIT', 'key', '0', '1'] + ); + }); - testUtils.testWithClient('client.setBit', async client => { - assert.equal( - await client.setBit('key', 0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.setBit', async cluster => { - assert.equal( - await cluster.setBit('key', 0, 1), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('setBit', async client => { + assert.equal( + await client.setBit('key', 0, 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SETEX.spec.ts b/packages/client/lib/commands/SETEX.spec.ts index bca298c6c04..77034dd915a 100644 --- a/packages/client/lib/commands/SETEX.spec.ts +++ b/packages/client/lib/commands/SETEX.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SETEX'; +import SETEX from './SETEX'; describe('SETEX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1, 'value'), - ['SETEX', 'key', '1', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SETEX.transformArguments('key', 1, 'value'), + ['SETEX', 'key', '1', 'value'] + ); + }); - testUtils.testWithClient('client.setEx', async client => { - assert.equal( - await client.setEx('key', 1, 'value'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.setEx', async cluster => { - assert.equal( - await cluster.setEx('key', 1, 'value'), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('setEx', async client => { + assert.equal( + await client.setEx('key', 1, 'value'), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SETNX .spec.ts b/packages/client/lib/commands/SETNX .spec.ts index c5bdfcffa2c..38ac5c36cf1 100644 --- a/packages/client/lib/commands/SETNX .spec.ts +++ b/packages/client/lib/commands/SETNX .spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SETNX'; +import SETNX from './SETNX'; describe('SETNX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'value'), - ['SETNX', 'key', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SETNX.transformArguments('key', 'value'), + ['SETNX', 'key', 'value'] + ); + }); - testUtils.testWithClient('client.setNX', async client => { - assert.equal( - await client.setNX('key', 'value'), - true - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.setNX', async cluster => { - assert.equal( - await cluster.setNX('key', 'value'), - true - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('setNX', async client => { + assert.equal( + await client.setNX('key', 'value'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SETRANGE.spec.ts b/packages/client/lib/commands/SETRANGE.spec.ts index 398b7730404..5da1f185503 100644 --- a/packages/client/lib/commands/SETRANGE.spec.ts +++ b/packages/client/lib/commands/SETRANGE.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SETRANGE'; +import SETRANGE from './SETRANGE'; describe('SETRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 'value'), - ['SETRANGE', 'key', '0', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SETRANGE.transformArguments('key', 0, 'value'), + ['SETRANGE', 'key', '0', 'value'] + ); + }); - testUtils.testWithClient('client.setRange', async client => { - assert.equal( - await client.setRange('key', 0, 'value'), - 5 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.setRange', async cluster => { - assert.equal( - await cluster.setRange('key', 0, 'value'), - 5 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('setRange', async client => { + assert.equal( + await client.setRange('key', 0, 'value'), + 5 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 1a6faaa4042..54ec095a57a 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -99,7 +99,10 @@ import RPOPLPUSH from './RPOPLPUSH'; import RPUSH from './RPUSH'; import RPUSHX from './RPUSHX'; import SCAN from './SCAN'; +import SDIFF from './SDIFF'; +import SDIFFSTORE from './SDIFFSTORE'; import SET from './SET'; +import SETBIT from './SETBIT'; import SETEX from './SETEX'; import SETNX from './SETNX'; import SETRANGE from './SETRANGE'; @@ -354,12 +357,20 @@ export default { rPushX: RPUSHX, SCAN, scan: SCAN, + SDIFF, + sDiff: SDIFF, + SDIFFSTORE, + sDiffStore: SDIFFSTORE, SET, set: SET, + SETBIT, + setBit: SETBIT, SETEX, setEx: SETEX, SETNX, - setNx: SETNX, + setNX: SETNX, + SETRANGE, + setRange: SETRANGE, SINTER, sInter: SINTER, SINTERCARD, From 88333c01de97f6671ca5c16c65b9355327cef353 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 30 Apr 2023 10:33:05 -0400 Subject: [PATCH 029/325] some more commands --- packages/client/lib/commands/LPOP.spec.ts | 36 ++++---- .../client/lib/commands/LPOP_COUNT.spec.ts | 38 ++++---- packages/client/lib/commands/LPOS.spec.ts | 90 +++++++++---------- .../client/lib/commands/LPOS_COUNT.spec.ts | 90 +++++++++---------- packages/client/lib/commands/LPUSH.spec.ts | 50 +++++------ packages/client/lib/commands/LPUSHX.spec.ts | 50 +++++------ packages/client/lib/commands/LRANGE.spec.ts | 36 ++++---- packages/client/lib/commands/LREM.spec.ts | 36 ++++---- packages/client/lib/commands/LSET.spec.ts | 38 ++++---- packages/client/lib/commands/LTRIM.spec.ts | 36 ++++---- packages/client/lib/commands/LTRIM.ts | 2 +- packages/client/lib/commands/MGET.spec.ts | 36 ++++---- .../client/lib/commands/RANDOMKEY.spec.ts | 26 +++--- packages/client/lib/commands/RENAME.spec.ts | 33 +++---- packages/client/lib/commands/RENAMENX.spec.ts | 31 ++++--- packages/client/lib/commands/RPOP.spec.ts | 36 ++++---- .../client/lib/commands/RPOPLPUSH.spec.ts | 36 ++++---- .../client/lib/commands/RPOP_COUNT.spec.ts | 38 ++++---- packages/client/lib/commands/RPUSH.spec.ts | 50 +++++------ packages/client/lib/commands/RPUSH.ts | 4 +- packages/client/lib/commands/RPUSHX.spec.ts | 50 +++++------ packages/client/lib/commands/RPUSHX.ts | 4 +- packages/client/lib/commands/SADD.spec.ts | 43 ++++----- packages/client/lib/commands/SCARD.spec.ts | 29 +++--- packages/client/lib/commands/index.ts | 21 +++++ 25 files changed, 453 insertions(+), 486 deletions(-) diff --git a/packages/client/lib/commands/LPOP.spec.ts b/packages/client/lib/commands/LPOP.spec.ts index d694fb10588..0e432981a2b 100644 --- a/packages/client/lib/commands/LPOP.spec.ts +++ b/packages/client/lib/commands/LPOP.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPOP'; +import LPOP from './LPOP'; describe('LPOP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['LPOP', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LPOP.transformArguments('key'), + ['LPOP', 'key'] + ); + }); - testUtils.testWithClient('client.lPop', async client => { - assert.equal( - await client.lPop('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lPop', async cluster => { - assert.equal( - await cluster.lPop('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPop', async client => { + assert.equal( + await client.lPop('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LPOP_COUNT.spec.ts b/packages/client/lib/commands/LPOP_COUNT.spec.ts index 9d87fad3862..691af966c56 100644 --- a/packages/client/lib/commands/LPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOP_COUNT.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPOP_COUNT'; +import LPOP_COUNT from './LPOP_COUNT'; describe('LPOP COUNT', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['LPOP', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LPOP_COUNT.transformArguments('key', 1), + ['LPOP', 'key', '1'] + ); + }); - testUtils.testWithClient('client.lPopCount', async client => { - assert.equal( - await client.lPopCount('key', 1), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lPopCount', async cluster => { - assert.equal( - await cluster.lPopCount('key', 1), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPopCount', async client => { + assert.equal( + await client.lPopCount('key', 1), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LPOS.spec.ts b/packages/client/lib/commands/LPOS.spec.ts index 6b6050f2c3b..21c8a630f54 100644 --- a/packages/client/lib/commands/LPOS.spec.ts +++ b/packages/client/lib/commands/LPOS.spec.ts @@ -1,58 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPOS'; +import LPOS from './LPOS'; describe('LPOS', () => { - testUtils.isVersionGreaterThanHook([6, 0, 6]); + testUtils.isVersionGreaterThanHook([6, 0, 6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'element'), - ['LPOS', 'key', 'element'] - ); - }); - - it('with RANK', () => { - assert.deepEqual( - transformArguments('key', 'element', { - RANK: 0 - }), - ['LPOS', 'key', 'element', 'RANK', '0'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + LPOS.transformArguments('key', 'element'), + ['LPOS', 'key', 'element'] + ); + }); - it('with MAXLEN', () => { - assert.deepEqual( - transformArguments('key', 'element', { - MAXLEN: 10 - }), - ['LPOS', 'key', 'element', 'MAXLEN', '10'] - ); - }); + it('with RANK', () => { + assert.deepEqual( + LPOS.transformArguments('key', 'element', { + RANK: 0 + }), + ['LPOS', 'key', 'element', 'RANK', '0'] + ); + }); - it('with RANK, MAXLEN', () => { - assert.deepEqual( - transformArguments('key', 'element', { - RANK: 0, - MAXLEN: 10 - }), - ['LPOS', 'key', 'element', 'RANK', '0', 'MAXLEN', '10'] - ); - }); + it('with MAXLEN', () => { + assert.deepEqual( + LPOS.transformArguments('key', 'element', { + MAXLEN: 10 + }), + ['LPOS', 'key', 'element', 'MAXLEN', '10'] + ); }); - testUtils.testWithClient('client.lPos', async client => { - assert.equal( - await client.lPos('key', 'element'), - null - ); - }, GLOBAL.SERVERS.OPEN); + it('with RANK, MAXLEN', () => { + assert.deepEqual( + LPOS.transformArguments('key', 'element', { + RANK: 0, + MAXLEN: 10 + }), + ['LPOS', 'key', 'element', 'RANK', '0', 'MAXLEN', '10'] + ); + }); + }); - testUtils.testWithCluster('cluster.lPos', async cluster => { - assert.equal( - await cluster.lPos('key', 'element'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPos', async client => { + assert.equal( + await client.lPos('key', 'element'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LPOS_COUNT.spec.ts b/packages/client/lib/commands/LPOS_COUNT.spec.ts index 4b01f2f59b9..111323c55d8 100644 --- a/packages/client/lib/commands/LPOS_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOS_COUNT.spec.ts @@ -1,58 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPOS_COUNT'; +import LPOS_COUNT from './LPOS_COUNT'; describe('LPOS COUNT', () => { - testUtils.isVersionGreaterThanHook([6, 0, 6]); + testUtils.isVersionGreaterThanHook([6, 0, 6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'element', 0), - ['LPOS', 'key', 'element', 'COUNT', '0'] - ); - }); - - it('with RANK', () => { - assert.deepEqual( - transformArguments('key', 'element', 0, { - RANK: 0 - }), - ['LPOS', 'key', 'element', 'RANK', '0', 'COUNT', '0'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + LPOS_COUNT.transformArguments('key', 'element', 0), + ['LPOS', 'key', 'element', 'COUNT', '0'] + ); + }); - it('with MAXLEN', () => { - assert.deepEqual( - transformArguments('key', 'element', 0, { - MAXLEN: 10 - }), - ['LPOS', 'key', 'element', 'COUNT', '0', 'MAXLEN', '10'] - ); - }); + it('with RANK', () => { + assert.deepEqual( + LPOS_COUNT.transformArguments('key', 'element', 0, { + RANK: 0 + }), + ['LPOS', 'key', 'element', 'RANK', '0', 'COUNT', '0'] + ); + }); - it('with RANK, MAXLEN', () => { - assert.deepEqual( - transformArguments('key', 'element', 0, { - RANK: 0, - MAXLEN: 10 - }), - ['LPOS', 'key', 'element', 'RANK', '0', 'COUNT', '0', 'MAXLEN', '10'] - ); - }); + it('with MAXLEN', () => { + assert.deepEqual( + LPOS_COUNT.transformArguments('key', 'element', 0, { + MAXLEN: 10 + }), + ['LPOS', 'key', 'element', 'COUNT', '0', 'MAXLEN', '10'] + ); }); - testUtils.testWithClient('client.lPosCount', async client => { - assert.deepEqual( - await client.lPosCount('key', 'element', 0), - [] - ); - }, GLOBAL.SERVERS.OPEN); + it('with RANK, MAXLEN', () => { + assert.deepEqual( + LPOS_COUNT.transformArguments('key', 'element', 0, { + RANK: 0, + MAXLEN: 10 + }), + ['LPOS', 'key', 'element', 'RANK', '0', 'COUNT', '0', 'MAXLEN', '10'] + ); + }); + }); - testUtils.testWithCluster('cluster.lPosCount', async cluster => { - assert.deepEqual( - await cluster.lPosCount('key', 'element', 0), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPosCount', async client => { + assert.deepEqual( + await client.lPosCount('key', 'element', 0), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LPUSH.spec.ts b/packages/client/lib/commands/LPUSH.spec.ts index b5b1f5084eb..7ed3262ed28 100644 --- a/packages/client/lib/commands/LPUSH.spec.ts +++ b/packages/client/lib/commands/LPUSH.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPUSH'; +import LPUSH from './LPUSH'; describe('LPUSH', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['LPUSH', 'key', 'field'] - ); - }); - - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['LPUSH', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + LPUSH.transformArguments('key', 'field'), + ['LPUSH', 'key', 'field'] + ); }); - testUtils.testWithClient('client.lPush', async client => { - assert.equal( - await client.lPush('key', 'field'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + it('array', () => { + assert.deepEqual( + LPUSH.transformArguments('key', ['1', '2']), + ['LPUSH', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.lPush', async cluster => { - assert.equal( - await cluster.lPush('key', 'field'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPush', async client => { + assert.equal( + await client.lPush('key', 'field'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LPUSHX.spec.ts b/packages/client/lib/commands/LPUSHX.spec.ts index d978e5a588f..8cbe89e31b0 100644 --- a/packages/client/lib/commands/LPUSHX.spec.ts +++ b/packages/client/lib/commands/LPUSHX.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LPUSHX'; +import LPUSHX from './LPUSHX'; describe('LPUSHX', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'element'), - ['LPUSHX', 'key', 'element'] - ); - }); - - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['LPUSHX', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + LPUSHX.transformArguments('key', 'element'), + ['LPUSHX', 'key', 'element'] + ); }); - testUtils.testWithClient('client.lPushX', async client => { - assert.equal( - await client.lPushX('key', 'element'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + it('array', () => { + assert.deepEqual( + LPUSHX.transformArguments('key', ['1', '2']), + ['LPUSHX', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.lPushX', async cluster => { - assert.equal( - await cluster.lPushX('key', 'element'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lPushX', async client => { + assert.equal( + await client.lPushX('key', 'element'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LRANGE.spec.ts b/packages/client/lib/commands/LRANGE.spec.ts index dffe6087b80..12f0c8f7b9d 100644 --- a/packages/client/lib/commands/LRANGE.spec.ts +++ b/packages/client/lib/commands/LRANGE.spec.ts @@ -1,27 +1,23 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LRANGE'; +import LRANGE from './LRANGE'; describe('LRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, -1), - ['LRANGE', 'key', '0', '-1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LRANGE.transformArguments('key', 0, -1), + ['LRANGE', 'key', '0', '-1'] + ); + }); - testUtils.testWithClient('client.lRange', async client => { - assert.deepEqual( - await client.lRange('key', 0, -1), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lRange', async cluster => { - assert.deepEqual( - await cluster.lRange('key', 0, -1), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lRange', async client => { + assert.deepEqual( + await client.lRange('key', 0, -1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LREM.spec.ts b/packages/client/lib/commands/LREM.spec.ts index 3405f4beb07..bbc3f6096e9 100644 --- a/packages/client/lib/commands/LREM.spec.ts +++ b/packages/client/lib/commands/LREM.spec.ts @@ -1,27 +1,23 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LREM'; +import LREM from './LREM'; describe('LREM', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 'element'), - ['LREM', 'key', '0', 'element'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LREM.transformArguments('key', 0, 'element'), + ['LREM', 'key', '0', 'element'] + ); + }); - testUtils.testWithClient('client.lRem', async client => { - assert.equal( - await client.lRem('key', 0, 'element'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lRem', async cluster => { - assert.equal( - await cluster.lRem('key', 0, 'element'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lRem', async client => { + assert.equal( + await client.lRem('key', 0, 'element'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LSET.spec.ts b/packages/client/lib/commands/LSET.spec.ts index d7241032cc6..0d34331603b 100644 --- a/packages/client/lib/commands/LSET.spec.ts +++ b/packages/client/lib/commands/LSET.spec.ts @@ -1,28 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LSET'; +import LSET from './LSET'; describe('LSET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 'element'), - ['LSET', 'key', '0', 'element'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LSET.transformArguments('key', 0, 'element'), + ['LSET', 'key', '0', 'element'] + ); + }); - testUtils.testWithClient('client.lSet', async client => { - await client.lPush('key', 'element'); - assert.equal( - await client.lSet('key', 0, 'element'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lSet', async cluster => { - await cluster.lPush('key', 'element'); - assert.equal( - await cluster.lSet('key', 0, 'element'), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lSet', async client => { + assert.equal( + await client.lSet('key', 0, 'element'), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LTRIM.spec.ts b/packages/client/lib/commands/LTRIM.spec.ts index 5b6ac5d3660..df151d2ddb5 100644 --- a/packages/client/lib/commands/LTRIM.spec.ts +++ b/packages/client/lib/commands/LTRIM.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LTRIM'; +import LTRIM from './LTRIM'; describe('LTRIM', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, -1), - ['LTRIM', 'key', '0', '-1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LTRIM.transformArguments('key', 0, -1), + ['LTRIM', 'key', '0', '-1'] + ); + }); - testUtils.testWithClient('client.lTrim', async client => { - assert.equal( - await client.lTrim('key', 0, -1), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lTrim', async cluster => { - assert.equal( - await cluster.lTrim('key', 0, -1), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lTrim', async client => { + assert.equal( + await client.lTrim('key', 0, -1), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LTRIM.ts b/packages/client/lib/commands/LTRIM.ts index d4c69513165..79377ed1d5b 100644 --- a/packages/client/lib/commands/LTRIM.ts +++ b/packages/client/lib/commands/LTRIM.ts @@ -5,7 +5,7 @@ export default { transformArguments( key: RedisArgument, start: number, - stop: RedisArgument + stop: number ) { return [ 'LREM', diff --git a/packages/client/lib/commands/MGET.spec.ts b/packages/client/lib/commands/MGET.spec.ts index 9ff47895f4e..b9fa49bbdd6 100644 --- a/packages/client/lib/commands/MGET.spec.ts +++ b/packages/client/lib/commands/MGET.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MGET'; +import MGET from './MGET'; describe('MGET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['MGET', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MGET.transformArguments(['1', '2']), + ['MGET', '1', '2'] + ); + }); - testUtils.testWithClient('client.mGet', async client => { - assert.deepEqual( - await client.mGet(['key']), - [null] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.mGet', async cluster => { - assert.deepEqual( - await cluster.mGet(['key']), - [null] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('mGet', async client => { + assert.deepEqual( + await client.mGet(['key']), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RANDOMKEY.spec.ts b/packages/client/lib/commands/RANDOMKEY.spec.ts index 81c42b2fd83..8cd74669c55 100644 --- a/packages/client/lib/commands/RANDOMKEY.spec.ts +++ b/packages/client/lib/commands/RANDOMKEY.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RANDOMKEY'; +import RANDOMKEY from './RANDOMKEY'; describe('RANDOMKEY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['RANDOMKEY'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RANDOMKEY.transformArguments(), + ['RANDOMKEY'] + ); + }); - testUtils.testWithClient('client.randomKey', async client => { - assert.equal( - await client.randomKey(), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.randomKey', async client => { + assert.equal( + await client.randomKey(), + null + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/RENAME.spec.ts b/packages/client/lib/commands/RENAME.spec.ts index 49e0af600f6..d0d16115ea3 100644 --- a/packages/client/lib/commands/RENAME.spec.ts +++ b/packages/client/lib/commands/RENAME.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RENAME'; +import RENAME from './RENAME'; describe('RENAME', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('from', 'to'), - ['RENAME', 'from', 'to'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RENAME.transformArguments('source', 'destination'), + ['RENAME', 'source', 'destination'] + ); + }); - testUtils.testWithClient('client.rename', async client => { - await client.set('from', 'value'); - - assert.equal( - await client.rename('from', 'to'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('rename', async client => { + const [, reply] = await Promise.all([ + client.set('{tag}source', 'value'), + client.rename('{tag}source', '{tag}destination') + ]); + + assert.equal(reply, 'OK'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RENAMENX.spec.ts b/packages/client/lib/commands/RENAMENX.spec.ts index 6345eb5bd09..da1e0c4b480 100644 --- a/packages/client/lib/commands/RENAMENX.spec.ts +++ b/packages/client/lib/commands/RENAMENX.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RENAMENX'; +import RENAMENX from './RENAMENX'; describe('RENAMENX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('from', 'to'), - ['RENAMENX', 'from', 'to'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RENAMENX.transformArguments('source', 'destination'), + ['RENAMENX', 'source', 'destination'] + ); + }); - testUtils.testWithClient('client.renameNX', async client => { - await client.set('from', 'value'); + testUtils.testAll('renameNX', async client => { + const [, reply] = await Promise.all([ + client.set('{tag}source', 'value'), + client.renameNX('{tag}source', '{tag}destination') + ]); - assert.equal( - await client.renameNX('from', 'to'), - true - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPOP.spec.ts b/packages/client/lib/commands/RPOP.spec.ts index 6e57afa3216..d22dadccd3d 100644 --- a/packages/client/lib/commands/RPOP.spec.ts +++ b/packages/client/lib/commands/RPOP.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RPOP'; +import RPOP from './RPOP'; describe('RPOP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['RPOP', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RPOP.transformArguments('key'), + ['RPOP', 'key'] + ); + }); - testUtils.testWithClient('client.rPop', async client => { - assert.equal( - await client.rPop('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.rPop', async cluster => { - assert.equal( - await cluster.rPop('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('rPop', async client => { + assert.equal( + await client.rPop('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPOPLPUSH.spec.ts b/packages/client/lib/commands/RPOPLPUSH.spec.ts index cef3049bd91..bb045168bf8 100644 --- a/packages/client/lib/commands/RPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/RPOPLPUSH.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RPOPLPUSH'; +import RPOPLPUSH from './RPOPLPUSH'; describe('RPOPLPUSH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination'), - ['RPOPLPUSH', 'source', 'destination'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RPOPLPUSH.transformArguments('source', 'destination'), + ['RPOPLPUSH', 'source', 'destination'] + ); + }); - testUtils.testWithClient('client.rPopLPush', async client => { - assert.equal( - await client.rPopLPush('source', 'destination'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.rPopLPush', async cluster => { - assert.equal( - await cluster.rPopLPush('{tag}source', '{tag}destination'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('rPopLPush', async client => { + assert.equal( + await client.rPopLPush('{tag}source', '{tag}destination'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPOP_COUNT.spec.ts b/packages/client/lib/commands/RPOP_COUNT.spec.ts index 3657a608039..03ede55d6b1 100644 --- a/packages/client/lib/commands/RPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/RPOP_COUNT.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RPOP_COUNT'; +import RPOP_COUNT from './RPOP_COUNT'; describe('RPOP COUNT', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['RPOP', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RPOP_COUNT.transformArguments('key', 1), + ['RPOP', 'key', '1'] + ); + }); - testUtils.testWithClient('client.rPopCount', async client => { - assert.equal( - await client.rPopCount('key', 1), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.rPopCount', async cluster => { - assert.equal( - await cluster.rPopCount('key', 1), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('rPopCount', async client => { + assert.equal( + await client.rPopCount('key', 1), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPUSH.spec.ts b/packages/client/lib/commands/RPUSH.spec.ts index afa5c1c6400..0e860b3454f 100644 --- a/packages/client/lib/commands/RPUSH.spec.ts +++ b/packages/client/lib/commands/RPUSH.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RPUSH'; +import RPUSH from './RPUSH'; describe('RPUSH', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'element'), - ['RPUSH', 'key', 'element'] - ); - }); - - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['RPUSH', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + RPUSH.transformArguments('key', 'element'), + ['RPUSH', 'key', 'element'] + ); }); - testUtils.testWithClient('client.rPush', async client => { - assert.equal( - await client.rPush('key', 'element'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + it('array', () => { + assert.deepEqual( + RPUSH.transformArguments('key', ['1', '2']), + ['RPUSH', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.rPush', async cluster => { - assert.equal( - await cluster.rPush('key', 'element'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('rPush', async client => { + assert.equal( + await client.rPush('key', 'element'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPUSH.ts b/packages/client/lib/commands/RPUSH.ts index 6dca8c81ce3..4b048777389 100644 --- a/packages/client/lib/commands/RPUSH.ts +++ b/packages/client/lib/commands/RPUSH.ts @@ -1,11 +1,11 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, transformArguments( key: RedisArgument, - element: RedisArgument + element: RedisVariadicArgument ) { return pushVariadicArguments(['RPUSH', key], element); }, diff --git a/packages/client/lib/commands/RPUSHX.spec.ts b/packages/client/lib/commands/RPUSHX.spec.ts index ee2041de6f2..a8bd46d07c7 100644 --- a/packages/client/lib/commands/RPUSHX.spec.ts +++ b/packages/client/lib/commands/RPUSHX.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RPUSHX'; +import RPUSHX from './RPUSHX'; describe('RPUSHX', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'element'), - ['RPUSHX', 'key', 'element'] - ); - }); - - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['RPUSHX', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + RPUSHX.transformArguments('key', 'element'), + ['RPUSHX', 'key', 'element'] + ); }); - testUtils.testWithClient('client.rPushX', async client => { - assert.equal( - await client.rPushX('key', 'element'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + it('array', () => { + assert.deepEqual( + RPUSHX.transformArguments('key', ['1', '2']), + ['RPUSHX', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.rPushX', async cluster => { - assert.equal( - await cluster.rPushX('key', 'element'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('rPushX', async client => { + assert.equal( + await client.rPushX('key', 'element'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/RPUSHX.ts b/packages/client/lib/commands/RPUSHX.ts index ce38ba6b5fd..00b29624b0d 100644 --- a/packages/client/lib/commands/RPUSHX.ts +++ b/packages/client/lib/commands/RPUSHX.ts @@ -1,11 +1,11 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, transformArguments( key: RedisArgument, - element: RedisArgument + element: RedisVariadicArgument ) { return pushVariadicArguments(['RPUSHX', key], element); }, diff --git a/packages/client/lib/commands/SADD.spec.ts b/packages/client/lib/commands/SADD.spec.ts index 4533f6f9ad5..5496c003537 100644 --- a/packages/client/lib/commands/SADD.spec.ts +++ b/packages/client/lib/commands/SADD.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SADD'; +import SADD from './SADD'; describe('SADD', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['SADD', 'key', 'member'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SADD.transformArguments('key', 'member'), + ['SADD', 'key', 'member'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['SADD', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SADD.transformArguments('key', ['1', '2']), + ['SADD', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.sAdd', async client => { - assert.equal( - await client.sAdd('key', 'member'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sAdd', async client => { + assert.equal( + await client.sAdd('key', 'member'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/SCARD.spec.ts b/packages/client/lib/commands/SCARD.spec.ts index afc21c6b00c..2d6ba32c6d5 100644 --- a/packages/client/lib/commands/SCARD.spec.ts +++ b/packages/client/lib/commands/SCARD.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SCARD'; +import SCARD from './SCARD'; describe('SCARD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['SCARD', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SCARD.transformArguments('key'), + ['SCARD', 'key'] + ); + }); - testUtils.testWithClient('client.sCard', async client => { - assert.equal( - await client.sCard('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('sCard', async client => { + assert.equal( + await client.sCard('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 54ec095a57a..04e1f44b096 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -78,7 +78,9 @@ import LINSERT from './LINSERT'; import LLEN from './LLEN'; import LMOVE from './LMOVE'; import LMPOP from './LMPOP'; +import LPOP_COUNT from './LPOP_COUNT'; import LPOP from './LPOP'; +import LPOS_COUNT from './LPOS_COUNT'; import LPOS from './LPOS'; import LPUSH from './LPUSH'; import LPUSHX from './LPUSHX'; @@ -94,11 +96,16 @@ import PFCOUNT from './PFCOUNT'; import PFMERGE from './PFMERGE'; import PING from './PING'; import PSETEX from './PSETEX'; +import RENAME from './RENAME'; +import RENAMENX from './RENAMENX'; +import RPOP_COUNT from './RPOP_COUNT'; import RPOP from './RPOP'; import RPOPLPUSH from './RPOPLPUSH'; import RPUSH from './RPUSH'; import RPUSHX from './RPUSHX'; +import SADD from './SADD'; import SCAN from './SCAN'; +import SCARD from './SCARD'; import SDIFF from './SDIFF'; import SDIFFSTORE from './SDIFFSTORE'; import SET from './SET'; @@ -312,8 +319,12 @@ export default { lMove: LMOVE, LMPOP, lmPop: LMPOP, + LPOP_COUNT, + lPopCount: LPOP_COUNT, LPOP, lPop: LPOP, + LPOS_COUNT, + lPosCount: LPOS_COUNT, LPOS, lPos: LPOS, LPUSH, @@ -347,6 +358,12 @@ export default { ping: PING, PSETEX, pSetEx: PSETEX, + RENAME, + rename: RENAME, + RENAMENX, + renameNX: RENAMENX, + RPOP_COUNT, + rPopCount: RPOP_COUNT, RPOP, rPop: RPOP, RPOPLPUSH, @@ -355,8 +372,12 @@ export default { rPush: RPUSH, RPUSHX, rPushX: RPUSHX, + SADD, + sAdd: SADD, SCAN, scan: SCAN, + SCARD, + sCard: SCARD, SDIFF, sDiff: SDIFF, SDIFFSTORE, From e04609cc3ae76558a787bf0a77c1910344429d3f Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 30 Apr 2023 10:46:43 -0400 Subject: [PATCH 030/325] WIP --- packages/client/index.ts | 1 + packages/client/lib/RESP/decoder.ts | 86 ++--- packages/client/lib/RESP/types.ts | 60 ++-- packages/client/lib/client/commands-queue.ts | 6 +- packages/client/test.mjs | 338 ------------------- 5 files changed, 77 insertions(+), 414 deletions(-) delete mode 100644 packages/client/test.mjs diff --git a/packages/client/index.ts b/packages/client/index.ts index 7bb2f239469..c9b93f3377b 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -1,4 +1,5 @@ export { RedisModules, RedisFunctions, RedisScripts, RespVersions } from './lib/RESP/types'; +export { RESP_TYPES } from './lib/RESP/decoder'; export { VerbatimString } from './lib/RESP/verbatim-string'; export { defineScript } from './lib/lua-script'; // export * from './lib/errors'; diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 49f04a2191b..afac0356a4c 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -4,7 +4,7 @@ import { SimpleError, BlobError, ErrorReply } from '../errors'; import { Flags } from './types'; // https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md -export const TYPES = { +export const RESP_TYPES = { NULL: 95, // _ BOOLEAN: 35, // # NUMBER: 58, // : @@ -35,7 +35,7 @@ const ASCII = { } as const; export const PUSH_FLAGS = { - [TYPES.BLOB_STRING]: Buffer + [RESP_TYPES.BLOB_STRING]: Buffer }; // this was written with performance in mind, so it's not very readable... sorry :( @@ -98,98 +98,98 @@ export class Decoder { private _decodeTypeValue(type, chunk) { switch (type) { - case TYPES.NULL: + case RESP_TYPES.NULL: this._config.onReply(this._decodeNull()); return false; - case TYPES.BOOLEAN: + case RESP_TYPES.BOOLEAN: return this._handleDecodedValue( this._config.onReply, this._decodeBoolean(chunk) ); - case TYPES.NUMBER: + case RESP_TYPES.NUMBER: return this._handleDecodedValue( this._config.onReply, this._decodeNumber(chunk) ); - case TYPES.BIG_NUMBER: + case RESP_TYPES.BIG_NUMBER: return this._handleDecodedValue( this._config.onReply, this._decodeBigNumber( - this._config.getFlags()[TYPES.BIG_NUMBER], + this._config.getFlags()[RESP_TYPES.BIG_NUMBER], chunk ) ); - case TYPES.DOUBLE: + case RESP_TYPES.DOUBLE: return this._handleDecodedValue( this._config.onReply, this._decodeDouble( - this._config.getFlags()[TYPES.DOUBLE], + this._config.getFlags()[RESP_TYPES.DOUBLE], chunk ) ); - case TYPES.SIMPLE_STRING: + case RESP_TYPES.SIMPLE_STRING: return this._handleDecodedValue( this._config.onReply, this._decodeSimpleString( - this._config.getFlags()[TYPES.SIMPLE_STRING], + this._config.getFlags()[RESP_TYPES.SIMPLE_STRING], chunk ) ); - case TYPES.BLOB_STRING: + case RESP_TYPES.BLOB_STRING: return this._handleDecodedValue( this._config.onReply, this._decodeBlobString( - this._config.getFlags()[TYPES.BLOB_STRING], + this._config.getFlags()[RESP_TYPES.BLOB_STRING], chunk ) ); - case TYPES.VERBATIM_STRING: + case RESP_TYPES.VERBATIM_STRING: return this._handleDecodedValue( this._config.onReply, this._decodeVerbatimString( - this._config.getFlags()[TYPES.VERBATIM_STRING], + this._config.getFlags()[RESP_TYPES.VERBATIM_STRING], chunk ) ); - case TYPES.SIMPLE_ERROR: + case RESP_TYPES.SIMPLE_ERROR: return this._handleDecodedValue( this._config.onErrorReply, this._decodeSimpleError(chunk) ); - case TYPES.BLOB_ERROR: + case RESP_TYPES.BLOB_ERROR: return this._handleDecodedValue( this._config.onErrorReply, this._decodeBlobError(chunk) ); - case TYPES.ARRAY: + case RESP_TYPES.ARRAY: return this._handleDecodedValue( this._config.onReply, this._decodeArray(this._config.getFlags(), chunk) ); - case TYPES.SET: + case RESP_TYPES.SET: return this._handleDecodedValue( this._config.onReply, this._decodeSet(this._config.getFlags(), chunk) ); - case TYPES.MAP: + case RESP_TYPES.MAP: return this._handleDecodedValue( this._config.onReply, this._decodeMap(this._config.getFlags(), chunk) ); - case TYPES.PUSH: + case RESP_TYPES.PUSH: return this._handleDecodedValue( this._config.onPush, this._decodeArray(PUSH_FLAGS, chunk) @@ -664,43 +664,43 @@ export class Decoder { private _decodeNestedTypeValue(type, flags, chunk) { switch (type) { - case TYPES.NULL: + case RESP_TYPES.NULL: return this._decodeNull(); - case TYPES.BOOLEAN: + case RESP_TYPES.BOOLEAN: return this._decodeBoolean(chunk); - case TYPES.NUMBER: + case RESP_TYPES.NUMBER: return this._decodeNumber(chunk); - case TYPES.BIG_NUMBER: - return this._decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk); + case RESP_TYPES.BIG_NUMBER: + return this._decodeBigNumber(flags[RESP_TYPES.BIG_NUMBER], chunk); - case TYPES.DOUBLE: - return this._decodeDouble(flags[TYPES.DOUBLE], chunk); + case RESP_TYPES.DOUBLE: + return this._decodeDouble(flags[RESP_TYPES.DOUBLE], chunk); - case TYPES.SIMPLE_STRING: - return this._decodeSimpleString(flags[TYPES.SIMPLE_STRING], chunk); + case RESP_TYPES.SIMPLE_STRING: + return this._decodeSimpleString(flags[RESP_TYPES.SIMPLE_STRING], chunk); - case TYPES.BLOB_STRING: - return this._decodeBlobString(flags[TYPES.BLOB_STRING], chunk); + case RESP_TYPES.BLOB_STRING: + return this._decodeBlobString(flags[RESP_TYPES.BLOB_STRING], chunk); - case TYPES.VERBATIM_STRING: - return this._decodeVerbatimString(flags[TYPES.VERBATIM_STRING], chunk); + case RESP_TYPES.VERBATIM_STRING: + return this._decodeVerbatimString(flags[RESP_TYPES.VERBATIM_STRING], chunk); - case TYPES.SIMPLE_ERROR: + case RESP_TYPES.SIMPLE_ERROR: return this._decodeSimpleError(chunk); - case TYPES.BLOB_ERROR: + case RESP_TYPES.BLOB_ERROR: return this._decodeBlobError(chunk); - case TYPES.ARRAY: + case RESP_TYPES.ARRAY: return this._decodeArray(flags, chunk); - case TYPES.SET: + case RESP_TYPES.SET: return this._decodeSet(flags, chunk); - case TYPES.MAP: + case RESP_TYPES.MAP: return this._decodeMap(flags, chunk); } } @@ -805,7 +805,7 @@ export class Decoder { } private _decodeSetItems(length, flags, chunk) { - return flags[TYPES.SET] === Set ? + return flags[RESP_TYPES.SET] === Set ? this._decodeSetAsSet( new Set(), length, @@ -888,7 +888,7 @@ export class Decoder { } private _decodeMapItems(length, flags, chunk) { - switch (flags[TYPES.MAP]) { + switch (flags[RESP_TYPES.MAP]) { case Map: return this._decodeMapAsMap( new Map(), @@ -978,11 +978,11 @@ export class Decoder { private _decodeMapKeyValue(type, flags, chunk) { switch (type) { // decode simple string map key as string (and not as buffer) - case TYPES.SIMPLE_STRING: + case RESP_TYPES.SIMPLE_STRING: return this._decodeSimpleString(String, chunk); // decode blob string map key as string (and not as buffer) - case TYPES.BLOB_STRING: + case RESP_TYPES.BLOB_STRING: return this._decodeBlobString(String, chunk); default: diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 88ca88606d9..d6b11db72b6 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -1,13 +1,13 @@ import { RedisScriptConfig, SHA1 } from '../lua-script'; -import { TYPES } from './decoder'; +import { RESP_TYPES } from './decoder'; import { VerbatimString } from './verbatim-string'; -export type RespTypes = typeof TYPES; +export type RESP_TYPES = typeof RESP_TYPES; -export type RespTypesUnion = RespTypes[keyof RespTypes]; +export type RespTypes = RESP_TYPES[keyof RESP_TYPES]; type RespType< - RESP_TYPE extends RespTypesUnion, + RESP_TYPE extends RespTypes, DEFAULT, TYPES = never, FLAG_TYPES = DEFAULT | TYPES @@ -19,19 +19,19 @@ type RespType< }; export type NullReply = RespType< - RespTypes['NULL'], + RESP_TYPES['NULL'], null >; export type BooleanReply< T extends boolean = boolean > = RespType< - RespTypes['BOOLEAN'], + RESP_TYPES['BOOLEAN'], T >; export type NumberReply< T extends number = number > = RespType< - RespTypes['NUMBER'], + RESP_TYPES['NUMBER'], T, `${T}`, number | string @@ -39,7 +39,7 @@ export type NumberReply< export type BigNumberReply< T extends bigint = bigint > = RespType< - RespTypes['BIG_NUMBER'], + RESP_TYPES['BIG_NUMBER'], T, number | `${T}`, bigint | number | string @@ -47,7 +47,7 @@ export type BigNumberReply< export type DoubleReply< T extends number = number > = RespType< - RespTypes['DOUBLE'], + RESP_TYPES['DOUBLE'], T, `${T}`, number | string @@ -55,7 +55,7 @@ export type DoubleReply< export type SimpleStringReply< T extends string = string > = RespType< - RespTypes['SIMPLE_STRING'], + RESP_TYPES['SIMPLE_STRING'], T, Buffer, string | Buffer @@ -63,7 +63,7 @@ export type SimpleStringReply< export type BlobStringReply< T extends string = string > = RespType< - RespTypes['BLOB_STRING'], + RESP_TYPES['BLOB_STRING'], T, Buffer, string | Buffer @@ -71,39 +71,39 @@ export type BlobStringReply< export type VerbatimStringReply< T extends string = string > = RespType< - RespTypes['VERBATIM_STRING'], + RESP_TYPES['VERBATIM_STRING'], T, Buffer | VerbatimString, string | Buffer | VerbatimString >; export type SimpleErrorReply = RespType< - RespTypes['SIMPLE_ERROR'], + RESP_TYPES['SIMPLE_ERROR'], Buffer >; export type BlobErrorReply = RespType< - RespTypes['BLOB_ERROR'], + RESP_TYPES['BLOB_ERROR'], Buffer >; export type ArrayReply = RespType< - RespTypes['ARRAY'], + RESP_TYPES['ARRAY'], Array, never, Array >; export type TuplesReply]> = RespType< - RespTypes['ARRAY'], + RESP_TYPES['ARRAY'], T, never, Array >; export type SetReply = RespType< - RespTypes['SET'], + RESP_TYPES['SET'], Array, Set, Array | Set >; export type MapReply = RespType< - RespTypes['MAP'], + RESP_TYPES['MAP'], { [key: string]: V }, Map | Array, Map | Array @@ -114,7 +114,7 @@ type MapKeyValue = [key: BlobStringReply, value: unknown]; type MapTuples = Array; export type TuplesToMapReply = RespType< - RespTypes['MAP'], + RESP_TYPES['MAP'], { [P in T[number] as P[0] extends BlobStringReply ? S : never]: P[1]; }, @@ -134,16 +134,16 @@ type FlattenTuples = ( export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply | // cannot reuse ArrayReply, SetReply and MapReply because of circular reference RespType< - RespTypes['ARRAY'], + RESP_TYPES['ARRAY'], Array > | RespType< - RespTypes['SET'], + RESP_TYPES['SET'], Array, Set > | RespType< - RespTypes['MAP'], + RESP_TYPES['MAP'], { [key: string]: ReplyUnion }, Map | Array >; @@ -152,10 +152,10 @@ export type Reply = ReplyWithFlags; export type Flag = ((...args: any) => T) | (new (...args: any) => T); -type RespTypeUnion = T extends RespType ? FLAG_TYPES : never; +type RespTypeUnion = T extends RespType ? FLAG_TYPES : never; export type Flags = { - [P in RespTypesUnion]?: Flag>>>; + [P in RespTypes]?: Flag>>>; }; type MapKey< @@ -163,8 +163,8 @@ type MapKey< FLAGS extends Flags > = ReplyWithFlags; export type ReplyWithFlags< @@ -299,13 +299,13 @@ type Resp2Array = ( export type Resp2Reply = ( RESP3REPLY extends RespType ? // TODO: RESP3 only scalar types - RESP_TYPE extends RespTypes['DOUBLE'] ? BlobStringReply : - RESP_TYPE extends RespTypes['ARRAY'] | RespTypes['SET'] ? RespType< + RESP_TYPE extends RESP_TYPES['DOUBLE'] ? BlobStringReply : + RESP_TYPE extends RESP_TYPES['ARRAY'] | RESP_TYPES['SET'] ? RespType< RESP_TYPE, Resp2Array > : - RESP_TYPE extends RespTypes['MAP'] ? RespType< - RespTypes['ARRAY'], + RESP_TYPE extends RESP_TYPES['MAP'] ? RespType< + RESP_TYPES['ARRAY'], Resp2Array>> > : RespType< diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 9d215799e0a..69ba57425a6 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,6 +1,6 @@ import * as LinkedList from 'yallist'; import encodeCommand from '../RESP/encoder'; -import { Decoder, PUSH_FLAGS, TYPES } from '../RESP/decoder'; +import { Decoder, PUSH_FLAGS, RESP_TYPES } from '../RESP/decoder'; import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; @@ -32,7 +32,7 @@ const PONG = Buffer.from('pong'); const RESP2_PUSH_FLAGS = { ...PUSH_FLAGS, - [TYPES.SIMPLE_STRING]: Buffer + [RESP_TYPES.SIMPLE_STRING]: Buffer }; export default class RedisCommandsQueue { @@ -125,7 +125,7 @@ export default class RedisCommandsQueue { if (PONG.equals(reply[0] as Buffer)) { const { resolve, flags } = this._waitingForReply.shift()!, buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(flags?.[TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + resolve(flags?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); return; } } diff --git a/packages/client/test.mjs b/packages/client/test.mjs deleted file mode 100644 index f50279ece2b..00000000000 --- a/packages/client/test.mjs +++ /dev/null @@ -1,338 +0,0 @@ -import { setTimeout } from 'timers/promises'; -import { createClient, defineScript, createCluster } from './dist/index.js'; -import { TYPES } from './dist/lib/RESP/decoder.js'; - -async function client() { - console.log(`!!! CLIENT !!!`); - - const client = createClient({ - RESP, - isolationPoolOptions: { - max: 5 - }, - modules: { - /** - * module jsdoc - */ - module: { - /** - * module ping jsdoc - */ - ping: { - /** - * @param {string} [message] - */ - transformArguments(message) { - const args = ['PING']; - if (message) { - args.push(message); - } - - return args; - }, - /** - * @callback PingReply - * @returns {import('./lib/RESP/types').SimpleStringReply} - * - * @type {PingReply} - */ - transformReply: undefined - }, - /** - * module square jsdoc - */ - square: { - /** - * @param {number} number - */ - transformArguments(number) { - return ['FCALL_RO', 'square', '0', number.toString()]; - }, - /** - * @callback SquareResp2 - * @returns {import('./lib/RESP/types').BlobStringReply} - * - * @callback SquareResp3 - * @returns {import('./lib/RESP/types').DoubleReply} - * - * @type {{ 2: SquareResp2, 3: SquareResp3 }} - */ - transformReply: undefined - } - } - }, - functions: { - /** - * library jsdoc - */ - library: { - /** - * library square jsdoc - */ - square: { - IS_READ_ONLY: true, - NUMBER_OF_KEYS: 0, - /** - * @param {number} number - */ - transformArguments(number) { - return [number.toString()]; - }, - /** - * @callback SquareResp2 - * @returns {import('./lib/RESP/types').BlobStringReply} - * - * @callback SquareResp3 - * @returns {import('./lib/RESP/types').DoubleReply} - * - * @type {{ 2: SquareResp2, 3: SquareResp3 }} - */ - transformReply: undefined - } - } - }, - scripts: { - /** - * square jsdoc - */ - square: defineScript({ - SCRIPT: 'return { double = ARGV[1] * ARGV[1] };', - NUMBER_OF_KEYS: 0, - /** - * @param {number} number - */ - transformArguments(number) { - return [number.toString()]; - }, - - /** - * @callback SquareResp2 - * @returns {import('./lib/RESP/types').BlobStringReply} - * - * @callback SquareResp3 - * @returns {import('./lib/RESP/types').DoubleReply} - * - * @type {{ 2: SquareResp2, 3: SquareResp3 }} - */ - transformReply: undefined - }) - } - }); - - const multi = client.multi() - .get('a') - .set('a', 'b'); - - for (let i = 0; i< 10; i++) { - multi.incr('a'); - } - - const result = await multi.exec(); - - const bufferClient = client.withFlags({ - [TYPES.SIMPLE_STRING]: Buffer, - [TYPES.BLOB_STRING]: Buffer - }); - - client.on('error', err => console.error(err)); - - await client.connect(); - - client.ping() - - // console.log( - // 'SCAN', - // await client.scan(0), - // await bufferClient.scan(0) - // ); - - // const fn = - // `#!LUA name=math - // redis.register_function{ - // function_name = "square", - // callback = function(keys, args) return { double = args[1] * args[1] } end, - // flags = { "no-writes" } - // }`; - - // await client.sendCommand(['FLUSHALL']); - // await client.sendCommand(['FUNCTION', 'LOAD', 'REPLACE', fn]); - - // console.log( - // 'info:\n', - // await client.info(), - // 'info with flags:\n', - // await client.withFlags({ - // [TYPES.VERBATIM_STRING]: VerbatimString - // }).info(), - // ); - - // console.log( - // 'client.module.square (module):', - // await client.module.square(1), - // await client.withFlags({ - // [TYPES.DOUBLE]: String - // }).module.square(1) - // ); - - // console.log( - // 'client.library.square (function):', - // await client.library.square(2), - // await client.withFlags({ - // [TYPES.DOUBLE]: String - // }).library.square(2) - // ); - - // console.log( - // 'client.square (script):', - // await client.square(4), - // await client.withFlags({ - // [TYPES.DOUBLE]: String - // }).square(4) - // ); - - // console.log( - // 'MULTI', - // await client.multi() - // .ping() - // .module.ping() - // .library.square(2) - // .square(4) - // .exec() - // ); - - // console.log( - // 'SET key value', - // await client.set('key', 'value'), - // ); - - // console.log( - // 'GET key', - // await client.get('key'), - // ); - - // console.log( - // 'GET key (bufferClient)', - // await bufferClient.get('key'), - // ); - - // console.log( - // 'sendCommand DEL key', - // await client.sendCommand(['DEL', 'key']) - // ); - - // console.log( - // 'HSET key field value', - // await client.hSet('key', 'field', 'value') - // ); - - // console.log( - // 'HGET key field', - // await client.hGet('key', 'field') - // ); - - // console.log( - // 'HGETALL key', - // await client.hGetAll('key') - // ); - - // console.log( - // 'HGETALL key (bufferClient)', - // await bufferClient.hGetAll('key') - // ); - - // console.log( - // 'CLIENT ID', - // await client.sendCommand(['CLIENT', 'ID']), - // ); - - // await client.subscribe('channel', message => { - // console.log('channel', message); - // }); - - // let publisherClient; - // if (RESP !== 3) { - // publisherClient = client.duplicate(); - // publisherClient.on('error', err => console.error('PubSubClient error', err)); - - // await publisherClient.connect(); - // } - - // const TIMES = 3; - // console.log( - // `[PUBLISH channel ] [PING ] * ${TIMES}`, - // await Promise.all( - // Array.from({ length: 5 }).map((_, i) => - // Promise.all([ - // (publisherClient ?? client).sendCommand(['PUBLISH', 'channel', i.toString()]).catch(), - // client.ping(i.toString()), - // client.isolated().clientId(), - // client.executeIsolated(client => client.clientId()) - // ]) - // ) - // ) - // ); - - const entries = Array.from({ length: 100 }).map((_, i) => ['{a}' + i.toString(), i.toString()]) - - await client.mSet(entries); - for await (const key of client.scanIterator()) { - console.log('SCAN', key); - } - - await client.hSet('hash', entries.flat()); - for await (const entry of client.hScanIterator('hash')) { - console.log('HSCAN', entry) - } - - await Promise.all([ - // publisherClient?.disconnect(), - client.disconnect() - ]); -} - -async function cluster() { - console.log(`!!! CLUSTER !!!`); - - const cluster = createCluster({ - rootNodes: [{}], - RESP - }); - cluster.on('error', err => console.error(err)); - - await cluster.connect(); - - console.log( - 'SET key value', - await cluster.set('key', 'value') - ); - - console.log( - 'GET key', - await cluster.get('key') - ); - - await cluster.subscribe('channel', message => { - console.log('(cluster) channel', message); - }); - - const CLUSTER_TIMES = 3; - console.log( - `[PUBLISH channel ] [PING ] * ${CLUSTER_TIMES}`, - await Promise.all( - Array.from({ length: 5 }).map(async (_, i) => { - const client = await cluster.nodeClient(cluster.getRandomNode()); - return client.sendCommand(['PUBLISH', 'channel', i.toString()]); - }) - ) - ); - - // wait for messages - await setTimeout(1000); - - await cluster.disconnect(); -} - -const RESP = 3; - -await client(); -// await cluster(); From a5d0963fcfaaca3f26a83567dfb76b43dc026c72 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 30 Apr 2023 11:08:59 -0400 Subject: [PATCH 031/325] Release client@2.0.0-next.1 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index d7c52a20438..806c90af218 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.7", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 4304f4dba35213accbc981d9ecc6f764d20d4a65 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 1 May 2023 06:58:27 -0400 Subject: [PATCH 032/325] some more commands --- packages/client/lib/commands/LLEN.spec.ts | 36 +++++------ packages/client/lib/commands/LMOVE.spec.ts | 38 +++++------- packages/client/lib/commands/LMOVE.ts | 1 + packages/client/lib/commands/LMPOP.spec.ts | 49 ++++++++------- packages/client/lib/commands/LMPOP.ts | 1 + packages/client/lib/commands/LSET.ts | 4 +- packages/client/lib/commands/LTRIM.ts | 4 +- packages/client/lib/commands/MOVE.spec.ts | 26 ++++---- packages/client/lib/commands/MSET.spec.ts | 62 +++++++++---------- packages/client/lib/commands/MSETNX.spec.ts | 62 +++++++++---------- packages/client/lib/commands/PERSIST.spec.ts | 29 +++++---- packages/client/lib/commands/PEXPIRE.spec.ts | 43 +++++++------ .../client/lib/commands/PEXPIREAT.spec.ts | 57 +++++++++-------- .../client/lib/commands/PEXPIRETIME.spec.ts | 31 +++++----- packages/client/lib/commands/PEXPIRETIME.ts | 2 +- packages/client/lib/commands/PFADD.spec.ts | 43 +++++++------ packages/client/lib/commands/PFADD.ts | 4 +- packages/client/lib/commands/PFCOUNT.spec.ts | 43 +++++++------ packages/client/lib/commands/PFMERGE.spec.ts | 43 +++++++------ packages/client/lib/commands/PSETEX.spec.ts | 37 +++++------ packages/client/lib/commands/PTTL.spec.ts | 29 +++++---- packages/client/lib/commands/index.ts | 20 +++++- 22 files changed, 345 insertions(+), 319 deletions(-) diff --git a/packages/client/lib/commands/LLEN.spec.ts b/packages/client/lib/commands/LLEN.spec.ts index fb126ddad55..931969a936e 100644 --- a/packages/client/lib/commands/LLEN.spec.ts +++ b/packages/client/lib/commands/LLEN.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LLEN'; +import LLEN from './LLEN'; describe('LLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['LLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LLEN.transformArguments('key'), + ['LLEN', 'key'] + ); + }); - testUtils.testWithClient('client.lLen', async client => { - assert.equal( - await client.lLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lLen', async cluster => { - assert.equal( - await cluster.lLen('key'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lLen', async client => { + assert.equal( + await client.lLen('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LMOVE.spec.ts b/packages/client/lib/commands/LMOVE.spec.ts index f1d418c394e..c804614de5f 100644 --- a/packages/client/lib/commands/LMOVE.spec.ts +++ b/packages/client/lib/commands/LMOVE.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LMOVE'; +import LMOVE from './LMOVE'; describe('LMOVE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination', 'LEFT', 'RIGHT'), - ['LMOVE', 'source', 'destination', 'LEFT', 'RIGHT'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LMOVE.transformArguments('source', 'destination', 'LEFT', 'RIGHT'), + ['LMOVE', 'source', 'destination', 'LEFT', 'RIGHT'] + ); + }); - testUtils.testWithClient('client.lMove', async client => { - assert.equal( - await client.lMove('source', 'destination', 'LEFT', 'RIGHT'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lMove', async cluster => { - assert.equal( - await cluster.lMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lMove', async client => { + assert.equal( + await client.lMove('source', 'destination', 'LEFT', 'RIGHT'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LMOVE.ts b/packages/client/lib/commands/LMOVE.ts index 3ec118b9905..95adc71a0ff 100644 --- a/packages/client/lib/commands/LMOVE.ts +++ b/packages/client/lib/commands/LMOVE.ts @@ -3,6 +3,7 @@ import { ListSide } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, transformArguments( source: RedisArgument, destination: RedisArgument, diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts index 5675ee9a285..f620714f4f4 100644 --- a/packages/client/lib/commands/LMPOP.spec.ts +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -1,32 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LMPOP'; +import LMPOP from './LMPOP'; describe('LMPOP', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'LEFT'), - ['LMPOP', '1', 'key', 'LEFT'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + LMPOP.transformArguments('key', 'LEFT'), + ['LMPOP', '1', 'key', 'LEFT'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', 'LEFT', { - COUNT: 2 - }), - ['LMPOP', '1', 'key', 'LEFT', 'COUNT', '2'] - ); - }); + it('with COUNT', () => { + assert.deepEqual( + LMPOP.transformArguments('key', 'LEFT', { + COUNT: 2 + }), + ['LMPOP', '1', 'key', 'LEFT', 'COUNT', '2'] + ); }); + }); - testUtils.testWithClient('client.lmPop', async client => { - assert.deepEqual( - await client.lmPop('key', 'RIGHT'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.lmPop', async client => { + assert.deepEqual( + await client.lmPop('key', 'RIGHT'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts index 5cefc296302..7ce4bbc2d7b 100644 --- a/packages/client/lib/commands/LMPOP.ts +++ b/packages/client/lib/commands/LMPOP.ts @@ -3,6 +3,7 @@ import { transformLMPopArguments, LMPopOptions, ListSide, RedisVariadicArgument export default { FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, transformArguments( keys: RedisVariadicArgument, side: ListSide, diff --git a/packages/client/lib/commands/LSET.ts b/packages/client/lib/commands/LSET.ts index 3c5b7867469..edb86baae0f 100644 --- a/packages/client/lib/commands/LSET.ts +++ b/packages/client/lib/commands/LSET.ts @@ -9,11 +9,11 @@ export default { element: RedisArgument ) { return [ - 'LREM', + 'LSET', key, index.toString(), element ]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/LTRIM.ts b/packages/client/lib/commands/LTRIM.ts index 79377ed1d5b..b80aa6264e9 100644 --- a/packages/client/lib/commands/LTRIM.ts +++ b/packages/client/lib/commands/LTRIM.ts @@ -8,11 +8,11 @@ export default { stop: number ) { return [ - 'LREM', + 'LTRIM', key, start.toString(), stop.toString() ]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts index f7fdc481cbf..f6fcfdbad4c 100644 --- a/packages/client/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MOVE'; +import MOVE from './MOVE'; describe('MOVE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['MOVE', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MOVE.transformArguments('key', 1), + ['MOVE', 'key', '1'] + ); + }); - testUtils.testWithClient('client.move', async client => { - assert.equal( - await client.move('key', 1), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.move', async client => { + assert.equal( + await client.move('key', 1), + 1 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MSET.spec.ts b/packages/client/lib/commands/MSET.spec.ts index 0568f38487e..8de2f9fe2df 100644 --- a/packages/client/lib/commands/MSET.spec.ts +++ b/packages/client/lib/commands/MSET.spec.ts @@ -1,42 +1,38 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MSET'; +import MSET from './MSET'; describe('MSET', () => { - describe('transformArguments', () => { - it("['key1', 'value1', 'key2', 'value2']", () => { - assert.deepEqual( - transformArguments(['key1', 'value1', 'key2', 'value2']), - ['MSET', 'key1', 'value1', 'key2', 'value2'] - ); - }); - - it("[['key1', 'value1'], ['key2', 'value2']]", () => { - assert.deepEqual( - transformArguments([['key1', 'value1'], ['key2', 'value2']]), - ['MSET', 'key1', 'value1', 'key2', 'value2'] - ); - }); + describe('transformArguments', () => { + it("['key1', 'value1', 'key2', 'value2']", () => { + assert.deepEqual( + MSET.transformArguments(['key1', 'value1', 'key2', 'value2']), + ['MSET', 'key1', 'value1', 'key2', 'value2'] + ); + }); - it("{key1: 'value1'. key2: 'value2'}", () => { - assert.deepEqual( - transformArguments({ key1: 'value1', key2: 'value2' }), - ['MSET', 'key1', 'value1', 'key2', 'value2'] - ); - }); + it("[['key1', 'value1'], ['key2', 'value2']]", () => { + assert.deepEqual( + MSET.transformArguments([['key1', 'value1'], ['key2', 'value2']]), + ['MSET', 'key1', 'value1', 'key2', 'value2'] + ); }); - testUtils.testWithClient('client.mSet', async client => { - assert.equal( - await client.mSet(['key1', 'value1', 'key2', 'value2']), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + it("{key1: 'value1'. key2: 'value2'}", () => { + assert.deepEqual( + MSET.transformArguments({ key1: 'value1', key2: 'value2' }), + ['MSET', 'key1', 'value1', 'key2', 'value2'] + ); + }); + }); - testUtils.testWithCluster('cluster.mSet', async cluster => { - assert.equal( - await cluster.mSet(['{key}1', 'value1', '{key}2', 'value2']), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('mSet', async client => { + assert.equal( + await client.mSet(['key1', 'value1', 'key2', 'value2']), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/MSETNX.spec.ts b/packages/client/lib/commands/MSETNX.spec.ts index 854a9affd8a..0c8f07879d3 100644 --- a/packages/client/lib/commands/MSETNX.spec.ts +++ b/packages/client/lib/commands/MSETNX.spec.ts @@ -1,42 +1,38 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MSETNX'; +import MSETNX from './MSETNX'; describe('MSETNX', () => { - describe('transformArguments', () => { - it("['key1', 'value1', 'key2', 'value2']", () => { - assert.deepEqual( - transformArguments(['key1', 'value1', 'key2', 'value2']), - ['MSETNX', 'key1', 'value1', 'key2', 'value2'] - ); - }); - - it("[['key1', 'value1'], ['key2', 'value2']]", () => { - assert.deepEqual( - transformArguments([['key1', 'value1'], ['key2', 'value2']]), - ['MSETNX', 'key1', 'value1', 'key2', 'value2'] - ); - }); + describe('transformArguments', () => { + it("['key1', 'value1', 'key2', 'value2']", () => { + assert.deepEqual( + MSETNX.transformArguments(['key1', 'value1', 'key2', 'value2']), + ['MSETNX', 'key1', 'value1', 'key2', 'value2'] + ); + }); - it("{key1: 'value1'. key2: 'value2'}", () => { - assert.deepEqual( - transformArguments({ key1: 'value1', key2: 'value2' }), - ['MSETNX', 'key1', 'value1', 'key2', 'value2'] - ); - }); + it("[['key1', 'value1'], ['key2', 'value2']]", () => { + assert.deepEqual( + MSETNX.transformArguments([['key1', 'value1'], ['key2', 'value2']]), + ['MSETNX', 'key1', 'value1', 'key2', 'value2'] + ); }); - testUtils.testWithClient('client.mSetNX', async client => { - assert.equal( - await client.mSetNX(['key1', 'value1', 'key2', 'value2']), - true - ); - }, GLOBAL.SERVERS.OPEN); + it("{key1: 'value1'. key2: 'value2'}", () => { + assert.deepEqual( + MSETNX.transformArguments({ key1: 'value1', key2: 'value2' }), + ['MSETNX', 'key1', 'value1', 'key2', 'value2'] + ); + }); + }); - testUtils.testWithCluster('cluster.mSetNX', async cluster => { - assert.equal( - await cluster.mSetNX(['{key}1', 'value1', '{key}2', 'value2']), - true - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('mSetNX', async client => { + assert.equal( + await client.mSetNX(['{key}1', 'value1', '{key}2', 'value2']), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PERSIST.spec.ts b/packages/client/lib/commands/PERSIST.spec.ts index 4e53bd85a6c..4e0c288ea0e 100644 --- a/packages/client/lib/commands/PERSIST.spec.ts +++ b/packages/client/lib/commands/PERSIST.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PERSIST'; +import PERSIST from './PERSIST'; describe('PERSIST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['PERSIST', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PERSIST.transformArguments('key'), + ['PERSIST', 'key'] + ); + }); - testUtils.testWithClient('client.persist', async client => { - assert.equal( - await client.persist('key'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('persist', async client => { + assert.equal( + await client.persist('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PEXPIRE.spec.ts b/packages/client/lib/commands/PEXPIRE.spec.ts index 03bde656103..2b2a2f4b07f 100644 --- a/packages/client/lib/commands/PEXPIRE.spec.ts +++ b/packages/client/lib/commands/PEXPIRE.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PEXPIRE'; +import PEXPIRE from './PEXPIRE'; describe('PEXPIRE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 1), - ['PEXPIRE', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + PEXPIRE.transformArguments('key', 1), + ['PEXPIRE', 'key', '1'] + ); + }); - it('with set option', () => { - assert.deepEqual( - transformArguments('key', 1, 'GT'), - ['PEXPIRE', 'key', '1', 'GT'] - ); - }); + it('with set option', () => { + assert.deepEqual( + PEXPIRE.transformArguments('key', 1, 'GT'), + ['PEXPIRE', 'key', '1', 'GT'] + ); }); + }); - testUtils.testWithClient('client.pExpire', async client => { - assert.equal( - await client.pExpire('key', 1), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pExpire', async client => { + assert.equal( + await client.pExpire('key', 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PEXPIREAT.spec.ts b/packages/client/lib/commands/PEXPIREAT.spec.ts index fec03c8fb75..455595313f0 100644 --- a/packages/client/lib/commands/PEXPIREAT.spec.ts +++ b/packages/client/lib/commands/PEXPIREAT.spec.ts @@ -1,36 +1,39 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PEXPIREAT'; +import PEXPIREAT from './PEXPIREAT'; describe('PEXPIREAT', () => { - describe('transformArguments', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', 1), - ['PEXPIREAT', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('number', () => { + assert.deepEqual( + PEXPIREAT.transformArguments('key', 1), + ['PEXPIREAT', 'key', '1'] + ); + }); - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', d), - ['PEXPIREAT', 'key', d.getTime().toString()] - ); - }); + it('date', () => { + const d = new Date(); + assert.deepEqual( + PEXPIREAT.transformArguments('key', d), + ['PEXPIREAT', 'key', d.getTime().toString()] + ); + }); - it('with set option', () => { - assert.deepEqual( - transformArguments('key', 1, 'XX'), - ['PEXPIREAT', 'key', '1', 'XX'] - ); - }); + it('with set option', () => { + assert.deepEqual( + PEXPIREAT.transformArguments('key', 1, 'XX'), + ['PEXPIREAT', 'key', '1', 'XX'] + ); }); + }); - testUtils.testWithClient('client.pExpireAt', async client => { - assert.equal( - await client.pExpireAt('key', 1), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pExpireAt', async client => { + assert.equal( + await client.pExpireAt('key', 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PEXPIRETIME.spec.ts b/packages/client/lib/commands/PEXPIRETIME.spec.ts index a2fd7f03f82..53c86acd184 100644 --- a/packages/client/lib/commands/PEXPIRETIME.spec.ts +++ b/packages/client/lib/commands/PEXPIRETIME.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PEXPIRETIME'; +import PEXPIRETIME from './PEXPIRETIME'; describe('PEXPIRETIME', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['PEXPIRETIME', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PEXPIRETIME.transformArguments('key'), + ['PEXPIRETIME', 'key'] + ); + }); - testUtils.testWithClient('client.pExpireTime', async client => { - assert.equal( - await client.pExpireTime('key'), - -2 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pExpireTime', async client => { + assert.equal( + await client.pExpireTime('key'), + -2 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PEXPIRETIME.ts b/packages/client/lib/commands/PEXPIRETIME.ts index 49877701b60..e228351fa0e 100644 --- a/packages/client/lib/commands/PEXPIRETIME.ts +++ b/packages/client/lib/commands/PEXPIRETIME.ts @@ -4,7 +4,7 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument) { - return ['PEXPIREAT', key]; + return ['PEXPIRETIME', key]; }, transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/client/lib/commands/PFADD.spec.ts b/packages/client/lib/commands/PFADD.spec.ts index 8c0e752fd50..61db8b94647 100644 --- a/packages/client/lib/commands/PFADD.spec.ts +++ b/packages/client/lib/commands/PFADD.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PFADD'; +import PFADD from './PFADD'; describe('PFADD', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'element'), - ['PFADD', 'key', 'element'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + PFADD.transformArguments('key', 'element'), + ['PFADD', 'key', 'element'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['PFADD', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + PFADD.transformArguments('key', ['1', '2']), + ['PFADD', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.pfAdd', async client => { - assert.equal( - await client.pfAdd('key', '1'), - true - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pfAdd', async client => { + assert.equal( + await client.pfAdd('key', '1'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PFADD.ts b/packages/client/lib/commands/PFADD.ts index 41bf2adfe5e..d7f198fbe55 100644 --- a/packages/client/lib/commands/PFADD.ts +++ b/packages/client/lib/commands/PFADD.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { @@ -10,5 +10,5 @@ export default { return pushVariadicArguments(args, element); }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/client/lib/commands/PFCOUNT.spec.ts b/packages/client/lib/commands/PFCOUNT.spec.ts index a1ea06c4494..6f531de2715 100644 --- a/packages/client/lib/commands/PFCOUNT.spec.ts +++ b/packages/client/lib/commands/PFCOUNT.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PFCOUNT'; +import PFCOUNT from './PFCOUNT'; describe('PFCOUNT', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['PFCOUNT', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + PFCOUNT.transformArguments('key'), + ['PFCOUNT', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['PFCOUNT', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + PFCOUNT.transformArguments(['1', '2']), + ['PFCOUNT', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.pfCount', async client => { - assert.equal( - await client.pfCount('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pfCount', async client => { + assert.equal( + await client.pfCount('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PFMERGE.spec.ts b/packages/client/lib/commands/PFMERGE.spec.ts index 881fc5f5439..63e061c6a00 100644 --- a/packages/client/lib/commands/PFMERGE.spec.ts +++ b/packages/client/lib/commands/PFMERGE.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PFMERGE'; +import PFMERGE from './PFMERGE'; describe('PFMERGE', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('destination', 'source'), - ['PFMERGE', 'destination', 'source'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + PFMERGE.transformArguments('destination', 'source'), + ['PFMERGE', 'destination', 'source'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('destination', ['1', '2']), - ['PFMERGE', 'destination', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + PFMERGE.transformArguments('destination', ['1', '2']), + ['PFMERGE', 'destination', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.pfMerge', async client => { - assert.equal( - await client.pfMerge('destination', 'source'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pfMerge', async client => { + assert.equal( + await client.pfMerge('{tag}destination', '{tag}source'), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PSETEX.spec.ts b/packages/client/lib/commands/PSETEX.spec.ts index f6262ed8709..11ce8027b42 100644 --- a/packages/client/lib/commands/PSETEX.spec.ts +++ b/packages/client/lib/commands/PSETEX.spec.ts @@ -1,27 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PSETEX'; +import PSETEX from './PSETEX'; describe('PSETEX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1, 'value'), - ['PSETEX', 'key', '1', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PSETEX.transformArguments('key', 1, 'value'), + ['PSETEX', 'key', '1', 'value'] + ); + }); - testUtils.testWithClient('client.pSetEx', async client => { - const a = await client.pSetEx('key', 1, 'value'); - assert.equal( - await client.pSetEx('key', 1, 'value'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.pSetEx', async cluster => { - assert.equal( - await cluster.pSetEx('key', 1, 'value'), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('pSetEx', async client => { + assert.equal( + await client.pSetEx('key', 1, 'value'), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/PTTL.spec.ts b/packages/client/lib/commands/PTTL.spec.ts index e65421de590..116441f5b56 100644 --- a/packages/client/lib/commands/PTTL.spec.ts +++ b/packages/client/lib/commands/PTTL.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PTTL'; +import PTTL from './PTTL'; describe('PTTL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['PTTL', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PTTL.transformArguments('key'), + ['PTTL', 'key'] + ); + }); - testUtils.testWithClient('client.pTTL', async client => { - assert.equal( - await client.pTTL('key'), - -2 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('pTTL', async client => { + assert.equal( + await client.pTTL('key'), + -2 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 04e1f44b096..38f1c0fb09c 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -91,11 +91,17 @@ import LTRIM from './LTRIM'; import MGET from './MGET'; import MSET from './MSET'; import MSETNX from './MSETNX'; +import PERSIST from './PERSIST'; +import PEXPIRE from './PEXPIRE'; +import PEXPIREAT from './PEXPIREAT'; +import PEXPIRETIME from './PEXPIRETIME'; import PFADD from './PFADD'; import PFCOUNT from './PFCOUNT'; import PFMERGE from './PFMERGE'; import PING from './PING'; import PSETEX from './PSETEX'; +import PTTL from './PTTL'; +import RANDOMKEY from './RANDOMKEY'; import RENAME from './RENAME'; import RENAMENX from './RENAMENX'; import RPOP_COUNT from './RPOP_COUNT'; @@ -344,7 +350,15 @@ export default { MSET, mSet: MSET, MSETNX, - mSetNx: MSETNX, + mSetNX: MSETNX, + PERSIST, + persist: PERSIST, + PEXPIRE, + pExpire: PEXPIRE, + PEXPIREAT, + pExpireAt: PEXPIREAT, + PEXPIRETIME, + pExpireTime: PEXPIRETIME, PFADD, pfAdd: PFADD, PFCOUNT, @@ -358,6 +372,10 @@ export default { ping: PING, PSETEX, pSetEx: PSETEX, + PTTL, + pTTL: PTTL, + RANDOMKEY, + randomKey: RANDOMKEY, RENAME, rename: RENAME, RENAMENX, From 74caece450b398e8569ed040b3003702d0399658 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 1 May 2023 19:06:21 -0400 Subject: [PATCH 033/325] fix XADD --- packages/client/lib/commands/XADD.spec.ts | 197 ++++++++---------- packages/client/lib/commands/XADD.ts | 100 +++++---- .../lib/commands/XADD_NOMKSTREAM.spec.ts | 93 +++++++++ .../client/lib/commands/XADD_NOMKSTREAM.ts | 13 ++ packages/client/lib/commands/index.ts | 8 +- 5 files changed, 247 insertions(+), 164 deletions(-) create mode 100644 packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts create mode 100644 packages/client/lib/commands/XADD_NOMKSTREAM.ts diff --git a/packages/client/lib/commands/XADD.spec.ts b/packages/client/lib/commands/XADD.spec.ts index c2b9c4f7bbe..bfc3e0c2caf 100644 --- a/packages/client/lib/commands/XADD.spec.ts +++ b/packages/client/lib/commands/XADD.spec.ts @@ -1,118 +1,93 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XADD'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XADD from './XADD'; -// describe('XADD', () => { -// describe('transformArguments', () => { -// it('single field', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }), -// ['XADD', 'key', '*', 'field', 'value'] -// ); -// }); +describe('XADD', () => { + describe('transformArguments', () => { + it('single field', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + field: 'value' + }), + ['XADD', 'key', '*', 'field', 'value'] + ); + }); -// it('multiple fields', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// '1': 'I', -// '2': 'II' -// }), -// ['XADD', 'key', '*', '1', 'I', '2', 'II'] -// ); -// }); + it('multiple fields', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + '1': 'I', + '2': 'II' + }), + ['XADD', 'key', '*', '1', 'I', '2', 'II'] + ); + }); -// it('with NOMKSTREAM', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// NOMKSTREAM: true -// }), -// ['XADD', 'key', 'NOMKSTREAM', '*', 'field', 'value'] -// ); -// }); + it('with TRIM', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + threshold: 1000 + } + }), + ['XADD', 'key', '1000', '*', 'field', 'value'] + ); + }); -// it('with TRIM', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// TRIM: { -// threshold: 1000 -// } -// }), -// ['XADD', 'key', '1000', '*', 'field', 'value'] -// ); -// }); + it('with TRIM.strategy', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + strategy: 'MAXLEN', + threshold: 1000 + } + }), + ['XADD', 'key', 'MAXLEN', '1000', '*', 'field', 'value'] + ); + }); -// it('with TRIM.strategy', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// TRIM: { -// strategy: 'MAXLEN', -// threshold: 1000 -// } -// }), -// ['XADD', 'key', 'MAXLEN', '1000', '*','field', 'value'] -// ); -// }); + it('with TRIM.strategyModifier', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + strategyModifier: '=', + threshold: 1000 + } + }), + ['XADD', 'key', '=', '1000', '*', 'field', 'value'] + ); + }); -// it('with TRIM.strategyModifier', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// TRIM: { -// strategyModifier: '=', -// threshold: 1000 -// } -// }), -// ['XADD', 'key', '=', '1000', '*', 'field', 'value'] -// ); -// }); + it('with TRIM.limit', () => { + assert.deepEqual( + XADD.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + threshold: 1000, + limit: 1 + } + }), + ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value'] + ); + }); + }); -// it('with TRIM.limit', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// TRIM: { -// threshold: 1000, -// limit: 1 -// } -// }), -// ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value'] -// ); -// }); - -// it('with NOMKSTREAM, TRIM, TRIM.*', () => { -// assert.deepEqual( -// transformArguments('key', '*', { -// field: 'value' -// }, { -// NOMKSTREAM: true, -// TRIM: { -// strategy: 'MAXLEN', -// strategyModifier: '=', -// threshold: 1000, -// limit: 1 -// } -// }), -// ['XADD', 'key', 'NOMKSTREAM', 'MAXLEN', '=', '1000', 'LIMIT', '1', '*', 'field', 'value'] -// ); -// }); -// }); - -// testUtils.testWithClient('client.xAdd', async client => { -// assert.equal( -// typeof await client.xAdd('key', '*', { -// field: 'value' -// }), -// 'string' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xAdd', async client => { + assert.equal( + typeof await client.xAdd('key', '*', { + field: 'value' + }), + 'string' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XADD.ts b/packages/client/lib/commands/XADD.ts index 16d7286ca70..9b6fe045a8f 100644 --- a/packages/client/lib/commands/XADD.ts +++ b/packages/client/lib/commands/XADD.ts @@ -1,52 +1,48 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 1; - -// interface XAddOptions { -// NOMKSTREAM?: true; -// TRIM?: { -// strategy?: 'MAXLEN' | 'MINID'; -// strategyModifier?: '=' | '~'; -// threshold: number; -// limit?: number; -// }; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// id: RedisCommandArgument, -// message: Record, -// options?: XAddOptions -// ): RedisCommandArguments { -// const args = ['XADD', key]; - -// if (options?.NOMKSTREAM) { -// args.push('NOMKSTREAM'); -// } - -// if (options?.TRIM) { -// if (options.TRIM.strategy) { -// args.push(options.TRIM.strategy); -// } - -// if (options.TRIM.strategyModifier) { -// args.push(options.TRIM.strategyModifier); -// } - -// args.push(options.TRIM.threshold.toString()); - -// if (options.TRIM.limit) { -// args.push('LIMIT', options.TRIM.limit.toString()); -// } -// } - -// args.push(id); - -// for (const [key, value] of Object.entries(message)) { -// args.push(key, value); -// } - -// return args; -// } - -// export declare function transformReply(): string; +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; + +export interface XAddOptions { + TRIM?: { + strategy?: 'MAXLEN' | 'MINID'; + strategyModifier?: '=' | '~'; + threshold: number; + limit?: number; + }; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + id: RedisArgument, + message: Record, + options?: XAddOptions + ) { + const args = ['XADD', key]; + + if (options?.TRIM) { + if (options.TRIM.strategy) { + args.push(options.TRIM.strategy); + } + + if (options.TRIM.strategyModifier) { + args.push(options.TRIM.strategyModifier); + } + + args.push(options.TRIM.threshold.toString()); + + if (options.TRIM.limit) { + args.push('LIMIT', options.TRIM.limit.toString()); + } + } + + args.push(id); + + for (const [key, value] of Object.entries(message)) { + args.push(key, value); + } + + return args; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts new file mode 100644 index 00000000000..e28bd4e1053 --- /dev/null +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts @@ -0,0 +1,93 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; + +describe('XADD NOMKSTREAM', () => { + describe('transformArguments', () => { + it('single field', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + field: 'value' + }), + ['XADD', 'key', '*', 'field', 'value', 'NOMKSTREAM'] + ); + }); + + it('multiple fields', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + '1': 'I', + '2': 'II' + }), + ['XADD', 'key', '*', '1', 'I', '2', 'II', 'NOMKSTREAM'] + ); + }); + + it('with TRIM', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + threshold: 1000 + } + }), + ['XADD', 'key', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ); + }); + + it('with TRIM.strategy', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + strategy: 'MAXLEN', + threshold: 1000 + } + }), + ['XADD', 'key', 'MAXLEN', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ); + }); + + it('with TRIM.strategyModifier', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + strategyModifier: '=', + threshold: 1000 + } + }), + ['XADD', 'key', '=', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ); + }); + + it('with TRIM.limit', () => { + assert.deepEqual( + XADD_NOMKSTREAM.transformArguments('key', '*', { + field: 'value' + }, { + TRIM: { + threshold: 1000, + limit: 1 + } + }), + ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value', 'NOMKSTREAM'] + ); + }); + }); + + testUtils.testAll('xAddNoMkStream', async client => { + assert.equal( + typeof await client.xAddNoMkStream('key', '*', { + field: 'value' + }), + 'string' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.ts new file mode 100644 index 00000000000..4c425f89826 --- /dev/null +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.ts @@ -0,0 +1,13 @@ +import { BlobStringReply, NullReply, Command } from '../RESP/types'; +import XADD from './XADD'; + +export default { + FIRST_KEY_INDEX: XADD.FIRST_KEY_INDEX, + IS_READ_ONLY: XADD.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = XADD.transformArguments(...args); + redisArgs.push('NOMKSTREAM'); + return redisArgs; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 38f1c0fb09c..19667c7feed 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -141,6 +141,8 @@ import UNLINK from './UNLINK'; import UNWATCH from './UNWATCH'; import WAIT from './WAIT'; import WATCH from './WATCH'; +import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; +import XADD from './XADD'; import XLEN from './XLEN'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; @@ -407,7 +409,7 @@ export default { SETEX, setEx: SETEX, SETNX, - setNX: SETNX, + setNX: SETNX, SETRANGE, setRange: SETRANGE, SINTER, @@ -454,6 +456,10 @@ export default { wait: WAIT, WATCH, watch: WATCH, + XADD_NOMKSTREAM, + xAddNoMkStream: XADD_NOMKSTREAM, + XADD, + xAdd: XADD, XLEN, xLen: XLEN, ZADD, From e58562be4df6fc3265fc10d230a86d9648fa4c5d Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 1 May 2023 19:08:14 -0400 Subject: [PATCH 034/325] clean code --- packages/client/lib/commands/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 19667c7feed..a07c5b8b02f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -55,7 +55,7 @@ import HGETALL from './HGETALL'; import HINCRBY from './HINCRBY'; import HINCRBYFLOAT from './HINCRBYFLOAT'; import HKEYS from './HKEYS'; -import HLEN from './HLEN' +import HLEN from './HLEN'; import HMGET from './HMGET'; import HRANDFIELD_COUNT_WITHVALUES from './HRANDFIELD_COUNT_WITHVALUES'; import HRANDFIELD_COUNT from './HRANDFIELD_COUNT'; From ea87a6767fce75c598ee24d0e6b56a5795145017 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 1 May 2023 19:20:45 -0400 Subject: [PATCH 035/325] fix XACK --- packages/client/lib/commands/XACK.spec.ts | 53 ++++++++++++----------- packages/client/lib/commands/XACK.ts | 27 ++++++------ packages/client/lib/commands/index.ts | 3 ++ 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/packages/client/lib/commands/XACK.spec.ts b/packages/client/lib/commands/XACK.spec.ts index fdfaee5fb59..dd44debe2a1 100644 --- a/packages/client/lib/commands/XACK.spec.ts +++ b/packages/client/lib/commands/XACK.spec.ts @@ -1,28 +1,31 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XACK'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XACK from './XACK'; -// describe('XACK', () => { -// describe('transformArguments', () => { -// it('string', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '1-0'), -// ['XACK', 'key', 'group', '1-0'] -// ); -// }); +describe('XACK', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + XACK.transformArguments('key', 'group', '1-0'), + ['XACK', 'key', 'group', '1-0'] + ); + }); -// it('array', () => { -// assert.deepEqual( -// transformArguments('key', 'group', ['1-0', '2-0']), -// ['XACK', 'key', 'group', '1-0', '2-0'] -// ); -// }); -// }); + it('array', () => { + assert.deepEqual( + XACK.transformArguments('key', 'group', ['1-0', '2-0']), + ['XACK', 'key', 'group', '1-0', '2-0'] + ); + }); + }); -// testUtils.testWithClient('client.xAck', async client => { -// assert.equal( -// await client.xAck('key', 'group', '1-0'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xAck', async client => { + assert.equal( + await client.xAck('key', 'group', '1-0'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XACK.ts b/packages/client/lib/commands/XACK.ts index 4d54df00d1e..89b2d581201 100644 --- a/packages/client/lib/commands/XACK.ts +++ b/packages/client/lib/commands/XACK.ts @@ -1,14 +1,15 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// id: RedisCommandArgument | Array -// ): RedisCommandArguments { -// return pushVariadicArguments(['XACK', key, group], id); -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + id: RedisVariadicArgument + ) { + return pushVariadicArguments(['XACK', key, group], id); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index a07c5b8b02f..fa48aa9ef46 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -141,6 +141,7 @@ import UNLINK from './UNLINK'; import UNWATCH from './UNWATCH'; import WAIT from './WAIT'; import WATCH from './WATCH'; +import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; import XLEN from './XLEN'; @@ -456,6 +457,8 @@ export default { wait: WAIT, WATCH, watch: WATCH, + XACK, + xAck: XACK, XADD_NOMKSTREAM, xAddNoMkStream: XADD_NOMKSTREAM, XADD, From dd6b211db36c4b4909790c23acd78e44fd757c8d Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 15:28:23 -0400 Subject: [PATCH 036/325] fix XDEL --- packages/client/lib/commands/XDEL.spec.ts | 53 ++++++++++++----------- packages/client/lib/commands/XDEL.ts | 22 +++++----- packages/client/lib/commands/index.ts | 4 ++ todo.md | 31 +++++++++++++ 4 files changed, 73 insertions(+), 37 deletions(-) create mode 100644 todo.md diff --git a/packages/client/lib/commands/XDEL.spec.ts b/packages/client/lib/commands/XDEL.spec.ts index 4f7d48aa0ee..a5c81a58181 100644 --- a/packages/client/lib/commands/XDEL.spec.ts +++ b/packages/client/lib/commands/XDEL.spec.ts @@ -1,28 +1,31 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XDEL'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XDEL from './XDEL'; -// describe('XDEL', () => { -// describe('transformArguments', () => { -// it('string', () => { -// assert.deepEqual( -// transformArguments('key', '0-0'), -// ['XDEL', 'key', '0-0'] -// ); -// }); +describe('XDEL', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + XDEL.transformArguments('key', '0-0'), + ['XDEL', 'key', '0-0'] + ); + }); -// it('array', () => { -// assert.deepEqual( -// transformArguments('key', ['0-0', '1-0']), -// ['XDEL', 'key', '0-0', '1-0'] -// ); -// }); -// }); + it('array', () => { + assert.deepEqual( + XDEL.transformArguments('key', ['0-0', '1-0']), + ['XDEL', 'key', '0-0', '1-0'] + ); + }); + }); -// testUtils.testWithClient('client.xDel', async client => { -// assert.equal( -// await client.xDel('key', '0-0'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xDel', async client => { + assert.equal( + await client.xDel('key', '0-0'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XDEL.ts b/packages/client/lib/commands/XDEL.ts index dab033fe572..acc9198c2b8 100644 --- a/packages/client/lib/commands/XDEL.ts +++ b/packages/client/lib/commands/XDEL.ts @@ -1,13 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// id: RedisCommandArgument | Array -// ): RedisCommandArguments { -// return pushVariadicArguments(['XDEL', key], id); -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, id: RedisVariadicArgument) { + return pushVariadicArguments(['XDEL', key], id); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index fa48aa9ef46..c5f4e31156f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -144,6 +144,7 @@ import WATCH from './WATCH'; import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; +import XDEL from './XDEL' import XLEN from './XLEN'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; @@ -463,6 +464,9 @@ export default { xAddNoMkStream: XADD_NOMKSTREAM, XADD, xAdd: XADD, + XDEL, + xDel: XDEL, + XLEN, xLen: XLEN, ZADD, diff --git a/todo.md b/todo.md new file mode 100644 index 00000000000..d3c2e81aa32 --- /dev/null +++ b/todo.md @@ -0,0 +1,31 @@ +# return type +- `XAUTOCLAIM` + + +# create commands +- `ZREVRANGE` +- `ZREVRANGEBYLEX` +- `ZREVRANGEBYSCORE` +- `ZREVRANGE WITHSCORE` +- `ZRANK WITHSCORE` + + +# waiting List +- `BZMPOP.ts` +- `BZPOPMAX.ts` +- `BZPOPMIN.ts` +- `ZRANGEBYSCORE.ts` +- `ZRANGEBYLEX.ts` +- `ZPOPMIN.ts` +- `ZPOPMAX.ts` +- `ZMPOP.ts` +- `ZUNION.ts` +- `ZREMRANGEBYLEX.ts` +- `ZREMRANGEBYRANK.ts` +- `ZREMRANGEBYSCORE.ts` +- `ZUNION.ts` +- `ZUNIONSTORE.ts` + + +# other + From 449d9c40ae6581cf6ad61e162e0d7e03e5e2c6d0 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 15:40:00 -0400 Subject: [PATCH 037/325] fix XTRIM --- packages/client/lib/commands/XTRIM.spec.ts | 91 +++++++++++----------- packages/client/lib/commands/XTRIM.ts | 62 +++++++-------- packages/client/lib/commands/index.ts | 6 +- 3 files changed, 82 insertions(+), 77 deletions(-) diff --git a/packages/client/lib/commands/XTRIM.spec.ts b/packages/client/lib/commands/XTRIM.spec.ts index bcbb1c928c5..4c6ea985f1c 100644 --- a/packages/client/lib/commands/XTRIM.spec.ts +++ b/packages/client/lib/commands/XTRIM.spec.ts @@ -1,49 +1,52 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XTRIM'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XTRIM from './XTRIM'; -// describe('XTRIM', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', 'MAXLEN', 1), -// ['XTRIM', 'key', 'MAXLEN', '1'] -// ); -// }); +describe('XTRIM', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XTRIM.transformArguments('key', 'MAXLEN', 1), + ['XTRIM', 'key', 'MAXLEN', '1'] + ); + }); -// it('with strategyModifier', () => { -// assert.deepEqual( -// transformArguments('key', 'MAXLEN', 1, { -// strategyModifier: '=' -// }), -// ['XTRIM', 'key', 'MAXLEN', '=', '1'] -// ); -// }); + it('with strategyModifier', () => { + assert.deepEqual( + XTRIM.transformArguments('key', 'MAXLEN', 1, { + strategyModifier: '=' + }), + ['XTRIM', 'key', 'MAXLEN', '=', '1'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('key', 'MAXLEN', 1, { -// LIMIT: 1 -// }), -// ['XTRIM', 'key', 'MAXLEN', '1', 'LIMIT', '1'] -// ); -// }); + it('with LIMIT', () => { + assert.deepEqual( + XTRIM.transformArguments('key', 'MAXLEN', 1, { + LIMIT: 1 + }), + ['XTRIM', 'key', 'MAXLEN', '1', 'LIMIT', '1'] + ); + }); -// it('with strategyModifier, LIMIT', () => { -// assert.deepEqual( -// transformArguments('key', 'MAXLEN', 1, { -// strategyModifier: '=', -// LIMIT: 1 -// }), -// ['XTRIM', 'key', 'MAXLEN', '=', '1', 'LIMIT', '1'] -// ); -// }); -// }); + it('with strategyModifier, LIMIT', () => { + assert.deepEqual( + XTRIM.transformArguments('key', 'MAXLEN', 1, { + strategyModifier: '=', + LIMIT: 1 + }), + ['XTRIM', 'key', 'MAXLEN', '=', '1', 'LIMIT', '1'] + ); + }); + }); -// testUtils.testWithClient('client.xTrim', async client => { -// assert.equal( -// await client.xTrim('key', 'MAXLEN', 1), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xTrim', async client => { + assert.equal( + await client.xTrim('key', 'MAXLEN', 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN, + }); +}); diff --git a/packages/client/lib/commands/XTRIM.ts b/packages/client/lib/commands/XTRIM.ts index 780aeb30d7b..edbb11f3ea0 100644 --- a/packages/client/lib/commands/XTRIM.ts +++ b/packages/client/lib/commands/XTRIM.ts @@ -1,31 +1,31 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 1; - -// interface XTrimOptions { -// strategyModifier?: '=' | '~'; -// LIMIT?: number; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// strategy: 'MAXLEN' | 'MINID', -// threshold: number, -// options?: XTrimOptions -// ): RedisCommandArguments { -// const args = ['XTRIM', key, strategy]; - -// if (options?.strategyModifier) { -// args.push(options.strategyModifier); -// } - -// args.push(threshold.toString()); - -// if (options?.LIMIT) { -// args.push('LIMIT', options.LIMIT.toString()); -// } - -// return args; -// } - -// export declare function transformReply(): number; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; + +export interface XTrimOptions { + strategyModifier?: '=' | '~'; + LIMIT?: number; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + strategy: 'MAXLEN' | 'MINID', + threshold: number, + options?: XTrimOptions) { + const args = ['XTRIM', key, strategy]; + + if (options?.strategyModifier) { + args.push(options.strategyModifier); + } + + args.push(threshold.toString()); + + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c5f4e31156f..b95d7467a67 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -144,7 +144,8 @@ import WATCH from './WATCH'; import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; -import XDEL from './XDEL' +import XDEL from './XDEL'; +import XTRIM from './XTRIM'; import XLEN from './XLEN'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; @@ -466,7 +467,8 @@ export default { xAdd: XADD, XDEL, xDel: XDEL, - + XTRIM, + xTrim: XTRIM, XLEN, xLen: XLEN, ZADD, From afa394e35d77ab70c0263e07cfb6d7545f1961e2 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 16:06:14 -0400 Subject: [PATCH 038/325] fix XSETID --- packages/client/lib/commands/XSETID.spec.ts | 42 ++++++++++++++++++ packages/client/lib/commands/XSETID.ts | 47 +++++++++++---------- packages/client/lib/commands/index.ts | 3 ++ todo.md | 3 +- 4 files changed, 71 insertions(+), 24 deletions(-) diff --git a/packages/client/lib/commands/XSETID.spec.ts b/packages/client/lib/commands/XSETID.spec.ts index e69de29bb2d..8e951335a88 100644 --- a/packages/client/lib/commands/XSETID.spec.ts +++ b/packages/client/lib/commands/XSETID.spec.ts @@ -0,0 +1,42 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XSETID from './XSETID'; + +describe('XSETID', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XSETID.transformArguments('key', '0-0'), + ['XSETID', 'key', '0-0'] + ); + }); + + it('with ENTRIESADDED', () => { + assert.deepEqual( + XSETID.transformArguments('key', '0-0', { + ENTRIESADDED: 1 + }), + ['XSETID', 'key', '0-0', 'ENTRIESADDED', '1'] + ); + }); + + it('with MAXDELETEDID', () => { + assert.deepEqual( + XSETID.transformArguments('key', '0-0', { + MAXDELETEDID: '1-1' + }), + ['XSETID', 'key', '0-0', 'MAXDELETEDID', '1-1'] + ); + }); + }); + + testUtils.testAll('xSetId', async client => { + assert.deepEqual( + await client.xSetId('key', '0-0'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XSETID.ts b/packages/client/lib/commands/XSETID.ts index df7cc10f906..bd3a8fd0bc1 100644 --- a/packages/client/lib/commands/XSETID.ts +++ b/packages/client/lib/commands/XSETID.ts @@ -1,28 +1,29 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +export interface XSetIdOptions { + ENTRIESADDED?: number; + MAXDELETEDID?: RedisArgument; +} -// export const FIRST_KEY_INDEX = 1; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + lastId: RedisArgument, + options?: XSetIdOptions + ) { + const args = ['XSETID', key, lastId]; -// interface XSetIdOptions { -// ENTRIESADDED?: number; -// MAXDELETEDID?: RedisCommandArgument; -// } + if (options?.ENTRIESADDED) { + args.push('ENTRIESADDED', options.ENTRIESADDED.toString()); + } -// export function transformArguments( -// key: RedisCommandArgument, -// lastId: RedisCommandArgument, -// options?: XSetIdOptions -// ): RedisCommandArguments { -// const args = ['XSETID', key, lastId]; + if (options?.MAXDELETEDID) { + args.push('MAXDELETEDID', options.MAXDELETEDID); + } -// if (options?.ENTRIESADDED) { -// args.push('ENTRIESADDED', options.ENTRIESADDED.toString()); -// } + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -// if (options?.MAXDELETEDID) { -// args.push('MAXDELETEDID', options.MAXDELETEDID); -// } - -// return args; -// } - -// export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index b95d7467a67..491e0b32245 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -145,6 +145,7 @@ import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; import XDEL from './XDEL'; +import XSETID from './XSETID'; import XTRIM from './XTRIM'; import XLEN from './XLEN'; import ZADD from './ZADD'; @@ -467,6 +468,8 @@ export default { xAdd: XADD, XDEL, xDel: XDEL, + XSETID, + xSetId: XSETID, XTRIM, xTrim: XTRIM, XLEN, diff --git a/todo.md b/todo.md index d3c2e81aa32..3be2364f5c1 100644 --- a/todo.md +++ b/todo.md @@ -1,5 +1,6 @@ -# return type +# return type \ missing documentation - `XAUTOCLAIM` +- `XSETID` # create commands From e1727d16a1adeb4848e85406d9f8c9a1a9f97097 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 17:27:57 -0400 Subject: [PATCH 039/325] fix ZUNION --- packages/client/lib/commands/ZUNION.spec.ts | 87 +++++++++++---------- packages/client/lib/commands/ZUNION.ts | 59 +++++++------- packages/client/lib/commands/index.ts | 5 +- todo.md | 15 ++-- 4 files changed, 87 insertions(+), 79 deletions(-) diff --git a/packages/client/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts index b9882906047..a8aad538033 100644 --- a/packages/client/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -1,48 +1,51 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZUNION'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZUNION from './ZUNION'; -// describe('ZUNION', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('ZUNION', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// describe('transformArguments', () => { -// it('key (string)', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['ZUNION', '1', 'key'] -// ); -// }); + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZUNION.transformArguments('key'), + ['ZUNION', '1', 'key'] + ); + }); -// it('keys (array)', () => { -// assert.deepEqual( -// transformArguments(['1', '2']), -// ['ZUNION', '2', '1', '2'] -// ); -// }); + it('keys (array)', () => { + assert.deepEqual( + ZUNION.transformArguments(['1', '2']), + ['ZUNION', '2', '1', '2'] + ); + }); -// it('with WEIGHTS', () => { -// assert.deepEqual( -// transformArguments('key', { -// WEIGHTS: [1] -// }), -// ['ZUNION', '1', 'key', 'WEIGHTS', '1'] -// ); -// }); + it('with WEIGHTS', () => { + assert.deepEqual( + ZUNION.transformArguments('key', { + WEIGHTS: [1] + }), + ['ZUNION', '1', 'key', 'WEIGHTS', '1'] + ); + }); -// it('with AGGREGATE', () => { -// assert.deepEqual( -// transformArguments('key', { -// AGGREGATE: 'SUM' -// }), -// ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM'] -// ); -// }); -// }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZUNION.transformArguments('key', { + AGGREGATE: 'SUM' + }), + ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM'] + ); + }); + }); -// testUtils.testWithClient('client.zUnion', async client => { -// assert.deepEqual( -// await client.zUnion('key'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('client.zUnion', async client => { + assert.deepEqual( + await client.zUnion('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZUNION.ts b/packages/client/lib/commands/ZUNION.ts index 537aecc8508..f9eb06fbdfa 100644 --- a/packages/client/lib/commands/ZUNION.ts +++ b/packages/client/lib/commands/ZUNION.ts @@ -1,30 +1,29 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArgument } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 2; - -// export const IS_READ_ONLY = true; - -// interface ZUnionOptions { -// WEIGHTS?: Array; -// AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; -// } - -// export function transformArguments( -// keys: Array | RedisCommandArgument, -// options?: ZUnionOptions -// ): RedisCommandArguments { -// const args = pushVariadicArgument(['ZUNION'], keys); - -// if (options?.WEIGHTS) { -// args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); -// } - -// if (options?.AGGREGATE) { -// args.push('AGGREGATE', options.AGGREGATE); -// } - -// return args; -// } - -// export declare function transformReply(): Array; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; + +export interface ZUnionOptions { + WEIGHTS?: Array; + AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; +} + +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + keys: RedisVariadicArgument, + options?: ZUnionOptions + ) { + const args = pushVariadicArgument(['ZUNION'], keys); + + if (options?.WEIGHTS) { + args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); + } + + if (options?.AGGREGATE) { + args.push('AGGREGATE', options.AGGREGATE); + } + + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 491e0b32245..0d435c6a4cd 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -170,6 +170,7 @@ import ZREM from './ZREM'; import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; import ZSCORE from './ZSCORE'; +import ZUNION from './ZUNION'; import { Command } from '../RESP/types'; export default { @@ -517,5 +518,7 @@ export default { ZSCAN, zScan: ZSCAN, ZSCORE, - zScore: ZSCORE + zScore: ZSCORE, + ZUNION, + zUnion: ZUNION } as const satisfies Record; diff --git a/todo.md b/todo.md index 3be2364f5c1..adb88fe025a 100644 --- a/todo.md +++ b/todo.md @@ -1,6 +1,7 @@ # return type \ missing documentation - `XAUTOCLAIM` - `XSETID` +- `ZUNION` # create commands @@ -12,14 +13,8 @@ # waiting List -- `BZMPOP.ts` -- `BZPOPMAX.ts` -- `BZPOPMIN.ts` - `ZRANGEBYSCORE.ts` - `ZRANGEBYLEX.ts` -- `ZPOPMIN.ts` -- `ZPOPMAX.ts` -- `ZMPOP.ts` - `ZUNION.ts` - `ZREMRANGEBYLEX.ts` - `ZREMRANGEBYRANK.ts` @@ -27,6 +22,14 @@ - `ZUNION.ts` - `ZUNIONSTORE.ts` +# fot leiba +- `BZMPOP.ts` +- `BZPOPMAX.ts` +- `BZPOPMIN.ts` +- `ZMPOP.ts` +- `ZPOPMAX.ts` +- `ZPOPMIN.ts` + # other From d643134dcee74ecd3a43378d9921406e465955e3 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 17:43:05 -0400 Subject: [PATCH 040/325] fix ZUNION --- packages/client/lib/commands/ZUNION.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts index a8aad538033..8aca77531ef 100644 --- a/packages/client/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -39,7 +39,7 @@ describe('ZUNION', () => { }); }); - testUtils.testAll('client.zUnion', async client => { + testUtils.testAll('zUnion', async client => { assert.deepEqual( await client.zUnion('key'), [] From 31c91dececac6e07454efa31f5d3a19ae6860f89 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 17:43:10 -0400 Subject: [PATCH 041/325] fix ZUNIONSTORE --- .../client/lib/commands/ZUNIONSTORE.spec.ts | 103 +++++++++--------- packages/client/lib/commands/ZUNIONSTORE.ts | 49 +++++---- packages/client/lib/commands/index.ts | 5 +- todo.md | 2 - 4 files changed, 82 insertions(+), 77 deletions(-) diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index 4458dcb648c..ae561aff651 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -1,56 +1,59 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZUNIONSTORE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZUNIONSTORE from './ZUNIONSTORE'; -// describe('ZUNIONSTORE', () => { -// describe('transformArguments', () => { -// it('key (string)', () => { -// assert.deepEqual( -// transformArguments('destination', 'key'), -// ['ZUNIONSTORE', 'destination', '1', 'key'] -// ); -// }); +describe('ZUNIONSTORE', () => { + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', 'key'), + ['ZUNIONSTORE', 'destination', '1', 'key'] + ); + }); -// it('keys (array)', () => { -// assert.deepEqual( -// transformArguments('destination', ['1', '2']), -// ['ZUNIONSTORE', 'destination', '2', '1', '2'] -// ); -// }); + it('keys (array)', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', ['1', '2']), + ['ZUNIONSTORE', 'destination', '2', '1', '2'] + ); + }); -// it('with WEIGHTS', () => { -// assert.deepEqual( -// transformArguments('destination', 'key', { -// WEIGHTS: [1] -// }), -// ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] -// ); -// }); + it('with WEIGHTS', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', 'key', { + WEIGHTS: [1] + }), + ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] + ); + }); -// it('with AGGREGATE', () => { -// assert.deepEqual( -// transformArguments('destination', 'key', { -// AGGREGATE: 'SUM' -// }), -// ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] -// ); -// }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', 'key', { + AGGREGATE: 'SUM' + }), + ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] + ); + }); -// it('with WEIGHTS, AGGREGATE', () => { -// assert.deepEqual( -// transformArguments('destination', 'key', { -// WEIGHTS: [1], -// AGGREGATE: 'SUM' -// }), -// ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] -// ); -// }); -// }); + it('with WEIGHTS, AGGREGATE', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', 'key', { + WEIGHTS: [1], + AGGREGATE: 'SUM' + }), + ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] + ); + }); + }); -// testUtils.testWithClient('client.zUnionStore', async client => { -// assert.equal( -// await client.zUnionStore('destination', 'key'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zUnionStore', async client => { + assert.equal( + await client.zUnionStore('destination', 'key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZUNIONSTORE.ts b/packages/client/lib/commands/ZUNIONSTORE.ts index dab0417fac9..ed70c75c3ce 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.ts @@ -1,29 +1,30 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArgument } from './generic-transformers'; +import { RedisArgument, NumberReply, Command, } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; +export interface ZUnionOptions { + WEIGHTS?: Array; + AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; +} -// interface ZUnionOptions { -// WEIGHTS?: Array; -// AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + keys: RedisVariadicArgument, + options?: ZUnionOptions + ) { + const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); -// export function transformArguments( -// destination: RedisCommandArgument, -// keys: Array | RedisCommandArgument, -// options?: ZUnionOptions -// ): RedisCommandArguments { -// const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); + if (options?.WEIGHTS) { + args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); + } -// if (options?.WEIGHTS) { -// args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); -// } + if (options?.AGGREGATE) { + args.push('AGGREGATE', options.AGGREGATE); + } -// if (options?.AGGREGATE) { -// args.push('AGGREGATE', options.AGGREGATE); -// } - -// return args; -// } - -// export declare function transformReply(): number; + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 0d435c6a4cd..c5c58f2877e 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -171,6 +171,7 @@ import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; import ZSCORE from './ZSCORE'; import ZUNION from './ZUNION'; +import ZUNIONSTORE from './ZUNIONSTORE'; import { Command } from '../RESP/types'; export default { @@ -520,5 +521,7 @@ export default { ZSCORE, zScore: ZSCORE, ZUNION, - zUnion: ZUNION + zUnion: ZUNION, + ZUNIONSTORE, + zUnionStore: ZUNIONSTORE, } as const satisfies Record; diff --git a/todo.md b/todo.md index adb88fe025a..6a7744fc3fc 100644 --- a/todo.md +++ b/todo.md @@ -15,11 +15,9 @@ # waiting List - `ZRANGEBYSCORE.ts` - `ZRANGEBYLEX.ts` -- `ZUNION.ts` - `ZREMRANGEBYLEX.ts` - `ZREMRANGEBYRANK.ts` - `ZREMRANGEBYSCORE.ts` -- `ZUNION.ts` - `ZUNIONSTORE.ts` # fot leiba From 28d8215b6d1d278fe5e693251aa0b0b60989c655 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 17:54:55 -0400 Subject: [PATCH 042/325] fix ZRANGEBYSCORE --- .../client/lib/commands/ZRANGEBYSCORE.spec.ts | 63 ++++++++++--------- packages/client/lib/commands/ZRANGEBYSCORE.ts | 61 +++++++++--------- packages/client/lib/commands/index.ts | 3 + todo.md | 1 - 4 files changed, 67 insertions(+), 61 deletions(-) diff --git a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts index 1d064c37c12..2ff55676b8b 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts @@ -1,33 +1,36 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZRANGEBYSCORE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGEBYSCORE from './ZRANGEBYSCORE'; -// describe('ZRANGEBYSCORE', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1), -// ['ZRANGEBYSCORE', 'src', '0', '1'] -// ); -// }); +describe('ZRANGEBYSCORE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGEBYSCORE.transformArguments('src', 0, 1), + ['ZRANGEBYSCORE', 'src', '0', '1'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1'] -// ); -// }); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGEBYSCORE.transformArguments('src', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1'] + ); + }); + }); -// testUtils.testWithClient('client.zRangeByScore', async client => { -// assert.deepEqual( -// await client.zRangeByScore('src', 0, 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRangeByScore', async client => { + assert.deepEqual( + await client.zRangeByScore('src', 0, 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANGEBYSCORE.ts b/packages/client/lib/commands/ZRANGEBYSCORE.ts index 562dd6b5d0d..e54c96380de 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.ts @@ -1,35 +1,36 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformStringDoubleArgument } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; +export interface ZRangeByScoreOptions { + LIMIT?: { + offset: number; + count: number; + }; +} -// export const IS_READ_ONLY = true; +export declare function transformReply(): Array; -// export interface ZRangeByScoreOptions { -// LIMIT?: { -// offset: number; -// count: number; -// }; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + min: string | number, + max: string | number, + options?: ZRangeByScoreOptions + ) { + const args = [ + 'ZRANGEBYSCORE', + key, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) + ]; -// export function transformArguments( -// key: RedisCommandArgument, -// min: string | number, -// max: string | number, -// options?: ZRangeByScoreOptions -// ): RedisCommandArguments { -// const args = [ -// 'ZRANGEBYSCORE', -// key, -// transformStringDoubleArgument(min), -// transformStringDoubleArgument(max) -// ]; + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); + } -// if (options?.LIMIT) { -// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); -// } - -// return args; -// } - -// export declare function transformReply(): Array; + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c5c58f2877e..818bc4ef17e 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -165,6 +165,7 @@ import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; import ZRANDMEMBER from './ZRANDMEMBER'; import ZRANGE from './ZRANGE'; +import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; import ZREVRANK from './ZREVRANK'; @@ -510,6 +511,8 @@ export default { zRandMember: ZRANDMEMBER, ZRANGE, zRange: ZRANGE, + ZRANGEBYSCORE, + zRangeByScore: ZRANGEBYSCORE, ZRANK, zRank: ZRANK, ZREM, diff --git a/todo.md b/todo.md index 6a7744fc3fc..cd08196a655 100644 --- a/todo.md +++ b/todo.md @@ -18,7 +18,6 @@ - `ZREMRANGEBYLEX.ts` - `ZREMRANGEBYRANK.ts` - `ZREMRANGEBYSCORE.ts` -- `ZUNIONSTORE.ts` # fot leiba - `BZMPOP.ts` From a5344946b6ad17f96b3de697cd4d415f63eebf54 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 18:01:45 -0400 Subject: [PATCH 043/325] fix ZRANGEBYLEX --- .../client/lib/commands/ZRANGEBYLEX.spec.ts | 63 ++++++++++--------- packages/client/lib/commands/ZRANGEBYLEX.ts | 61 +++++++++--------- packages/client/lib/commands/index.ts | 3 + todo.md | 1 - 4 files changed, 66 insertions(+), 62 deletions(-) diff --git a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts index 40b779eac2c..7b0c22946c0 100644 --- a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts @@ -1,33 +1,36 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZRANGEBYLEX'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGEBYLEX from './ZRANGEBYLEX'; -// describe('ZRANGEBYLEX', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('src', '-', '+'), -// ['ZRANGEBYLEX', 'src', '-', '+'] -// ); -// }); +describe('ZRANGEBYLEX', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGEBYLEX.transformArguments('src', '-', '+'), + ['ZRANGEBYLEX', 'src', '-', '+'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', '-', '+', { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGEBYLEX', 'src', '-', '+', 'LIMIT', '0', '1'] -// ); -// }); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGEBYLEX.transformArguments('src', '-', '+', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGEBYLEX', 'src', '-', '+', 'LIMIT', '0', '1'] + ); + }); + }); -// testUtils.testWithClient('client.zRangeByLex', async client => { -// assert.deepEqual( -// await client.zRangeByLex('src', '-', '+'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRangeByLex', async client => { + assert.deepEqual( + await client.zRangeByLex('src', '-', '+'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANGEBYLEX.ts b/packages/client/lib/commands/ZRANGEBYLEX.ts index d06debb008b..afe7718f3c3 100644 --- a/packages/client/lib/commands/ZRANGEBYLEX.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.ts @@ -1,35 +1,34 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformStringDoubleArgument } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; +export interface ZRangeByLexOptions { + LIMIT?: { + offset: number; + count: number; + }; +} -// export const IS_READ_ONLY = true; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + min: RedisArgument, + max: RedisArgument, + options?: ZRangeByLexOptions + ) { + const args = [ + 'ZRANGEBYLEX', + key, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) + ]; -// export interface ZRangeByLexOptions { -// LIMIT?: { -// offset: number; -// count: number; -// }; -// } + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); + } -// export function transformArguments( -// key: RedisCommandArgument, -// min: RedisCommandArgument, -// max: RedisCommandArgument, -// options?: ZRangeByLexOptions -// ): RedisCommandArguments { -// const args = [ -// 'ZRANGEBYLEX', -// key, -// transformStringDoubleArgument(min), -// transformStringDoubleArgument(max) -// ]; - -// if (options?.LIMIT) { -// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); -// } - -// return args; -// } - -// export declare function transformReply(): Array; + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 818bc4ef17e..a680d067489 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -165,6 +165,7 @@ import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; import ZRANDMEMBER from './ZRANDMEMBER'; import ZRANGE from './ZRANGE'; +import ZRANGEBYLEX from './ZRANGEBYLEX'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; @@ -511,6 +512,8 @@ export default { zRandMember: ZRANDMEMBER, ZRANGE, zRange: ZRANGE, + ZRANGEBYLEX, + zRangeByLex: ZRANGEBYLEX, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, ZRANK, diff --git a/todo.md b/todo.md index cd08196a655..1c1425acd62 100644 --- a/todo.md +++ b/todo.md @@ -13,7 +13,6 @@ # waiting List -- `ZRANGEBYSCORE.ts` - `ZRANGEBYLEX.ts` - `ZREMRANGEBYLEX.ts` - `ZREMRANGEBYRANK.ts` From 08040f943173d69af48e5e985f2b012aa1ecb334 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 18:11:08 -0400 Subject: [PATCH 044/325] fix ZREMRANGEBYLEX --- .../lib/commands/ZREMRANGEBYLEX.spec.ts | 37 ++++++++++--------- .../client/lib/commands/ZREMRANGEBYLEX.ts | 37 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ todo.md | 2 - 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts index 5b9f74fbe42..149aca959c8 100644 --- a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts @@ -1,19 +1,22 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZREMRANGEBYLEX'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; -// describe('ZREMRANGEBYLEX', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', '[a', '[b'), -// ['ZREMRANGEBYLEX', 'key', '[a', '[b'] -// ); -// }); +describe('ZREMRANGEBYLEX', () => { + it('transformArguments', () => { + assert.deepEqual( + ZREMRANGEBYLEX.transformArguments('key', '[a', '[b'), + ['ZREMRANGEBYLEX', 'key', '[a', '[b'] + ); + }); -// testUtils.testWithClient('client.zRemRangeByLex', async client => { -// assert.equal( -// await client.zRemRangeByLex('key', '[a', '[b'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRemRangeByLex', async client => { + assert.equal( + await client.zRemRangeByLex('key', '[a', '[b'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZREMRANGEBYLEX.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.ts index 8c7adf0c91f..e3cd7013ac2 100644 --- a/packages/client/lib/commands/ZREMRANGEBYLEX.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.ts @@ -1,19 +1,20 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformStringDoubleArgument } from './generic-transformers'; +import { NumberReply, Command, RedisArgument } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// min: RedisCommandArgument | number, -// max: RedisCommandArgument | number -// ): RedisCommandArguments { -// return [ -// 'ZREMRANGEBYLEX', -// key, -// transformStringDoubleArgument(min), -// transformStringDoubleArgument(max) -// ]; -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + min: RedisArgument | number, + max: RedisArgument | number + ) { + return [ + 'ZREMRANGEBYLEX', + key, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) + ]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index a680d067489..04743b08b78 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -169,6 +169,7 @@ import ZRANGEBYLEX from './ZRANGEBYLEX'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; +import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; import ZSCORE from './ZSCORE'; @@ -516,6 +517,8 @@ export default { zRangeByLex: ZRANGEBYLEX, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, + ZREMRANGEBYLEX, + zRemRangeByLex: ZREMRANGEBYLEX, ZRANK, zRank: ZRANK, ZREM, diff --git a/todo.md b/todo.md index 1c1425acd62..95d8c58e7ab 100644 --- a/todo.md +++ b/todo.md @@ -13,8 +13,6 @@ # waiting List -- `ZRANGEBYLEX.ts` -- `ZREMRANGEBYLEX.ts` - `ZREMRANGEBYRANK.ts` - `ZREMRANGEBYSCORE.ts` From a280648e6269ff06f8f28f2e64a75e90d8b205f3 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 18:19:54 -0400 Subject: [PATCH 045/325] fix ZREMRANGEBYRANK --- .../lib/commands/ZREMRANGEBYRANK.spec.ts | 37 ++++++++++--------- .../client/lib/commands/ZREMRANGEBYRANK.ts | 24 ++++++------ packages/client/lib/commands/index.ts | 7 +++- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts index 4dd660af742..f6030e4f081 100644 --- a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts @@ -1,19 +1,22 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZREMRANGEBYRANK'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZREMRANGEBYRANK from './ZREMRANGEBYRANK'; -// describe('ZREMRANGEBYRANK', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 0, 1), -// ['ZREMRANGEBYRANK', 'key', '0', '1'] -// ); -// }); +describe('ZREMRANGEBYRANK', () => { + it('transformArguments', () => { + assert.deepEqual( + ZREMRANGEBYRANK.transformArguments('key', 0, 1), + ['ZREMRANGEBYRANK', 'key', '0', '1'] + ); + }); -// testUtils.testWithClient('client.zRemRangeByRank', async client => { -// assert.equal( -// await client.zRemRangeByRank('key', 0, 1), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRemRangeByRank', async client => { + assert.equal( + await client.zRemRangeByRank('key', 0, 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZREMRANGEBYRANK.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.ts index bfb36cb6cbd..986de33060e 100644 --- a/packages/client/lib/commands/ZREMRANGEBYRANK.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.ts @@ -1,13 +1,13 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// start: number, -// stop: number -// ): RedisCommandArguments { -// return ['ZREMRANGEBYRANK', key, start.toString(), stop.toString()]; -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + start: number, + stop: number) { + return ['ZREMRANGEBYRANK', key, start.toString(), stop.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 04743b08b78..eb8d227d417 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -170,6 +170,7 @@ import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; +import ZREMRANGEBYRANK from './ZREMRANGEBYRANK'; import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; import ZSCORE from './ZSCORE'; @@ -517,12 +518,14 @@ export default { zRangeByLex: ZRANGEBYLEX, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, - ZREMRANGEBYLEX, - zRemRangeByLex: ZREMRANGEBYLEX, ZRANK, zRank: ZRANK, ZREM, zRem: ZREM, + ZREMRANGEBYLEX, + zRemRangeByLex: ZREMRANGEBYLEX, + ZREMRANGEBYRANK, + zRemRangeByRank: ZREMRANGEBYRANK, ZREVRANK, zRevRank: ZREVRANK, ZSCAN, From 98c1a1d235a2e1b0bc04df5911190e2f540ae048 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 18:35:33 -0400 Subject: [PATCH 046/325] fix ZREMRANGEBYSCORE --- .../lib/commands/ZREMRANGEBYSCORE.spec.ts | 37 ++++++++++--------- .../client/lib/commands/ZREMRANGEBYSCORE.ts | 37 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts index 8d4bbf5286a..ff819438d6f 100644 --- a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts @@ -1,19 +1,22 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZREMRANGEBYSCORE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; -// describe('ZREMRANGEBYSCORE', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 0, 1), -// ['ZREMRANGEBYSCORE', 'key', '0', '1'] -// ); -// }); +describe('ZREMRANGEBYSCORE', () => { + it('transformArguments', () => { + assert.deepEqual( + ZREMRANGEBYSCORE.transformArguments('key', 0, 1), + ['ZREMRANGEBYSCORE', 'key', '0', '1'] + ); + }); -// testUtils.testWithClient('client.zRemRangeByScore', async client => { -// assert.equal( -// await client.zRemRangeByScore('key', 0, 1), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRemRangeByScore', async client => { + assert.equal( + await client.zRemRangeByScore('key', 0, 1), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZREMRANGEBYSCORE.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.ts index 802e42db8da..7050f2627a7 100644 --- a/packages/client/lib/commands/ZREMRANGEBYSCORE.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.ts @@ -1,19 +1,20 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformStringDoubleArgument } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// min: RedisCommandArgument | number, -// max: RedisCommandArgument | number, -// ): RedisCommandArguments { -// return [ -// 'ZREMRANGEBYSCORE', -// key, -// transformStringDoubleArgument(min), -// transformStringDoubleArgument(max) -// ]; -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + min: RedisArgument | number, + max: RedisArgument | number, + ) { + return [ + 'ZREMRANGEBYSCORE', + key, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) + ]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index eb8d227d417..2613cc05d6f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -167,6 +167,7 @@ import ZRANDMEMBER from './ZRANDMEMBER'; import ZRANGE from './ZRANGE'; import ZRANGEBYLEX from './ZRANGEBYLEX'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; +import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; @@ -526,6 +527,8 @@ export default { zRemRangeByLex: ZREMRANGEBYLEX, ZREMRANGEBYRANK, zRemRangeByRank: ZREMRANGEBYRANK, + ZREMRANGEBYSCORE, + zRemRangeByScore: ZREMRANGEBYSCORE, ZREVRANK, zRevRank: ZREVRANK, ZSCAN, From 6809365e982d5bc7b67130a82d378f45efc2120b Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 19:34:49 -0400 Subject: [PATCH 047/325] fix EXISTS spec --- packages/client/lib/commands/EXISTS.spec.ts | 43 +++++++++++---------- packages/client/lib/commands/index.ts | 3 ++ todo.md | 15 ++++--- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/packages/client/lib/commands/EXISTS.spec.ts b/packages/client/lib/commands/EXISTS.spec.ts index be1a808225e..bc5f564a45f 100644 --- a/packages/client/lib/commands/EXISTS.spec.ts +++ b/packages/client/lib/commands/EXISTS.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EXISTS'; +import EXISTS from './EXISTS'; describe('EXISTS', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['EXISTS', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + EXISTS.transformArguments('key'), + ['EXISTS', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['EXISTS', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + EXISTS.transformArguments(['1', '2']), + ['EXISTS', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.exists', async client => { - assert.equal( - await client.exists('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('exists', async client => { + assert.equal( + await client.exists('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 2613cc05d6f..c1aa9f1a646 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -92,6 +92,7 @@ import MGET from './MGET'; import MSET from './MSET'; import MSETNX from './MSETNX'; import PERSIST from './PERSIST'; +import EXISTS from './EXISTS'; import PEXPIRE from './PEXPIRE'; import PEXPIREAT from './PEXPIREAT'; import PEXPIRETIME from './PEXPIRETIME'; @@ -366,6 +367,8 @@ export default { mSetNX: MSETNX, PERSIST, persist: PERSIST, + EXISTS, + exists: EXISTS, PEXPIRE, pExpire: PEXPIRE, PEXPIREAT, diff --git a/todo.md b/todo.md index 95d8c58e7ab..bb05f695e45 100644 --- a/todo.md +++ b/todo.md @@ -8,13 +8,15 @@ - `ZREVRANGE` - `ZREVRANGEBYLEX` - `ZREVRANGEBYSCORE` -- `ZREVRANGE WITHSCORE` -- `ZRANK WITHSCORE` -# waiting List -- `ZREMRANGEBYRANK.ts` -- `ZREMRANGEBYSCORE.ts` +# waiting List categoreis +- Generic +- String +- Hash +- List +- Set +- Bitmap # fot leiba - `BZMPOP.ts` @@ -23,7 +25,8 @@ - `ZMPOP.ts` - `ZPOPMAX.ts` - `ZPOPMIN.ts` - +- `ZREVRANGE WITHSCORE` +- `ZRANK WITHSCORE` # other From 80ecd9e06a401676b8e4a41d99159cab32857e45 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 19:50:01 -0400 Subject: [PATCH 048/325] fix DUMP spec --- packages/client/lib/commands/DUMP.spec.ts | 15 +++++++++------ packages/client/lib/commands/index.ts | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/client/lib/commands/DUMP.spec.ts b/packages/client/lib/commands/DUMP.spec.ts index aebbf4f3f7c..94cc11ed513 100644 --- a/packages/client/lib/commands/DUMP.spec.ts +++ b/packages/client/lib/commands/DUMP.spec.ts @@ -2,10 +2,13 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('DUMP', () => { - testUtils.testWithClient('client.dump', async client => { - assert.equal( - await client.dump('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.dump', async client => { + assert.equal( + await client.dump('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c1aa9f1a646..2fad74caef2 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -42,6 +42,7 @@ import CLUSTER_MYID from './CLUSTER_MYID'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; import DECR from './DECR'; import DECRBY from './DECRBY'; +import DUMP from './DUMP'; import GET from './GET'; import GETDEL from './GETDEL'; import GETEX from './GETEX'; @@ -269,6 +270,8 @@ export default { decr: DECR, DECRBY, decrBy: DECRBY, + DUMP, + dump: DUMP, GET, get: GET, GETDEL, From ca90d51fb8ddf7efc2b54b06489640bfe2f16e9f Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 19:52:28 -0400 Subject: [PATCH 049/325] fix DEL spec --- packages/client/lib/commands/DEL.spec.ts | 43 +++++++++++++----------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/client/lib/commands/DEL.spec.ts b/packages/client/lib/commands/DEL.spec.ts index 75a29a8f641..6ec8ed8021a 100644 --- a/packages/client/lib/commands/DEL.spec.ts +++ b/packages/client/lib/commands/DEL.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DEL'; +import DEL from './DEL'; describe('DEL', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key'), - ['DEL', 'key'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + DEL.transformArguments('key'), + ['DEL', 'key'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['key1', 'key2']), - ['DEL', 'key1', 'key2'] - ); - }); + it('array', () => { + assert.deepEqual( + DEL.transformArguments(['key1', 'key2']), + ['DEL', 'key1', 'key2'] + ); }); + }); - testUtils.testWithClient('client.del', async client => { - assert.equal( - await client.del('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('del', async client => { + assert.equal( + await client.del('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 2fad74caef2..360308d3cd2 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -42,6 +42,7 @@ import CLUSTER_MYID from './CLUSTER_MYID'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; import DECR from './DECR'; import DECRBY from './DECRBY'; +import DEL from './DEL'; import DUMP from './DUMP'; import GET from './GET'; import GETDEL from './GETDEL'; @@ -270,6 +271,8 @@ export default { decr: DECR, DECRBY, decrBy: DECRBY, + DEL, + del: DEL, DUMP, dump: DUMP, GET, From 3dfea0031890a00da1192f2aa3295750e8f66884 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 20:02:03 -0400 Subject: [PATCH 050/325] fix COPY spec --- packages/client/lib/commands/COPY.spec.ts | 101 ++++++++++------------ packages/client/lib/commands/COPY.ts | 1 + packages/client/lib/commands/index.ts | 3 + 3 files changed, 48 insertions(+), 57 deletions(-) diff --git a/packages/client/lib/commands/COPY.spec.ts b/packages/client/lib/commands/COPY.spec.ts index 0d68e969cdb..412d49db3a0 100644 --- a/packages/client/lib/commands/COPY.spec.ts +++ b/packages/client/lib/commands/COPY.spec.ts @@ -1,67 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './COPY'; +import COPY from './COPY'; describe('COPY', () => { - testUtils.isVersionGreaterThanHook([6, 2]); - - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('source', 'destination'), - ['COPY', 'source', 'destination'] - ); - }); - - it('with destination DB flag', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - destinationDb: 1 - }), - ['COPY', 'source', 'destination', 'DB', '1'] - ); - }); - - it('with replace flag', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - replace: true - }), - ['COPY', 'source', 'destination', 'REPLACE'] - ); - }); - - it('with both flags', () => { - assert.deepEqual( - transformArguments('source', 'destination', { - destinationDb: 1, - replace: true - }), - ['COPY', 'source', 'destination', 'DB', '1', 'REPLACE'] - ); - }); + testUtils.isVersionGreaterThanHook([6, 2]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + COPY.transformArguments('source', 'destination'), + ['COPY', 'source', 'destination'] + ); }); - describe('transformReply', () => { - it('0', () => { - assert.equal( - transformReply(0), - false - ); - }); + it('with destination DB flag', () => { + assert.deepEqual( + COPY.transformArguments('source', 'destination', { + DB: 1 + }), + ['COPY', 'source', 'destination', 'DB', '1'] + ); + }); - it('1', () => { - assert.equal( - transformReply(1), - true - ); - }); + it('with replace flag', () => { + assert.deepEqual( + COPY.transformArguments('source', 'destination', { + REPLACE: true + }), + ['COPY', 'source', 'destination', 'REPLACE'] + ); }); - testUtils.testWithClient('client.copy', async client => { - assert.equal( - await client.copy('source', 'destination'), - false - ); - }, GLOBAL.SERVERS.OPEN); + it('with both flags', () => { + assert.deepEqual( + COPY.transformArguments('source', 'destination', { + DB: 1, + REPLACE: true + }), + ['COPY', 'source', 'destination', 'DB', '1', 'REPLACE'] + ); + }); + }); + + testUtils.testAll('copy', async client => { + assert.equal( + await client.copy('{tag}source', '{tag}destination'), + false + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/COPY.ts b/packages/client/lib/commands/COPY.ts index 2ef3c3224f8..a65948cf944 100644 --- a/packages/client/lib/commands/COPY.ts +++ b/packages/client/lib/commands/COPY.ts @@ -7,6 +7,7 @@ export interface CopyCommandOptions { export default { FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, transformArguments(source: RedisArgument, destination: RedisArgument, options?: CopyCommandOptions) { const args = ['COPY', source, destination]; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 360308d3cd2..6eee5e38192 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -40,6 +40,7 @@ import CLUSTER_SLOTS from './CLUSTER_SLOTS'; import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; +import COPY from './COPY'; import DECR from './DECR'; import DECRBY from './DECRBY'; import DEL from './DEL'; @@ -267,6 +268,8 @@ export default { clusterMyId: CLUSTER_MYID, CLUSTER_REPLICATE, clusterReplicate: CLUSTER_REPLICATE, + COPY, + copy: COPY, DECR, decr: DECR, DECRBY, From 73994f243b0846150642c0ae0acf6f8e1802bb5d Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 20:06:31 -0400 Subject: [PATCH 051/325] fix EXPIRE spec --- packages/client/lib/commands/EXPIRE.spec.ts | 43 +++++++++++---------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/client/lib/commands/EXPIRE.spec.ts b/packages/client/lib/commands/EXPIRE.spec.ts index 39f9d70bd93..ff0ac667767 100644 --- a/packages/client/lib/commands/EXPIRE.spec.ts +++ b/packages/client/lib/commands/EXPIRE.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EXPIRE'; +import EXPIRE from './EXPIRE'; describe('EXPIRE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 1), - ['EXPIRE', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + EXPIRE.transformArguments('key', 1), + ['EXPIRE', 'key', '1'] + ); + }); - it('with set option', () => { - assert.deepEqual( - transformArguments('key', 1, 'NX'), - ['EXPIRE', 'key', '1', 'NX'] - ); - }); + it('with set option', () => { + assert.deepEqual( + EXPIRE.transformArguments('key', 1, 'NX'), + ['EXPIRE', 'key', '1', 'NX'] + ); }); + }); - testUtils.testWithClient('client.expire', async client => { - assert.equal( - await client.expire('key', 0), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('expire', async client => { + assert.equal( + await client.expire('key', 0), + false + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 6eee5e38192..1deded3ca28 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -96,6 +96,7 @@ import MSET from './MSET'; import MSETNX from './MSETNX'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; +import EXPIRE from './EXPIRE'; import PEXPIRE from './PEXPIRE'; import PEXPIREAT from './PEXPIREAT'; import PEXPIRETIME from './PEXPIRETIME'; @@ -378,6 +379,8 @@ export default { persist: PERSIST, EXISTS, exists: EXISTS, + EXPIRE, + expire: EXPIRE, PEXPIRE, pExpire: PEXPIRE, PEXPIREAT, From fe1ae49a40c5ed7a6538caa553d030c7111f9e9b Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 20:13:27 -0400 Subject: [PATCH 052/325] fix EXPIREAT spec --- packages/client/lib/commands/EXPIREAT.spec.ts | 59 ++++++++++--------- packages/client/lib/commands/EXPIREAT.ts | 2 +- packages/client/lib/commands/index.ts | 3 + 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/packages/client/lib/commands/EXPIREAT.spec.ts b/packages/client/lib/commands/EXPIREAT.spec.ts index 0335b36f5f5..45677f8835d 100644 --- a/packages/client/lib/commands/EXPIREAT.spec.ts +++ b/packages/client/lib/commands/EXPIREAT.spec.ts @@ -1,36 +1,39 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EXPIREAT'; +import EXPIREAT from './EXPIREAT'; describe('EXPIREAT', () => { - describe('transformArguments', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', 1), - ['EXPIREAT', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('number', () => { + assert.deepEqual( + EXPIREAT.transformArguments('key', 1), + ['EXPIREAT', 'key', '1'] + ); + }); + + it('date', () => { + const d = new Date(); + assert.deepEqual( + EXPIREAT.transformArguments('key', d), + ['EXPIREAT', 'key', Math.floor(d.getTime() / 1000).toString()] + ); + }); - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', d), - ['EXPIREAT', 'key', Math.floor(d.getTime() / 1000).toString()] - ); - }); - - it('with set option', () => { - assert.deepEqual( - transformArguments('key', 1, 'GT'), - ['EXPIREAT', 'key', '1', 'GT'] - ); - }); + it('with set option', () => { + assert.deepEqual( + EXPIREAT.transformArguments('key', 1, 'GT'), + ['EXPIREAT', 'key', '1', 'GT'] + ); }); + }); - testUtils.testWithClient('client.expireAt', async client => { - assert.equal( - await client.expireAt('key', 1), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('expireAt', async client => { + assert.equal( + await client.expireAt('key', 1), + false + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/EXPIREAT.ts b/packages/client/lib/commands/EXPIREAT.ts index b9b5986caca..9a959a87f99 100644 --- a/packages/client/lib/commands/EXPIREAT.ts +++ b/packages/client/lib/commands/EXPIREAT.ts @@ -9,7 +9,7 @@ export default { timestamp: number | Date, mode?: 'NX' | 'XX' | 'GT' | 'LT' ) { - const args = ['EXPIRE', key, transformEXAT(timestamp)]; + const args = ['EXPIREAT', key, transformEXAT(timestamp)]; if (mode) { args.push(mode); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 1deded3ca28..cb365ad99e0 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -97,6 +97,7 @@ import MSETNX from './MSETNX'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; +import EXPIREAT from './EXPIREAT'; import PEXPIRE from './PEXPIRE'; import PEXPIREAT from './PEXPIREAT'; import PEXPIRETIME from './PEXPIRETIME'; @@ -381,6 +382,8 @@ export default { exists: EXISTS, EXPIRE, expire: EXPIRE, + EXPIREAT, + expireAt: EXPIREAT, PEXPIRE, pExpire: PEXPIRE, PEXPIREAT, From 2ea068ac77674123d79f94707f8c835a756a1388 Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 20:17:15 -0400 Subject: [PATCH 053/325] fix EXPIRETIME spec --- .../client/lib/commands/EXPIRETIME.spec.ts | 31 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/commands/EXPIRETIME.spec.ts b/packages/client/lib/commands/EXPIRETIME.spec.ts index 1d63e759a5d..8936c7638dc 100644 --- a/packages/client/lib/commands/EXPIRETIME.spec.ts +++ b/packages/client/lib/commands/EXPIRETIME.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EXPIRETIME'; +import EXPIRETIME from './EXPIRETIME'; describe('EXPIRETIME', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['EXPIRETIME', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EXPIRETIME.transformArguments('key'), + ['EXPIRETIME', 'key'] + ); + }); - testUtils.testWithClient('client.expireTime', async client => { - assert.equal( - await client.expireTime('key'), - -2 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('expireTime', async client => { + assert.equal( + await client.expireTime('key'), + -2 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index cb365ad99e0..7aca8d7136c 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -98,6 +98,7 @@ import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; import EXPIREAT from './EXPIREAT'; +import EXPIRETIME from './EXPIRETIME'; import PEXPIRE from './PEXPIRE'; import PEXPIREAT from './PEXPIREAT'; import PEXPIRETIME from './PEXPIRETIME'; @@ -384,6 +385,8 @@ export default { expire: EXPIRE, EXPIREAT, expireAt: EXPIREAT, + EXPIRETIME, + expireTime: EXPIRETIME, PEXPIRE, pExpire: PEXPIRE, PEXPIREAT, From d810ce644b80a7e4af965c385cfe748722db5c6c Mon Sep 17 00:00:00 2001 From: dovi Date: Tue, 2 May 2023 20:22:11 -0400 Subject: [PATCH 054/325] fix KEYS spec --- packages/client/lib/commands/KEYS.spec.ts | 15 +++++++++------ packages/client/lib/commands/KEYS.ts | 1 + packages/client/lib/commands/index.ts | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/client/lib/commands/KEYS.spec.ts b/packages/client/lib/commands/KEYS.spec.ts index c066331ea7c..34dbaf6f2c9 100644 --- a/packages/client/lib/commands/KEYS.spec.ts +++ b/packages/client/lib/commands/KEYS.spec.ts @@ -2,10 +2,13 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('KEYS', () => { - testUtils.testWithClient('client.keys', async client => { - assert.deepEqual( - await client.keys('pattern'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.keys', async client => { + assert.deepEqual( + await client.keys('pattern'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/KEYS.ts b/packages/client/lib/commands/KEYS.ts index 507681a56aa..488ba1154c9 100644 --- a/packages/client/lib/commands/KEYS.ts +++ b/packages/client/lib/commands/KEYS.ts @@ -1,6 +1,7 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(pattern: RedisArgument) { return ['KEYS', pattern]; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 7aca8d7136c..7644ef2c9b9 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -72,6 +72,7 @@ import INCR from './INCR'; import INCRBY from './INCRBY'; import INCRBYFLOAT from './INCRBYFLOAT'; import INFO from './INFO'; +import KEYS from './KEYS'; // import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; // import LCS_IDX from './LCS_IDX'; import LCS_LEN from './LCS_LEN'; @@ -335,6 +336,8 @@ export default { incrByFloat: INCRBYFLOAT, INFO, info: INFO, + KEYS, + keys: KEYS, // LCS_IDX_WITHMATCHLEN, // LCS_IDX, LCS_LEN, From e85fa11e81f27839542d98dde1228573ed741605 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:07:30 -0400 Subject: [PATCH 055/325] fix MOVE spec --- packages/client/lib/commands/MOVE.spec.ts | 7 +++++-- packages/client/lib/commands/index.ts | 3 +++ todo.md | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts index f6fcfdbad4c..63e10c8e107 100644 --- a/packages/client/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -10,10 +10,13 @@ describe('MOVE', () => { ); }); - testUtils.testWithClient('client.move', async client => { + testUtils.testAll('move', async client => { assert.equal( await client.move('key', 1), 1 ); - }, GLOBAL.SERVERS.OPEN); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 7644ef2c9b9..b439c7ff10a 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -93,6 +93,7 @@ import LREM from './LREM'; import LSET from './LSET'; import LTRIM from './LTRIM'; import MGET from './MGET'; +import MOVE from './MOVE'; import MSET from './MSET'; import MSETNX from './MSETNX'; import PERSIST from './PERSIST'; @@ -376,6 +377,8 @@ export default { lTrim: LTRIM, MGET, mGet: MGET, + MOVE, + move: MOVE, MSET, mSet: MSET, MSETNX, diff --git a/todo.md b/todo.md index bb05f695e45..aea88196df3 100644 --- a/todo.md +++ b/todo.md @@ -11,7 +11,7 @@ # waiting List categoreis -- Generic +- Generic - String - Hash - List @@ -27,6 +27,7 @@ - `ZPOPMIN.ts` - `ZREVRANGE WITHSCORE` - `ZRANK WITHSCORE` +- `MIGRATE` # other From 19cd6dc04a1131f0d2914174f747c75a484eee9a Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:12:31 -0400 Subject: [PATCH 056/325] fix OBJECT_ENCODING spec --- .../lib/commands/OBJECT_ENCODING.spec.ts | 29 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/OBJECT_ENCODING.spec.ts b/packages/client/lib/commands/OBJECT_ENCODING.spec.ts index 6f42969d547..0ea77767b8b 100644 --- a/packages/client/lib/commands/OBJECT_ENCODING.spec.ts +++ b/packages/client/lib/commands/OBJECT_ENCODING.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJECT_ENCODING'; +import OBJECT_ENCODING from './OBJECT_ENCODING'; describe('OBJECT ENCODING', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['OBJECT', 'ENCODING', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + OBJECT_ENCODING.transformArguments('key'), + ['OBJECT', 'ENCODING', 'key'] + ); + }); - testUtils.testWithClient('client.objectEncoding', async client => { - assert.equal( - await client.objectEncoding('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('objectEncoding', async client => { + assert.equal( + await client.objectEncoding('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index b439c7ff10a..c75d300b069 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -96,6 +96,7 @@ import MGET from './MGET'; import MOVE from './MOVE'; import MSET from './MSET'; import MSETNX from './MSETNX'; +import OBJECT_ENCODING from './OBJECT_ENCODING'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; @@ -383,6 +384,8 @@ export default { mSet: MSET, MSETNX, mSetNX: MSETNX, + OBJECT_ENCODING, + objectEncoding: OBJECT_ENCODING, PERSIST, persist: PERSIST, EXISTS, From 1a7d5ff8e470672746adac82bbce0389f7191152 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:15:42 -0400 Subject: [PATCH 057/325] fix OBJECT_FREQ spec --- .../client/lib/commands/OBJECT_FREQ.spec.ts | 29 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/OBJECT_FREQ.spec.ts b/packages/client/lib/commands/OBJECT_FREQ.spec.ts index 6d2513cf18c..e072d371649 100644 --- a/packages/client/lib/commands/OBJECT_FREQ.spec.ts +++ b/packages/client/lib/commands/OBJECT_FREQ.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJECT_FREQ'; +import OBJECT_FREQ from './OBJECT_FREQ'; describe('OBJECT FREQ', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['OBJECT', 'FREQ', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + OBJECT_FREQ.transformArguments('key'), + ['OBJECT', 'FREQ', 'key'] + ); + }); - testUtils.testWithClient('client.objectFreq', async client => { - assert.equal( - await client.objectFreq('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.objectFreq', async client => { + assert.equal( + await client.objectFreq('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c75d300b069..a2a6f737641 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -97,6 +97,7 @@ import MOVE from './MOVE'; import MSET from './MSET'; import MSETNX from './MSETNX'; import OBJECT_ENCODING from './OBJECT_ENCODING'; +import OBJECT_FREQ from './OBJECT_FREQ'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; @@ -386,6 +387,8 @@ export default { mSetNX: MSETNX, OBJECT_ENCODING, objectEncoding: OBJECT_ENCODING, + OBJECT_FREQ, + objectFreq: OBJECT_FREQ, PERSIST, persist: PERSIST, EXISTS, From 3ab624165607da9e18f8486a540295055965e6c3 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:18:15 -0400 Subject: [PATCH 058/325] fix OBJECT_IDLETIME spec --- .../lib/commands/OBJECT_IDLETIME.spec.ts | 29 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts b/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts index 61529e1366b..ed908d142fe 100644 --- a/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts +++ b/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJECT_IDLETIME'; +import OBJECT_IDLETIME from './OBJECT_IDLETIME'; describe('OBJECT IDLETIME', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['OBJECT', 'IDLETIME', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + OBJECT_IDLETIME.transformArguments('key'), + ['OBJECT', 'IDLETIME', 'key'] + ); + }); - testUtils.testWithClient('client.objectIdleTime', async client => { - assert.equal( - await client.objectIdleTime('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.objectIdleTime', async client => { + assert.equal( + await client.objectIdleTime('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index a2a6f737641..ed6a42ec8ef 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -98,6 +98,7 @@ import MSET from './MSET'; import MSETNX from './MSETNX'; import OBJECT_ENCODING from './OBJECT_ENCODING'; import OBJECT_FREQ from './OBJECT_FREQ'; +import OBJECT_IDLETIME from './OBJECT_IDLETIME'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; @@ -389,6 +390,8 @@ export default { objectEncoding: OBJECT_ENCODING, OBJECT_FREQ, objectFreq: OBJECT_FREQ, + OBJECT_IDLETIME, + objectIdleTime: OBJECT_IDLETIME, PERSIST, persist: PERSIST, EXISTS, From 7d963a5d1bd0d21f1ef99dbf3a34d0cd83201d34 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:21:37 -0400 Subject: [PATCH 059/325] fix OBJECT_REFCOUNT spec --- .../lib/commands/OBJECT_REFCOUNT.spec.ts | 29 ++++++++++--------- packages/client/lib/commands/index.ts | 3 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts b/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts index 199dca3fe82..f0c50c8aaf3 100644 --- a/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts +++ b/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJECT_REFCOUNT'; +import OBJECT_REFCOUNT from './OBJECT_REFCOUNT'; describe('OBJECT REFCOUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['OBJECT', 'REFCOUNT', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + OBJECT_REFCOUNT.transformArguments('key'), + ['OBJECT', 'REFCOUNT', 'key'] + ); + }); - testUtils.testWithClient('client.objectRefCount', async client => { - assert.equal( - await client.objectRefCount('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('client.objectRefCount', async client => { + assert.equal( + await client.objectRefCount('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index ed6a42ec8ef..7bc56569829 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -99,6 +99,7 @@ import MSETNX from './MSETNX'; import OBJECT_ENCODING from './OBJECT_ENCODING'; import OBJECT_FREQ from './OBJECT_FREQ'; import OBJECT_IDLETIME from './OBJECT_IDLETIME'; +import OBJECT_REFCOUNT from './OBJECT_REFCOUNT'; import PERSIST from './PERSIST'; import EXISTS from './EXISTS'; import EXPIRE from './EXPIRE'; @@ -392,6 +393,8 @@ export default { objectFreq: OBJECT_FREQ, OBJECT_IDLETIME, objectIdleTime: OBJECT_IDLETIME, + OBJECT_REFCOUNT, + objectRefCount: OBJECT_REFCOUNT, PERSIST, persist: PERSIST, EXISTS, From 485a4f3adca38d3e44a9145a3d99ccaa4c05b7fb Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:26:25 -0400 Subject: [PATCH 060/325] fix RANDOMKEY spec --- packages/client/lib/commands/RANDOMKEY.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/RANDOMKEY.spec.ts b/packages/client/lib/commands/RANDOMKEY.spec.ts index 8cd74669c55..240fc03de10 100644 --- a/packages/client/lib/commands/RANDOMKEY.spec.ts +++ b/packages/client/lib/commands/RANDOMKEY.spec.ts @@ -10,10 +10,13 @@ describe('RANDOMKEY', () => { ); }); - testUtils.testWithClient('client.randomKey', async client => { + testUtils.testAll('randomKey', async client => { assert.equal( await client.randomKey(), null ); - }, GLOBAL.SERVERS.OPEN); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 1cb0c093219e437f11f729f84a857cac438a23db Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:29:40 -0400 Subject: [PATCH 061/325] RENAMENX clean code --- packages/client/lib/commands/RENAMENX.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts index 01dedc87798..4beff2437bc 100644 --- a/packages/client/lib/commands/RENAMENX.ts +++ b/packages/client/lib/commands/RENAMENX.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { IS_READ_ONLY: true, From 4c5d7a3d4e7136f197fbc4f28e8aad9debc6ee32 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:34:22 -0400 Subject: [PATCH 062/325] fix SCAN spec --- packages/client/lib/commands/SCAN.spec.ts | 7 +++++-- todo.md | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts index b2c10af0af1..baf3682954e 100644 --- a/packages/client/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -50,7 +50,7 @@ describe('SCAN', () => { }); }); - testUtils.testWithClient('client.scan', async client => { + testUtils.testAll('scan', async client => { assert.deepEqual( await client.scan(0), { @@ -58,5 +58,8 @@ describe('SCAN', () => { keys: [] } ); - }, GLOBAL.SERVERS.OPEN); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/todo.md b/todo.md index aea88196df3..949f9b3d6cd 100644 --- a/todo.md +++ b/todo.md @@ -11,7 +11,7 @@ # waiting List categoreis -- Generic +- Generic - String - Hash - List @@ -28,6 +28,7 @@ - `ZREVRANGE WITHSCORE` - `ZRANK WITHSCORE` - `MIGRATE` +- `RESTORE` # other From 39f2318d477d8a1b4786ac372e967018056d8da3 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:36:30 -0400 Subject: [PATCH 063/325] SORT_RO clean code --- packages/client/lib/commands/SORT_RO.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/SORT_RO.spec.ts b/packages/client/lib/commands/SORT_RO.spec.ts index d1349df2274..c49efc11b3b 100644 --- a/packages/client/lib/commands/SORT_RO.spec.ts +++ b/packages/client/lib/commands/SORT_RO.spec.ts @@ -89,7 +89,7 @@ describe('SORT_RO', () => { }); }); - testUtils.testAll('client.sortRo', async client => { + testUtils.testAll('sortRo', async client => { assert.deepEqual( await client.sortRo('key'), [] From f2326e5efae9bc3ea07778453d52358d9f14e76e Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:38:51 -0400 Subject: [PATCH 064/325] TTL clean code --- packages/client/lib/commands/TTL.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/client/lib/commands/TTL.spec.ts b/packages/client/lib/commands/TTL.spec.ts index 05c75851ee8..792f022593e 100644 --- a/packages/client/lib/commands/TTL.spec.ts +++ b/packages/client/lib/commands/TTL.spec.ts @@ -11,7 +11,6 @@ describe('TTL', () => { }); testUtils.testAll('ttl', async client => { - console.log(await client.get('key'), await client.ttl('key')); assert.equal( await client.ttl('key'), -2 From 3050cc8659a5d2286cc38f00f4a0cd8f16e0e3f5 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:42:31 -0400 Subject: [PATCH 065/325] fix WAIT spec & clean code --- packages/client/lib/commands/WAIT.spec.ts | 7 +++++-- packages/client/lib/commands/WAIT.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/commands/WAIT.spec.ts b/packages/client/lib/commands/WAIT.spec.ts index 8a8fb3a36c4..2b8c1de319c 100644 --- a/packages/client/lib/commands/WAIT.spec.ts +++ b/packages/client/lib/commands/WAIT.spec.ts @@ -10,10 +10,13 @@ describe('WAIT', () => { ); }); - testUtils.testWithClient('client.wait', async client => { + testUtils.testAll('wait', async client => { assert.equal( await client.wait(0, 1), 0 ); - }, GLOBAL.SERVERS.OPEN); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/WAIT.ts b/packages/client/lib/commands/WAIT.ts index 5c4bd156a62..21c39a643e5 100644 --- a/packages/client/lib/commands/WAIT.ts +++ b/packages/client/lib/commands/WAIT.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; +import { NumberReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, From e4b8370c030c4e53f365f50669f90452b82eda73 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:46:09 -0400 Subject: [PATCH 066/325] fix DECR spec --- packages/client/lib/commands/DECR.spec.ts | 29 +++++++++++++---------- todo.md | 4 ++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/client/lib/commands/DECR.spec.ts b/packages/client/lib/commands/DECR.spec.ts index 75e1205feda..aa7f2ad5c0a 100644 --- a/packages/client/lib/commands/DECR.spec.ts +++ b/packages/client/lib/commands/DECR.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DECR'; +import DECR from './DECR'; describe('DECR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['DECR', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DECR.transformArguments('key'), + ['DECR', 'key'] + ); + }); - testUtils.testWithClient('client.decr', async client => { - assert.equal( - await client.decr('key'), - -1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('decr', async client => { + assert.equal( + await client.decr('key'), + -1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/todo.md b/todo.md index 949f9b3d6cd..402afc073f1 100644 --- a/todo.md +++ b/todo.md @@ -11,8 +11,7 @@ # waiting List categoreis -- Generic -- String +- String - Hash - List - Set @@ -29,6 +28,7 @@ - `ZRANK WITHSCORE` - `MIGRATE` - `RESTORE` +- `WAITAOF` # other From 642c823d1b3cc5b1d0e837ed142dae6af7697ee6 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:50:33 -0400 Subject: [PATCH 067/325] fix DECRBY --- packages/client/lib/commands/DECRBY.spec.ts | 29 ++++++++++++--------- packages/client/lib/commands/DECRBY.ts | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/commands/DECRBY.spec.ts b/packages/client/lib/commands/DECRBY.spec.ts index d2c23e94728..60c18c4b06c 100644 --- a/packages/client/lib/commands/DECRBY.spec.ts +++ b/packages/client/lib/commands/DECRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DECRBY'; +import DECRBY from './DECRBY'; describe('DECRBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 2), - ['DECRBY', 'key', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 2), + ['DECRBY', 'key', '2'] + ); + }); - testUtils.testWithClient('client.decrBy', async client => { - assert.equal( - await client.decrBy('key', 2), - -2 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('decrBy', async client => { + assert.equal( + await client.decrBy('key', 2), + -2 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/DECRBY.ts b/packages/client/lib/commands/DECRBY.ts index 4a22aeb34cd..77d56939dd5 100644 --- a/packages/client/lib/commands/DECRBY.ts +++ b/packages/client/lib/commands/DECRBY.ts @@ -3,7 +3,7 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: 1, transformArguments(key: RedisArgument, decrement: number) { - return ['DECR', key, decrement.toString()]; + return ['DECRBY', key, decrement.toString()]; }, transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; From 9dd536edd90b08ec9590c5278dc323f1887b41d1 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:54:18 -0400 Subject: [PATCH 068/325] fix GET spec --- packages/client/lib/commands/GET.spec.ts | 43 +++++++++--------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/packages/client/lib/commands/GET.spec.ts b/packages/client/lib/commands/GET.spec.ts index 2946ea19b60..9e131694b11 100644 --- a/packages/client/lib/commands/GET.spec.ts +++ b/packages/client/lib/commands/GET.spec.ts @@ -1,33 +1,22 @@ import { strict as assert } from 'assert'; -import RedisClient from '../client'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GET'; +import GET from './GET'; describe('GET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GET', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GET.transformArguments('key'), + ['GET', 'key'] + ); + }); - testUtils.testWithClient('client.get', async client => { - const a = await client.get( - 'key' - ); - - - - assert.equal( - await client.get('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.get', async cluster => { - assert.equal( - await cluster.get('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('get', async client => { + assert.equal( + await client.get('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From e0bc86346ed1f83721a9a9e8b007ee3f3f4ffa62 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 14:58:34 -0400 Subject: [PATCH 069/325] fix GETDEL spec --- packages/client/lib/commands/GETDEL.spec.ts | 38 +++++++++------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/client/lib/commands/GETDEL.spec.ts b/packages/client/lib/commands/GETDEL.spec.ts index db3a486696a..cbb7553cfeb 100644 --- a/packages/client/lib/commands/GETDEL.spec.ts +++ b/packages/client/lib/commands/GETDEL.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETDEL'; +import GETDEL from './GETDEL'; describe('GETDEL', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GETDEL', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETDEL.transformArguments('key'), + ['GETDEL', 'key'] + ); + }); - testUtils.testWithClient('client.getDel', async client => { - assert.equal( - await client.getDel('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.getDel', async cluster => { - assert.equal( - await cluster.getDel('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getDel', async client => { + assert.equal( + await client.getDel('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From c6b21eab520c32a38a799160a5af039eaf424770 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:02:40 -0400 Subject: [PATCH 070/325] fix GETEX spec --- packages/client/lib/commands/GETEX.spec.ts | 158 ++++++++++----------- 1 file changed, 76 insertions(+), 82 deletions(-) diff --git a/packages/client/lib/commands/GETEX.spec.ts b/packages/client/lib/commands/GETEX.spec.ts index 1bf86089da1..7db4f4c345a 100644 --- a/packages/client/lib/commands/GETEX.spec.ts +++ b/packages/client/lib/commands/GETEX.spec.ts @@ -1,96 +1,90 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETEX'; +import GETEX from './GETEX'; describe('GETEX', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('EX', () => { - assert.deepEqual( - transformArguments('key', { - EX: 1 - }), - ['GETEX', 'key', 'EX', '1'] - ); - }); - - it('PX', () => { - assert.deepEqual( - transformArguments('key', { - PX: 1 - }), - ['GETEX', 'key', 'PX', '1'] - ); - }); - - describe('EXAT', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', { - EXAT: 1 - }), - ['GETEX', 'key', 'EXAT', '1'] - ); - }); - - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', { - EXAT: d - }), - ['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()] - ); - }); - }); + describe('transformArguments', () => { + it('EX', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + EX: 1 + }), + ['GETEX', 'key', 'EX', '1'] + ); + }); - describe('PXAT', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', { - PXAT: 1 - }), - ['GETEX', 'key', 'PXAT', '1'] - ); - }); + it('PX', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PX: 1 + }), + ['GETEX', 'key', 'PX', '1'] + ); + }); - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', { - PXAT: d - }), - ['GETEX', 'key', 'PXAT', d.getTime().toString()] - ); - }); - }); + describe('EXAT', () => { + it('number', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + EXAT: 1 + }), + ['GETEX', 'key', 'EXAT', '1'] + ); + }); - it('PERSIST', () => { - assert.deepEqual( - transformArguments('key', { - PERSIST: true - }), - ['GETEX', 'key', 'PERSIST'] - ); - }); + it('date', () => { + const d = new Date(); + assert.deepEqual( + GETEX.transformArguments('key', { + EXAT: d + }), + ['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()] + ); + }); }); - testUtils.testWithClient('client.getEx', async client => { - assert.equal( - await client.getEx('key', { - PERSIST: true - }), - null + describe('PXAT', () => { + it('number', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PXAT: 1 + }), + ['GETEX', 'key', 'PXAT', '1'] ); - }, GLOBAL.SERVERS.OPEN); + }); - testUtils.testWithCluster('cluster.getEx', async cluster => { - assert.equal( - await cluster.getEx('key', { - PERSIST: true - }), - null + it('date', () => { + const d = new Date(); + assert.deepEqual( + GETEX.transformArguments('key', { + PXAT: d + }), + ['GETEX', 'key', 'PXAT', d.getTime().toString()] ); - }, GLOBAL.CLUSTERS.OPEN); + }); + }); + + it('PERSIST', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PERSIST: true + }), + ['GETEX', 'key', 'PERSIST'] + ); + }); + }); + + testUtils.testAll('getEx', async client => { + assert.equal( + await client.getEx('key', { + PERSIST: true + }), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 58af728055f552c10901ad5c3e20cfa6a3205d69 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:04:37 -0400 Subject: [PATCH 071/325] fix GETRANGE spec --- packages/client/lib/commands/GETRANGE.spec.ts | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/packages/client/lib/commands/GETRANGE.spec.ts b/packages/client/lib/commands/GETRANGE.spec.ts index 0c9dbc2c70f..1a31e1a76f0 100644 --- a/packages/client/lib/commands/GETRANGE.spec.ts +++ b/packages/client/lib/commands/GETRANGE.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETRANGE'; +import GETRANGE from './GETRANGE'; describe('GETRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, -1), - ['GETRANGE', 'key', '0', '-1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETRANGE.transformArguments('key', 0, -1), + ['GETRANGE', 'key', '0', '-1'] + ); + }); - testUtils.testWithClient('client.getRange', async client => { - assert.equal( - await client.getRange('key', 0, -1), - '' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lTrim', async cluster => { - assert.equal( - await cluster.getRange('key', 0, -1), - '' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getRange', async client => { + assert.equal( + await client.getRange('key', 0, -1), + '' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From b34e5248800280f35041f2aa7ffb6f1ba6f201d9 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:06:41 -0400 Subject: [PATCH 072/325] fix GETSET spec --- packages/client/lib/commands/GETSET.spec.ts | 36 +++++++++------------ 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/packages/client/lib/commands/GETSET.spec.ts b/packages/client/lib/commands/GETSET.spec.ts index 73fbcec57ea..f52c2f29293 100644 --- a/packages/client/lib/commands/GETSET.spec.ts +++ b/packages/client/lib/commands/GETSET.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETSET'; +import GETSET from './GETSET'; describe('GETSET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'value'), - ['GETSET', 'key', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETSET.transformArguments('key', 'value'), + ['GETSET', 'key', 'value'] + ); + }); - testUtils.testWithClient('client.getSet', async client => { - assert.equal( - await client.getSet('key', 'value'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.getSet', async cluster => { - assert.equal( - await cluster.getSet('key', 'value'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getSet', async client => { + assert.equal( + await client.getSet('key', 'value'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 8d4421a8c1dd242dec6ebc0f6e17f14bb4ed5502 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:10:02 -0400 Subject: [PATCH 073/325] fix INCR spec --- packages/client/lib/commands/INCR.spec.ts | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/INCR.spec.ts b/packages/client/lib/commands/INCR.spec.ts index 321d83edc54..76a849aa4c2 100644 --- a/packages/client/lib/commands/INCR.spec.ts +++ b/packages/client/lib/commands/INCR.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCR'; +import INCR from './INCR'; describe('INCR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['INCR', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + INCR.transformArguments('key'), + ['INCR', 'key'] + ); + }); - testUtils.testWithClient('client.incr', async client => { - assert.equal( - await client.incr('key'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incr', async client => { + assert.equal( + await client.incr('key'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From c0834879f35d158791847c8c4a910485cc85b736 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:15:08 -0400 Subject: [PATCH 074/325] fix INCRBY spec --- packages/client/lib/commands/INCRBY.spec.ts | 31 +++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/commands/INCRBY.spec.ts b/packages/client/lib/commands/INCRBY.spec.ts index a671d0ec259..08c84a437b3 100644 --- a/packages/client/lib/commands/INCRBY.spec.ts +++ b/packages/client/lib/commands/INCRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCRBY'; +import INCRBY from './INCRBY'; -describe('INCR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['INCRBY', 'key', '1'] - ); - }); +describe('INCRBY', () => { + it('transformArguments', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1), + ['INCRBY', 'key', '1'] + ); + }); - testUtils.testWithClient('client.incrBy', async client => { - assert.equal( - await client.incrBy('key', 1), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incrBy', async client => { + assert.equal( + await client.incrBy('key', 1), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From e1c5af6f410c3ed8f7c5ef0213259b6c7a7d3987 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:17:47 -0400 Subject: [PATCH 075/325] fix INCRBYFLOAT spec --- .../client/lib/commands/INCRBYFLOAT.spec.ts | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/INCRBYFLOAT.spec.ts b/packages/client/lib/commands/INCRBYFLOAT.spec.ts index b2dd5aa5da9..79daac612ea 100644 --- a/packages/client/lib/commands/INCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/INCRBYFLOAT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCRBYFLOAT'; +import INCRBYFLOAT from './INCRBYFLOAT'; describe('INCRBYFLOAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1.5), - ['INCRBYFLOAT', 'key', '1.5'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + INCRBYFLOAT.transformArguments('key', 1.5), + ['INCRBYFLOAT', 'key', '1.5'] + ); + }); - testUtils.testWithClient('client.incrByFloat', async client => { - assert.equal( - await client.incrByFloat('key', 1.5), - '1.5' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incrByFloat', async client => { + assert.equal( + await client.incrByFloat('key', 1.5), + '1.5' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 708b71a2b042a2572772b2ddf688da5c6154cd43 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:20:10 -0400 Subject: [PATCH 076/325] fix LCS spec --- packages/client/lib/commands/LCS.spec.ts | 38 +++++++++++------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/client/lib/commands/LCS.spec.ts b/packages/client/lib/commands/LCS.spec.ts index a4d9035571e..b24ba2c6f22 100644 --- a/packages/client/lib/commands/LCS.spec.ts +++ b/packages/client/lib/commands/LCS.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LCS'; +import LCS from './LCS'; describe('LCS', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('1', '2'), - ['LCS', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LCS.transformArguments('1', '2'), + ['LCS', '1', '2'] + ); + }); - testUtils.testWithClient('client.lcs', async client => { - assert.equal( - await client.lcs('1', '2'), - '' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lcs', async cluster => { - assert.equal( - await cluster.lcs('{tag}1', '{tag}2'), - '' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lcs', async client => { + assert.equal( + await client.lcs('{tag}1', '{tag}2'), + '' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 2899653cd30adc50472e6166f4b6375198aab80a Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:22:43 -0400 Subject: [PATCH 077/325] fix MSET spec --- packages/client/lib/commands/MSET.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/MSET.spec.ts b/packages/client/lib/commands/MSET.spec.ts index 8de2f9fe2df..d8161b179f2 100644 --- a/packages/client/lib/commands/MSET.spec.ts +++ b/packages/client/lib/commands/MSET.spec.ts @@ -28,7 +28,7 @@ describe('MSET', () => { testUtils.testAll('mSet', async client => { assert.equal( - await client.mSet(['key1', 'value1', 'key2', 'value2']), + await client.mSet(['{tag}key1', 'value1', '{tag}key2', 'value2']), 'OK' ); }, { From afc33764e9cae697bea2dd2e880f06dffdd8a7c9 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:30:55 -0400 Subject: [PATCH 078/325] fix HDEL spec --- packages/client/lib/commands/HDEL.spec.ts | 43 ++++++++++++----------- todo.md | 1 - 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/client/lib/commands/HDEL.spec.ts b/packages/client/lib/commands/HDEL.spec.ts index eb24bcfacbd..c87b20397ee 100644 --- a/packages/client/lib/commands/HDEL.spec.ts +++ b/packages/client/lib/commands/HDEL.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HDEL'; +import HDEL from './HDEL'; describe('HDEL', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HDEL', 'key', 'field'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + HDEL.transformArguments('key', 'field'), + ['HDEL', 'key', 'field'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['HDEL', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + HDEL.transformArguments('key', ['1', '2']), + ['HDEL', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.hDel', async client => { - assert.equal( - await client.hDel('key', 'field'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hDel', async client => { + assert.equal( + await client.hDel('key', 'field'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/todo.md b/todo.md index 402afc073f1..53d90d83ea8 100644 --- a/todo.md +++ b/todo.md @@ -11,7 +11,6 @@ # waiting List categoreis -- String - Hash - List - Set From 9697cbbe25449fad2efa26b15508be4d2dab2c40 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:33:35 -0400 Subject: [PATCH 079/325] fix HEXISTS spec --- packages/client/lib/commands/HEXISTS.spec.ts | 29 +++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HEXISTS.spec.ts b/packages/client/lib/commands/HEXISTS.spec.ts index 3764319c123..fae7c11f2b0 100644 --- a/packages/client/lib/commands/HEXISTS.spec.ts +++ b/packages/client/lib/commands/HEXISTS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HEXISTS'; +import HEXISTS from './HEXISTS'; describe('HEXISTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HEXISTS', 'key', 'field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HEXISTS.transformArguments('key', 'field'), + ['HEXISTS', 'key', 'field'] + ); + }); - testUtils.testWithClient('client.hExists', async client => { - assert.equal( - await client.hExists('key', 'field'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hExists', async client => { + assert.equal( + await client.hExists('key', 'field'), + false + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 9177315667385c7f23a406677e2669355f490517 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 15:35:20 -0400 Subject: [PATCH 080/325] fix HGET spec --- packages/client/lib/commands/HGET.spec.ts | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HGET.spec.ts b/packages/client/lib/commands/HGET.spec.ts index 6b6d0a3ee22..33824d903a1 100644 --- a/packages/client/lib/commands/HGET.spec.ts +++ b/packages/client/lib/commands/HGET.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HGET'; +import HGET from './HGET'; describe('HGET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HGET', 'key', 'field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HGET.transformArguments('key', 'field'), + ['HGET', 'key', 'field'] + ); + }); - testUtils.testWithClient('client.hGet', async client => { - assert.equal( - await client.hGet('key', 'field'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hGet', async client => { + assert.equal( + await client.hGet('key', 'field'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 3bda368acb57cb37f035579301f135fa3f1b764b Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 16:48:52 -0400 Subject: [PATCH 081/325] fix HGETALL spec --- packages/client/lib/commands/HGETALL.spec.ts | 62 +++++++++----------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/packages/client/lib/commands/HGETALL.spec.ts b/packages/client/lib/commands/HGETALL.spec.ts index fcd1a30457c..9a9a30feaf8 100644 --- a/packages/client/lib/commands/HGETALL.spec.ts +++ b/packages/client/lib/commands/HGETALL.spec.ts @@ -1,41 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformReply } from './HGETALL'; describe('HGETALL', () => { - describe('transformReply', () => { - it('empty', () => { - assert.deepEqual( - transformReply([]), - Object.create(null) - ); - }); - it('with values', () => { - assert.deepEqual( - transformReply(['key1', 'value1', 'key2', 'value2']), - Object.create(null, { - key1: { - value: 'value1', - configurable: true, - enumerable: true, - writable: true - }, - key2: { - value: 'value2', - configurable: true, - enumerable: true, - writable: true - } - }) - ); - }); - }); + testUtils.testAll('hGetAll empty', async client => { + assert.deepEqual( + await client.hGetAll('key'), + Object.create(null) + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); - testUtils.testWithClient('client.hGetAll', async client => { - assert.deepEqual( - await client.hGetAll('key'), - Object.create(null) - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hGetAll with value', async client => { + const [, reply] = await Promise.all([ + client.hSet('key', 'field', 'value'), + client.hGetAll('key') + ]); + assert.deepEqual( + reply, + Object.create(null, { + field: { + value: 'value', + enumerable: true, + writable: true + } + }) + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 0516ca32bdc63e71adf0bb2856820ad0c9d82f9b Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 16:50:38 -0400 Subject: [PATCH 082/325] fix HINCRBY spec --- packages/client/lib/commands/HINCRBY.spec.ts | 29 +++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HINCRBY.spec.ts b/packages/client/lib/commands/HINCRBY.spec.ts index de406217921..263f841e3f8 100644 --- a/packages/client/lib/commands/HINCRBY.spec.ts +++ b/packages/client/lib/commands/HINCRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HINCRBY'; +import HINCRBY from './HINCRBY'; describe('HINCRBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field', 1), - ['HINCRBY', 'key', 'field', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HINCRBY.transformArguments('key', 'field', 1), + ['HINCRBY', 'key', 'field', '1'] + ); + }); - testUtils.testWithClient('client.hIncrBy', async client => { - assert.equal( - await client.hIncrBy('key', 'field', 1), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hIncrBy', async client => { + assert.equal( + await client.hIncrBy('key', 'field', 1), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From d9cac4665b51d7464bebc5d7dc7aaf981f76ce5b Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 16:53:36 -0400 Subject: [PATCH 083/325] fix HINCRBYFLOAT spec --- .../client/lib/commands/HINCRBYFLOAT.spec.ts | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts index bd0147a3481..56754ea2cf0 100644 --- a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HINCRBYFLOAT'; +import HINCRBYFLOAT from './HINCRBYFLOAT'; describe('HINCRBYFLOAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field', 1.5), - ['HINCRBYFLOAT', 'key', 'field', '1.5'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HINCRBYFLOAT.transformArguments('key', 'field', 1.5), + ['HINCRBYFLOAT', 'key', 'field', '1.5'] + ); + }); - testUtils.testWithClient('client.hIncrByFloat', async client => { - assert.equal( - await client.hIncrByFloat('key', 'field', 1.5), - '1.5' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hIncrByFloat', async client => { + assert.equal( + await client.hIncrByFloat('key', 'field', 1.5), + '1.5' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 87a6afc4ff2814515e932fbf7f07c7e3c03fc239 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 16:54:51 -0400 Subject: [PATCH 084/325] fix HKEYS spec --- packages/client/lib/commands/HKEYS.spec.ts | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HKEYS.spec.ts b/packages/client/lib/commands/HKEYS.spec.ts index f94538f67d3..080bfa46706 100644 --- a/packages/client/lib/commands/HKEYS.spec.ts +++ b/packages/client/lib/commands/HKEYS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HKEYS'; +import HKEYS from './HKEYS'; describe('HKEYS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HKEYS', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HKEYS.transformArguments('key'), + ['HKEYS', 'key'] + ); + }); - testUtils.testWithClient('client.hKeys', async client => { - assert.deepEqual( - await client.hKeys('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hKeys', async client => { + assert.deepEqual( + await client.hKeys('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From cca7709daec7e9f0f6f86a1fe981d0b41d160898 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 16:56:25 -0400 Subject: [PATCH 085/325] FIX HLEN spec --- packages/client/lib/commands/HLEN.spec.ts | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/commands/HLEN.spec.ts b/packages/client/lib/commands/HLEN.spec.ts index be9d4b13a7d..a0d804dff73 100644 --- a/packages/client/lib/commands/HLEN.spec.ts +++ b/packages/client/lib/commands/HLEN.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HLEN'; +import HLEN from './HLEN'; describe('HLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HLEN.transformArguments('key'), + ['HLEN', 'key'] + ); + }); - testUtils.testWithClient('client.hLen', async client => { - assert.equal( - await client.hLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hLen', async client => { + assert.equal( + await client.hLen('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 77baef5f8c2d291fa4f9ad114e40b8796a156e94 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 17:12:40 -0400 Subject: [PATCH 086/325] fix HMGET --- packages/client/lib/commands/HMGET.spec.ts | 43 ++++++++++++---------- packages/client/lib/commands/HMGET.ts | 2 +- packages/client/lib/commands/index.ts | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/packages/client/lib/commands/HMGET.spec.ts b/packages/client/lib/commands/HMGET.spec.ts index a7c934b760d..e21f67e2c61 100644 --- a/packages/client/lib/commands/HMGET.spec.ts +++ b/packages/client/lib/commands/HMGET.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HMGET'; +import HMGET from './HMGET'; describe('HMGET', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HMGET', 'key', 'field'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + HMGET.transformArguments('key', 'field'), + ['HMGET', 'key', 'field'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['field1', 'field2']), - ['HMGET', 'key', 'field1', 'field2'] - ); - }); + it('array', () => { + assert.deepEqual( + HMGET.transformArguments('key', ['field1', 'field2']), + ['HMGET', 'key', 'field1', 'field2'] + ); }); + }); - testUtils.testWithClient('client.hmGet', async client => { - assert.deepEqual( - await client.hmGet('key', 'field'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hmGet', async client => { + assert.deepEqual( + await client.hmGet('key', 'field'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HMGET.ts b/packages/client/lib/commands/HMGET.ts index 1c4acafdeef..df28a64be09 100644 --- a/packages/client/lib/commands/HMGET.ts +++ b/packages/client/lib/commands/HMGET.ts @@ -8,7 +8,7 @@ export default { key: RedisArgument, fields: RedisVariadicArgument ) { - return pushVariadicArguments(['HMGET'], fields); + return pushVariadicArguments(['HMGET', key], fields); }, transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 7bc56569829..4384c0d7e7f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -316,7 +316,7 @@ export default { HLEN, hLen: HLEN, HMGET, - hMGet: HMGET, + hmGet: HMGET, HRANDFIELD_COUNT_WITHVALUES, hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, HRANDFIELD_COUNT, From 5bbd8f1746fe5cc56cd12ee6aab2722468c163a5 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 17:16:49 -0400 Subject: [PATCH 087/325] fix HRANDFIELD spec --- .../client/lib/commands/HRANDFIELD.spec.ts | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/commands/HRANDFIELD.spec.ts b/packages/client/lib/commands/HRANDFIELD.spec.ts index df0a4fc7a1d..492733c5834 100644 --- a/packages/client/lib/commands/HRANDFIELD.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HRANDFIELD'; +import HRANDFIELD from './HRANDFIELD'; describe('HRANDFIELD', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HRANDFIELD', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HRANDFIELD.transformArguments('key'), + ['HRANDFIELD', 'key'] + ); + }); - testUtils.testWithClient('client.hRandField', async client => { - assert.equal( - await client.hRandField('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hRandField', async client => { + assert.equal( + await client.hRandField('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 331e390befdaee7035abb1ada6cd8d7f10f42d29 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 3 May 2023 17:29:36 -0400 Subject: [PATCH 088/325] WIP --- packages/client/lib/RESP/decoder.ts | 6 +- packages/client/lib/commands/BITOP.spec.ts | 2 +- .../client/lib/commands/CLIENT_CACHING.ts | 1 + .../client/lib/commands/CLIENT_GETNAME.ts | 1 + .../client/lib/commands/CLIENT_GETREDIR.ts | 1 + packages/client/lib/commands/CLIENT_ID.ts | 1 + packages/client/lib/commands/CLIENT_INFO.ts | 1 + packages/client/lib/commands/CLIENT_KILL.ts | 1 + packages/client/lib/commands/CLIENT_LIST.ts | 1 + .../client/lib/commands/CLIENT_NO-EVICT.ts | 1 + packages/client/lib/commands/CLIENT_PAUSE.ts | 1 + .../client/lib/commands/CLIENT_SETNAME.ts | 1 + .../client/lib/commands/CLIENT_UNPAUSE.ts | 1 + .../client/lib/commands/CLUSTER_ADDSLOTS.ts | 1 + .../lib/commands/CLUSTER_ADDSLOTSRANGE.ts | 1 + .../client/lib/commands/CLUSTER_BUMPEPOCH.ts | 1 + .../commands/CLUSTER_COUNT-FAILURE-REPORTS.ts | 1 + .../lib/commands/CLUSTER_COUNTKEYSINSLOT.ts | 1 + .../client/lib/commands/CLUSTER_DELSLOTS.ts | 1 + .../lib/commands/CLUSTER_DELSLOTSRANGE.ts | 1 + .../client/lib/commands/CLUSTER_FAILOVER.ts | 1 + .../client/lib/commands/CLUSTER_FLUSHSLOTS.ts | 1 + .../client/lib/commands/CLUSTER_FORGET.ts | 1 + .../lib/commands/CLUSTER_GETKEYSINSLOT.ts | 1 + packages/client/lib/commands/CLUSTER_SLOTS.ts | 1 + packages/client/lib/commands/CONFIG_GET.ts | 1 + packages/client/lib/commands/DBSIZE.ts | 1 + packages/client/lib/commands/DEL.ts | 1 + packages/client/lib/commands/ECHO.ts | 1 + packages/client/lib/commands/GET.spec.ts | 43 ++-- packages/client/lib/commands/GETBIT.spec.ts | 36 ++-- packages/client/lib/commands/GETDEL.spec.ts | 38 ++-- packages/client/lib/commands/GETEX.spec.ts | 184 ++++++++++-------- packages/client/lib/commands/GETEX.ts | 67 +++++-- packages/client/lib/commands/GETRANGE.spec.ts | 36 ++-- packages/client/lib/commands/GETSET.spec.ts | 36 ++-- packages/client/lib/commands/HDEL.spec.ts | 43 ++-- packages/client/lib/commands/HEXISTS.spec.ts | 29 +-- packages/client/lib/commands/HGET.spec.ts | 29 +-- packages/client/lib/commands/HINCRBY.spec.ts | 29 +-- .../client/lib/commands/HINCRBYFLOAT.spec.ts | 29 +-- packages/client/lib/commands/HKEYS.spec.ts | 29 +-- packages/client/lib/commands/HLEN.spec.ts | 29 +-- packages/client/lib/commands/HMGET.spec.ts | 43 ++-- packages/client/lib/commands/HMGET.ts | 2 +- .../client/lib/commands/HRANDFIELD.spec.ts | 31 +-- .../lib/commands/HRANDFIELD_COUNT.spec.ts | 31 +-- .../HRANDFIELD_COUNT_WITHVALUES.spec.ts | 0 packages/client/lib/commands/HSCAN.spec.ts | 111 +++++------ packages/client/lib/commands/HSET.spec.ts | 116 ++++++----- packages/client/lib/commands/HSETNX.spec.ts | 29 +-- packages/client/lib/commands/HSTRLEN.spec.ts | 29 +-- packages/client/lib/commands/HSTRLEN.ts | 2 +- packages/client/lib/commands/HVALS.spec.ts | 29 +-- packages/client/lib/commands/INCR.spec.ts | 29 +-- packages/client/lib/commands/INCRBY.spec.ts | 31 +-- .../client/lib/commands/INCRBYFLOAT.spec.ts | 29 +-- packages/client/lib/commands/INFO.ts | 1 + packages/client/lib/commands/KEYS.spec.ts | 12 +- packages/client/lib/commands/KEYS.ts | 1 + packages/client/lib/commands/LCS.spec.ts | 38 ++-- packages/client/lib/commands/LCS_LEN.spec.ts | 38 ++-- packages/client/lib/commands/LINDEX.spec.ts | 48 ++--- packages/client/lib/commands/LINSERT.spec.ts | 36 ++-- packages/client/lib/commands/LMOVE.spec.ts | 2 +- packages/client/lib/commands/LMPOP.spec.ts | 2 +- packages/client/lib/commands/LSET.spec.ts | 1 + packages/client/lib/commands/PING.ts | 1 + packages/client/lib/commands/RANDOMKEY.ts | 1 + packages/client/lib/commands/RENAME.ts | 1 + packages/client/lib/commands/RENAMENX.ts | 1 + packages/client/lib/commands/SCAN.ts | 1 + packages/client/lib/commands/SORT_RO.spec.ts | 2 +- packages/client/lib/commands/SPOP.spec.ts | 46 ++--- packages/client/lib/commands/SPOP.ts | 28 +-- .../client/lib/commands/SPOP_COUNT.spec.ts | 22 +++ packages/client/lib/commands/SPOP_COUNT.ts | 10 + packages/client/lib/commands/SREM.spec.ts | 2 +- packages/client/lib/commands/index.ts | 17 +- 79 files changed, 809 insertions(+), 706 deletions(-) create mode 100644 packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts create mode 100644 packages/client/lib/commands/SPOP_COUNT.spec.ts create mode 100644 packages/client/lib/commands/SPOP_COUNT.ts diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index afac0356a4c..2a0a30b474b 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -385,10 +385,10 @@ export class Decoder { } // Precalculated multipliers for decimal points to improve performance - // "A Number only keeps about 17 decimal places of precision" - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + // "... about 15 to 17 decimal places ..." + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#:~:text=about%2015%20to%2017%20decimal%20places static _DOUBLE_DECIMAL_MULTIPLIERS = [ - 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 ]; diff --git a/packages/client/lib/commands/BITOP.spec.ts b/packages/client/lib/commands/BITOP.spec.ts index c89d5ea0b37..bb411c0f1a2 100644 --- a/packages/client/lib/commands/BITOP.spec.ts +++ b/packages/client/lib/commands/BITOP.spec.ts @@ -19,7 +19,7 @@ describe('BITOP', () => { }); }); - testUtils.testAll('client.bitOp', async client => { + testUtils.testAll('bitOp', async client => { assert.equal( await client.bitOp('AND', '{tag}destKey', '{tag}key'), 0 diff --git a/packages/client/lib/commands/CLIENT_CACHING.ts b/packages/client/lib/commands/CLIENT_CACHING.ts index 35edf889fa7..505ae152f85 100644 --- a/packages/client/lib/commands/CLIENT_CACHING.ts +++ b/packages/client/lib/commands/CLIENT_CACHING.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(value: boolean) { return [ diff --git a/packages/client/lib/commands/CLIENT_GETNAME.ts b/packages/client/lib/commands/CLIENT_GETNAME.ts index 5e3272553e9..c46b576407b 100644 --- a/packages/client/lib/commands/CLIENT_GETNAME.ts +++ b/packages/client/lib/commands/CLIENT_GETNAME.ts @@ -1,6 +1,7 @@ import { BlobStringReply, NullReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return [ diff --git a/packages/client/lib/commands/CLIENT_GETREDIR.ts b/packages/client/lib/commands/CLIENT_GETREDIR.ts index c2e68de5b6f..ae0b601b4e8 100644 --- a/packages/client/lib/commands/CLIENT_GETREDIR.ts +++ b/packages/client/lib/commands/CLIENT_GETREDIR.ts @@ -1,6 +1,7 @@ import { NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLIENT', 'GETREDIR'] diff --git a/packages/client/lib/commands/CLIENT_ID.ts b/packages/client/lib/commands/CLIENT_ID.ts index cc298ed122e..165ab1931eb 100644 --- a/packages/client/lib/commands/CLIENT_ID.ts +++ b/packages/client/lib/commands/CLIENT_ID.ts @@ -1,6 +1,7 @@ import { NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLIENT', 'ID']; diff --git a/packages/client/lib/commands/CLIENT_INFO.ts b/packages/client/lib/commands/CLIENT_INFO.ts index 1bd9fc2f25f..88721e2f8b9 100644 --- a/packages/client/lib/commands/CLIENT_INFO.ts +++ b/packages/client/lib/commands/CLIENT_INFO.ts @@ -56,6 +56,7 @@ export interface ClientInfoReply { const CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLIENT', 'INFO'] diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index c1663f80e3a..81d0bc85ee7 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -42,6 +42,7 @@ export type ClientKillSkipMe = CLIENT_KILL_FILTERS['SKIP_ME'] | (ClientKillFilte export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(filters: ClientKillFilter | Array) { const args = ['CLIENT', 'KILL']; diff --git a/packages/client/lib/commands/CLIENT_LIST.ts b/packages/client/lib/commands/CLIENT_LIST.ts index b1c2e5d2db4..f50634d56d3 100644 --- a/packages/client/lib/commands/CLIENT_LIST.ts +++ b/packages/client/lib/commands/CLIENT_LIST.ts @@ -15,6 +15,7 @@ export interface ListFilterId { export type ListFilter = ListFilterType | ListFilterId; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(filter?: ListFilter) { let args: Array = ['CLIENT', 'LIST']; diff --git a/packages/client/lib/commands/CLIENT_NO-EVICT.ts b/packages/client/lib/commands/CLIENT_NO-EVICT.ts index 226405d0320..82aa50074ba 100644 --- a/packages/client/lib/commands/CLIENT_NO-EVICT.ts +++ b/packages/client/lib/commands/CLIENT_NO-EVICT.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(value: boolean) { return [ diff --git a/packages/client/lib/commands/CLIENT_PAUSE.ts b/packages/client/lib/commands/CLIENT_PAUSE.ts index b01e356cf54..87b4177ed8c 100644 --- a/packages/client/lib/commands/CLIENT_PAUSE.ts +++ b/packages/client/lib/commands/CLIENT_PAUSE.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(timeout: number, mode?: 'WRITE' | 'ALL') { const args = [ diff --git a/packages/client/lib/commands/CLIENT_SETNAME.ts b/packages/client/lib/commands/CLIENT_SETNAME.ts index 9208bba9243..e2e2a921958 100644 --- a/packages/client/lib/commands/CLIENT_SETNAME.ts +++ b/packages/client/lib/commands/CLIENT_SETNAME.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(name: RedisArgument) { return ['CLIENT', 'SETNAME', name]; diff --git a/packages/client/lib/commands/CLIENT_UNPAUSE.ts b/packages/client/lib/commands/CLIENT_UNPAUSE.ts index b2baf9c4bea..9da0a9a8bbe 100644 --- a/packages/client/lib/commands/CLIENT_UNPAUSE.ts +++ b/packages/client/lib/commands/CLIENT_UNPAUSE.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLIENT', 'UNPAUSE']; diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts index 0841b42eca6..dc42c2f13e8 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTS.ts @@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { pushVariadicNumberArguments } from './generic-transformers'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(slots: number | Array) { return pushVariadicNumberArguments( diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts index ebbd4529e1e..5cf649a30da 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.ts @@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(ranges: SlotRange | Array) { return pushSlotRangesArguments( diff --git a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts index c2587e82ae9..94f7e3b56f9 100644 --- a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts +++ b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLUSTER', 'BUMPEPOCH']; diff --git a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts index 1c33ca7453c..a005694713d 100644 --- a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts +++ b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.ts @@ -1,6 +1,7 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(nodeId: RedisArgument) { return ['CLUSTER', 'COUNT-FAILURE-REPORTS', nodeId]; diff --git a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts index 939d09d2082..2892c2aae2d 100644 --- a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts @@ -1,6 +1,7 @@ import { NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(slot: number) { return ['CLUSTER', 'COUNT-FAILURE-REPORTS', slot.toString()]; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTS.ts b/packages/client/lib/commands/CLUSTER_DELSLOTS.ts index f9f408fa936..6a6bbb76085 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTS.ts @@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { pushVariadicNumberArguments } from './generic-transformers'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(slots: number | Array) { return pushVariadicNumberArguments( diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts index 81e46ba2dc7..e28ca9c8405 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.ts @@ -2,6 +2,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { pushSlotRangesArguments, SlotRange } from './generic-transformers'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(ranges: SlotRange | Array) { return pushSlotRangesArguments( diff --git a/packages/client/lib/commands/CLUSTER_FAILOVER.ts b/packages/client/lib/commands/CLUSTER_FAILOVER.ts index 948d1f4864e..857e11f7b1f 100644 --- a/packages/client/lib/commands/CLUSTER_FAILOVER.ts +++ b/packages/client/lib/commands/CLUSTER_FAILOVER.ts @@ -8,6 +8,7 @@ export const FAILOVER_MODES = { export type FailoverModes = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES]; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(mode?: FailoverModes) { const args = ['CLUSTER', 'FAILOVER']; diff --git a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts index d4f783cd114..327ed7b7d17 100644 --- a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.ts @@ -1,6 +1,7 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLUSTER', 'FLUSHSLOTS']; diff --git a/packages/client/lib/commands/CLUSTER_FORGET.ts b/packages/client/lib/commands/CLUSTER_FORGET.ts index 19bc4657e4b..a51c039563b 100644 --- a/packages/client/lib/commands/CLUSTER_FORGET.ts +++ b/packages/client/lib/commands/CLUSTER_FORGET.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(nodeId: RedisArgument) { return ['CLUSTER', 'FORGET', nodeId]; diff --git a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts index b9970a07db8..c19cd225e04 100644 --- a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.ts @@ -1,6 +1,7 @@ import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(slot: number, count: number) { return ['CLUSTER', 'GETKEYSINSLOT', slot.toString(), count.toString()]; diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.ts b/packages/client/lib/commands/CLUSTER_SLOTS.ts index 5d4e5d7d0b8..13a925e9a48 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.ts @@ -16,6 +16,7 @@ type ClusterSlotsRawReply = ArrayReply<[ export type ClusterSlotsNode = ReturnType; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['CLUSTER', 'SLOTS']; diff --git a/packages/client/lib/commands/CONFIG_GET.ts b/packages/client/lib/commands/CONFIG_GET.ts index 45b8e61ac4a..0fc8229229f 100644 --- a/packages/client/lib/commands/CONFIG_GET.ts +++ b/packages/client/lib/commands/CONFIG_GET.ts @@ -2,6 +2,7 @@ import { RedisArgument, Command } from '../RESP/types'; import { transformTuplesReply } from './generic-transformers'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(parameter: RedisArgument) { return ['CONFIG', 'GET', parameter]; diff --git a/packages/client/lib/commands/DBSIZE.ts b/packages/client/lib/commands/DBSIZE.ts index c4d3c8d857a..54770831ab0 100644 --- a/packages/client/lib/commands/DBSIZE.ts +++ b/packages/client/lib/commands/DBSIZE.ts @@ -1,6 +1,7 @@ import { NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['DBSIZE']; diff --git a/packages/client/lib/commands/DEL.ts b/packages/client/lib/commands/DEL.ts index a9b10194279..f59a5ba2e89 100644 --- a/packages/client/lib/commands/DEL.ts +++ b/packages/client/lib/commands/DEL.ts @@ -3,6 +3,7 @@ import { RedisVariadicArgument, pushVariadicArguments } from './generic-transfor export default { FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, transformArguments(keys: RedisVariadicArgument) { return pushVariadicArguments(['DEL'], keys); }, diff --git a/packages/client/lib/commands/ECHO.ts b/packages/client/lib/commands/ECHO.ts index 828ab0382e2..dfe5ec13000 100644 --- a/packages/client/lib/commands/ECHO.ts +++ b/packages/client/lib/commands/ECHO.ts @@ -1,6 +1,7 @@ import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(message: RedisArgument) { return ['ECHO', message]; diff --git a/packages/client/lib/commands/GET.spec.ts b/packages/client/lib/commands/GET.spec.ts index 2946ea19b60..9e131694b11 100644 --- a/packages/client/lib/commands/GET.spec.ts +++ b/packages/client/lib/commands/GET.spec.ts @@ -1,33 +1,22 @@ import { strict as assert } from 'assert'; -import RedisClient from '../client'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GET'; +import GET from './GET'; describe('GET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GET', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GET.transformArguments('key'), + ['GET', 'key'] + ); + }); - testUtils.testWithClient('client.get', async client => { - const a = await client.get( - 'key' - ); - - - - assert.equal( - await client.get('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.get', async cluster => { - assert.equal( - await cluster.get('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('get', async client => { + assert.equal( + await client.get('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GETBIT.spec.ts b/packages/client/lib/commands/GETBIT.spec.ts index 4206084eced..5dbab538c1b 100644 --- a/packages/client/lib/commands/GETBIT.spec.ts +++ b/packages/client/lib/commands/GETBIT.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETBIT'; +import GETBIT from './GETBIT'; describe('GETBIT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0), - ['GETBIT', 'key', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETBIT.transformArguments('key', 0), + ['GETBIT', 'key', '0'] + ); + }); - testUtils.testWithClient('client.getBit', async client => { - assert.equal( - await client.getBit('key', 0), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.getBit', async cluster => { - assert.equal( - await cluster.getBit('key', 0), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getBit', async client => { + assert.equal( + await client.getBit('key', 0), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GETDEL.spec.ts b/packages/client/lib/commands/GETDEL.spec.ts index db3a486696a..cbb7553cfeb 100644 --- a/packages/client/lib/commands/GETDEL.spec.ts +++ b/packages/client/lib/commands/GETDEL.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETDEL'; +import GETDEL from './GETDEL'; describe('GETDEL', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GETDEL', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETDEL.transformArguments('key'), + ['GETDEL', 'key'] + ); + }); - testUtils.testWithClient('client.getDel', async client => { - assert.equal( - await client.getDel('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.getDel', async cluster => { - assert.equal( - await cluster.getDel('key'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getDel', async client => { + assert.equal( + await client.getDel('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GETEX.spec.ts b/packages/client/lib/commands/GETEX.spec.ts index 1bf86089da1..3bc0a5e03b9 100644 --- a/packages/client/lib/commands/GETEX.spec.ts +++ b/packages/client/lib/commands/GETEX.spec.ts @@ -1,96 +1,122 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETEX'; +import GETEX from './GETEX'; describe('GETEX', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('EX', () => { - assert.deepEqual( - transformArguments('key', { - EX: 1 - }), - ['GETEX', 'key', 'EX', '1'] - ); - }); + describe('transformArguments', () => { + it('EX | PX', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + type: 'EX', + value: 1 + }), + ['GETEX', 'key', 'EX', '1'] + ); + }); - it('PX', () => { - assert.deepEqual( - transformArguments('key', { - PX: 1 - }), - ['GETEX', 'key', 'PX', '1'] - ); - }); + it('EX (backwards compatibility)', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + EX: 1 + }), + ['GETEX', 'key', 'EX', '1'] + ); + }); - describe('EXAT', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', { - EXAT: 1 - }), - ['GETEX', 'key', 'EXAT', '1'] - ); - }); + it('PX (backwards compatibility)', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PX: 1 + }), + ['GETEX', 'key', 'PX', '1'] + ); + }); - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', { - EXAT: d - }), - ['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()] - ); - }); - }); + describe('EXAT | PXAT', () => { + it('number', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + type: 'EXAT', + value: 1 + }), + ['GETEX', 'key', 'EXAT', '1'] + ); + }); - describe('PXAT', () => { - it('number', () => { - assert.deepEqual( - transformArguments('key', { - PXAT: 1 - }), - ['GETEX', 'key', 'PXAT', '1'] - ); - }); + it('date', () => { + const d = new Date(); + assert.deepEqual( + GETEX.transformArguments('key', { + EXAT: d + }), + ['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()] + ); + }); + }); - it('date', () => { - const d = new Date(); - assert.deepEqual( - transformArguments('key', { - PXAT: d - }), - ['GETEX', 'key', 'PXAT', d.getTime().toString()] - ); - }); - }); + describe('EXAT (backwards compatibility)', () => { + it('number', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + EXAT: 1 + }), + ['GETEX', 'key', 'EXAT', '1'] + ); + }); - it('PERSIST', () => { - assert.deepEqual( - transformArguments('key', { - PERSIST: true - }), - ['GETEX', 'key', 'PERSIST'] - ); - }); + it('date', () => { + const d = new Date(); + assert.deepEqual( + GETEX.transformArguments('key', { + EXAT: d + }), + ['GETEX', 'key', 'EXAT', Math.floor(d.getTime() / 1000).toString()] + ); + }); }); - testUtils.testWithClient('client.getEx', async client => { - assert.equal( - await client.getEx('key', { - PERSIST: true - }), - null + describe('PXAT (backwards compatibility)', () => { + it('number', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PXAT: 1 + }), + ['GETEX', 'key', 'PXAT', '1'] ); - }, GLOBAL.SERVERS.OPEN); + }); - testUtils.testWithCluster('cluster.getEx', async cluster => { - assert.equal( - await cluster.getEx('key', { - PERSIST: true - }), - null + it('date', () => { + const d = new Date(); + assert.deepEqual( + GETEX.transformArguments('key', { + PXAT: d + }), + ['GETEX', 'key', 'PXAT', d.getTime().toString()] ); - }, GLOBAL.CLUSTERS.OPEN); + }); + }); + + it('PERSIST (backwards compatibility)', () => { + assert.deepEqual( + GETEX.transformArguments('key', { + PERSIST: true + }), + ['GETEX', 'key', 'PERSIST'] + ); + }); + }); + + testUtils.testAll('getEx', async client => { + assert.equal( + await client.getEx('key', { + type: 'PERSIST' + }), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GETEX.ts b/packages/client/lib/commands/GETEX.ts index 201a888208a..8244350eddb 100644 --- a/packages/client/lib/commands/GETEX.ts +++ b/packages/client/lib/commands/GETEX.ts @@ -1,36 +1,77 @@ import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; import { transformEXAT, transformPXAT } from './generic-transformers'; -export type GetExModes = { +export type GetExOptions = { + type: 'EX' | 'PX'; + value: number; +} | { + type: 'EXAT' | 'PXAT'; + value: number | Date; +} | { + type: 'PERSIST'; +} | { + /** + * @deprecated Use `{ type: 'EX', value: number }` instead. + */ EX: number; } | { + /** + * @deprecated Use `{ type: 'PX', value: number }` instead. + */ PX: number; } | { + /** + * @deprecated Use `{ type: 'EXAT', value: number | Date }` instead. + */ EXAT: number | Date; } | { + /** + * @deprecated Use `{ type: 'PXAT', value: number | Date }` instead. + */ PXAT: number | Date; } | { + /** + * @deprecated Use `{ type: 'PERSIST' }` instead. + */ PERSIST: true; }; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(key: RedisArgument, mode: GetExModes) { + transformArguments(key: RedisArgument, options: GetExOptions) { const args = ['GETEX', key]; - if ('EX' in mode) { - args.push('EX', mode.EX.toString()); - } else if ('PX' in mode) { - args.push('PX', mode.PX.toString()); - } else if ('EXAT' in mode) { - args.push('EXAT', transformEXAT(mode.EXAT)); - } else if ('PXAT' in mode) { - args.push('PXAT', transformPXAT(mode.PXAT)); - } else { // PERSIST - args.push('PERSIST'); - } + if ('type' in options) { + switch (options.type) { + case 'EX': + case 'PX': + args.push(options.type, options.value.toString()); + break; + + case 'EXAT': + case 'PXAT': + args.push(options.type, transformEXAT(options.value)); + break; + case 'PERSIST': + args.push('PERSIST'); + break; + } + } else { + if ('EX' in options) { + args.push('EX', options.EX.toString()); + } else if ('PX' in options) { + args.push('PX', options.PX.toString()); + } else if ('EXAT' in options) { + args.push('EXAT', transformEXAT(options.EXAT)); + } else if ('PXAT' in options) { + args.push('PXAT', transformPXAT(options.PXAT)); + } else { // PERSIST + args.push('PERSIST'); + } + } + return args; }, transformReply: undefined as unknown as () => BlobStringReply | NullReply diff --git a/packages/client/lib/commands/GETRANGE.spec.ts b/packages/client/lib/commands/GETRANGE.spec.ts index 0c9dbc2c70f..1a31e1a76f0 100644 --- a/packages/client/lib/commands/GETRANGE.spec.ts +++ b/packages/client/lib/commands/GETRANGE.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETRANGE'; +import GETRANGE from './GETRANGE'; describe('GETRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, -1), - ['GETRANGE', 'key', '0', '-1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETRANGE.transformArguments('key', 0, -1), + ['GETRANGE', 'key', '0', '-1'] + ); + }); - testUtils.testWithClient('client.getRange', async client => { - assert.equal( - await client.getRange('key', 0, -1), - '' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lTrim', async cluster => { - assert.equal( - await cluster.getRange('key', 0, -1), - '' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getRange', async client => { + assert.equal( + await client.getRange('key', 0, -1), + '' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GETSET.spec.ts b/packages/client/lib/commands/GETSET.spec.ts index 73fbcec57ea..f52c2f29293 100644 --- a/packages/client/lib/commands/GETSET.spec.ts +++ b/packages/client/lib/commands/GETSET.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GETSET'; +import GETSET from './GETSET'; describe('GETSET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'value'), - ['GETSET', 'key', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GETSET.transformArguments('key', 'value'), + ['GETSET', 'key', 'value'] + ); + }); - testUtils.testWithClient('client.getSet', async client => { - assert.equal( - await client.getSet('key', 'value'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.getSet', async cluster => { - assert.equal( - await cluster.getSet('key', 'value'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('getSet', async client => { + assert.equal( + await client.getSet('key', 'value'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HDEL.spec.ts b/packages/client/lib/commands/HDEL.spec.ts index eb24bcfacbd..c87b20397ee 100644 --- a/packages/client/lib/commands/HDEL.spec.ts +++ b/packages/client/lib/commands/HDEL.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HDEL'; +import HDEL from './HDEL'; describe('HDEL', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HDEL', 'key', 'field'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + HDEL.transformArguments('key', 'field'), + ['HDEL', 'key', 'field'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['HDEL', 'key', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + HDEL.transformArguments('key', ['1', '2']), + ['HDEL', 'key', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.hDel', async client => { - assert.equal( - await client.hDel('key', 'field'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hDel', async client => { + assert.equal( + await client.hDel('key', 'field'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HEXISTS.spec.ts b/packages/client/lib/commands/HEXISTS.spec.ts index 3764319c123..0e0e82fa21b 100644 --- a/packages/client/lib/commands/HEXISTS.spec.ts +++ b/packages/client/lib/commands/HEXISTS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HEXISTS'; +import HEXISTS from './HEXISTS'; describe('HEXISTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HEXISTS', 'key', 'field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HEXISTS.transformArguments('key', 'field'), + ['HEXISTS', 'key', 'field'] + ); + }); - testUtils.testWithClient('client.hExists', async client => { - assert.equal( - await client.hExists('key', 'field'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hExists', async client => { + assert.equal( + await client.hExists('key', 'field'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HGET.spec.ts b/packages/client/lib/commands/HGET.spec.ts index 6b6d0a3ee22..33824d903a1 100644 --- a/packages/client/lib/commands/HGET.spec.ts +++ b/packages/client/lib/commands/HGET.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HGET'; +import HGET from './HGET'; describe('HGET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HGET', 'key', 'field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HGET.transformArguments('key', 'field'), + ['HGET', 'key', 'field'] + ); + }); - testUtils.testWithClient('client.hGet', async client => { - assert.equal( - await client.hGet('key', 'field'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hGet', async client => { + assert.equal( + await client.hGet('key', 'field'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HINCRBY.spec.ts b/packages/client/lib/commands/HINCRBY.spec.ts index de406217921..263f841e3f8 100644 --- a/packages/client/lib/commands/HINCRBY.spec.ts +++ b/packages/client/lib/commands/HINCRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HINCRBY'; +import HINCRBY from './HINCRBY'; describe('HINCRBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field', 1), - ['HINCRBY', 'key', 'field', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HINCRBY.transformArguments('key', 'field', 1), + ['HINCRBY', 'key', 'field', '1'] + ); + }); - testUtils.testWithClient('client.hIncrBy', async client => { - assert.equal( - await client.hIncrBy('key', 'field', 1), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hIncrBy', async client => { + assert.equal( + await client.hIncrBy('key', 'field', 1), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts index bd0147a3481..56754ea2cf0 100644 --- a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HINCRBYFLOAT'; +import HINCRBYFLOAT from './HINCRBYFLOAT'; describe('HINCRBYFLOAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field', 1.5), - ['HINCRBYFLOAT', 'key', 'field', '1.5'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HINCRBYFLOAT.transformArguments('key', 'field', 1.5), + ['HINCRBYFLOAT', 'key', 'field', '1.5'] + ); + }); - testUtils.testWithClient('client.hIncrByFloat', async client => { - assert.equal( - await client.hIncrByFloat('key', 'field', 1.5), - '1.5' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hIncrByFloat', async client => { + assert.equal( + await client.hIncrByFloat('key', 'field', 1.5), + '1.5' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HKEYS.spec.ts b/packages/client/lib/commands/HKEYS.spec.ts index f94538f67d3..080bfa46706 100644 --- a/packages/client/lib/commands/HKEYS.spec.ts +++ b/packages/client/lib/commands/HKEYS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HKEYS'; +import HKEYS from './HKEYS'; describe('HKEYS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HKEYS', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HKEYS.transformArguments('key'), + ['HKEYS', 'key'] + ); + }); - testUtils.testWithClient('client.hKeys', async client => { - assert.deepEqual( - await client.hKeys('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hKeys', async client => { + assert.deepEqual( + await client.hKeys('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HLEN.spec.ts b/packages/client/lib/commands/HLEN.spec.ts index be9d4b13a7d..a0d804dff73 100644 --- a/packages/client/lib/commands/HLEN.spec.ts +++ b/packages/client/lib/commands/HLEN.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HLEN'; +import HLEN from './HLEN'; describe('HLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HLEN.transformArguments('key'), + ['HLEN', 'key'] + ); + }); - testUtils.testWithClient('client.hLen', async client => { - assert.equal( - await client.hLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hLen', async client => { + assert.equal( + await client.hLen('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HMGET.spec.ts b/packages/client/lib/commands/HMGET.spec.ts index a7c934b760d..e21f67e2c61 100644 --- a/packages/client/lib/commands/HMGET.spec.ts +++ b/packages/client/lib/commands/HMGET.spec.ts @@ -1,28 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HMGET'; +import HMGET from './HMGET'; describe('HMGET', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HMGET', 'key', 'field'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + HMGET.transformArguments('key', 'field'), + ['HMGET', 'key', 'field'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('key', ['field1', 'field2']), - ['HMGET', 'key', 'field1', 'field2'] - ); - }); + it('array', () => { + assert.deepEqual( + HMGET.transformArguments('key', ['field1', 'field2']), + ['HMGET', 'key', 'field1', 'field2'] + ); }); + }); - testUtils.testWithClient('client.hmGet', async client => { - assert.deepEqual( - await client.hmGet('key', 'field'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hmGet', async client => { + assert.deepEqual( + await client.hmGet('key', 'field'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HMGET.ts b/packages/client/lib/commands/HMGET.ts index 1c4acafdeef..df28a64be09 100644 --- a/packages/client/lib/commands/HMGET.ts +++ b/packages/client/lib/commands/HMGET.ts @@ -8,7 +8,7 @@ export default { key: RedisArgument, fields: RedisVariadicArgument ) { - return pushVariadicArguments(['HMGET'], fields); + return pushVariadicArguments(['HMGET', key], fields); }, transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/client/lib/commands/HRANDFIELD.spec.ts b/packages/client/lib/commands/HRANDFIELD.spec.ts index df0a4fc7a1d..492733c5834 100644 --- a/packages/client/lib/commands/HRANDFIELD.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HRANDFIELD'; +import HRANDFIELD from './HRANDFIELD'; describe('HRANDFIELD', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HRANDFIELD', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HRANDFIELD.transformArguments('key'), + ['HRANDFIELD', 'key'] + ); + }); - testUtils.testWithClient('client.hRandField', async client => { - assert.equal( - await client.hRandField('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hRandField', async client => { + assert.equal( + await client.hRandField('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts index 4bfce0f7e23..7b38d61695c 100644 --- a/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts @@ -1,21 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HRANDFIELD_COUNT'; +import HRANDFIELD_COUNT from './HRANDFIELD_COUNT'; describe('HRANDFIELD COUNT', () => { - testUtils.isVersionGreaterThanHook([6, 2, 5]); + testUtils.isVersionGreaterThanHook([6, 2, 5]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['HRANDFIELD', 'key', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HRANDFIELD_COUNT.transformArguments('key', 1), + ['HRANDFIELD', 'key', '1'] + ); + }); - testUtils.testWithClient('client.hRandFieldCount', async client => { - assert.deepEqual( - await client.hRandFieldCount('key', 1), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hRandFieldCount', async client => { + assert.deepEqual( + await client.hRandFieldCount('key', 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.spec.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/client/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts index b426763b99b..c655f5a1a50 100644 --- a/packages/client/lib/commands/HSCAN.spec.ts +++ b/packages/client/lib/commands/HSCAN.spec.ts @@ -1,77 +1,56 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './HSCAN'; +import HSCAN from './HSCAN'; describe('HSCAN', () => { - describe('transformArguments', () => { - it('cusror only', () => { - assert.deepEqual( - transformArguments('key', 0), - ['HSCAN', 'key', '0'] - ); - }); - - it('with MATCH', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern' - }), - ['HSCAN', 'key', '0', 'MATCH', 'pattern'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - COUNT: 1 - }), - ['HSCAN', 'key', '0', 'COUNT', '1'] - ); - }); + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + HSCAN.transformArguments('key', 0), + ['HSCAN', 'key', '0'] + ); + }); - it('with MATCH & COUNT', () => { - assert.deepEqual( - transformArguments('key', 0, { - MATCH: 'pattern', - COUNT: 1 - }), - ['HSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] - ); - }); + it('with MATCH', () => { + assert.deepEqual( + HSCAN.transformArguments('key', 0, { + MATCH: 'pattern' + }), + ['HSCAN', 'key', '0', 'MATCH', 'pattern'] + ); }); - describe('transformReply', () => { - it('without tuples', () => { - assert.deepEqual( - transformReply(['0', []]), - { - cursor: 0, - tuples: [] - } - ); - }); + it('with COUNT', () => { + assert.deepEqual( + HSCAN.transformArguments('key', 0, { + COUNT: 1 + }), + ['HSCAN', 'key', '0', 'COUNT', '1'] + ); + }); - it('with tuples', () => { - assert.deepEqual( - transformReply(['0', ['field', 'value']]), - { - cursor: 0, - tuples: [{ - field: 'field', - value: 'value' - }] - } - ); - }); + it('with MATCH & COUNT', () => { + assert.deepEqual( + HSCAN.transformArguments('key', 0, { + MATCH: 'pattern', + COUNT: 1 + }), + ['HSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1'] + ); }); + }); - testUtils.testWithClient('client.hScan', async client => { - assert.deepEqual( - await client.hScan('key', 0), - { - cursor: 0, - tuples: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.hScan', async client => { + await client.hSet('key', 'field', 'value'); + assert.deepEqual( + await client.hScan('key', 0), + { + cursor: 0, + entries: [{ + field: 'field', + value: 'value' + }] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/HSET.spec.ts b/packages/client/lib/commands/HSET.spec.ts index 73bc966f87a..093edee6d22 100644 --- a/packages/client/lib/commands/HSET.spec.ts +++ b/packages/client/lib/commands/HSET.spec.ts @@ -1,74 +1,70 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './HSET'; import testUtils, { GLOBAL } from '../test-utils'; +import HSET from './HSET'; describe('HSET', () => { - describe('transformArguments', () => { - describe('field, value', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', 'field', 'value'), - ['HSET', 'key', 'field', 'value'] - ); - }); - - it('number', () => { - assert.deepEqual( - transformArguments('key', 1, 2), - ['HSET', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + describe('field, value', () => { + it('string', () => { + assert.deepEqual( + HSET.transformArguments('key', 'field', 'value'), + ['HSET', 'key', 'field', 'value'] + ); + }); - it('Buffer', () => { - assert.deepEqual( - transformArguments(Buffer.from('key'), Buffer.from('field'), Buffer.from('value')), - ['HSET', Buffer.from('key'), Buffer.from('field'), Buffer.from('value')] - ); - }); - }); + it('number', () => { + assert.deepEqual( + HSET.transformArguments('key', 1, 2), + ['HSET', 'key', '1', '2'] + ); + }); - it('Map', () => { - assert.deepEqual( - transformArguments('key', new Map([['field', 'value']])), - ['HSET', 'key', 'field', 'value'] - ); - }); + it('Buffer', () => { + assert.deepEqual( + HSET.transformArguments(Buffer.from('key'), Buffer.from('field'), Buffer.from('value')), + ['HSET', Buffer.from('key'), Buffer.from('field'), Buffer.from('value')] + ); + }); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('key', [['field', 'value']]), - ['HSET', 'key', 'field', 'value'] - ); - }); + it('Map', () => { + assert.deepEqual( + HSET.transformArguments('key', new Map([['field', 'value']])), + ['HSET', 'key', 'field', 'value'] + ); + }); - describe('Object', () => { - it('string', () => { - assert.deepEqual( - transformArguments('key', { field: 'value' }), - ['HSET', 'key', 'field', 'value'] - ); - }); - - it('Buffer', () => { - assert.deepEqual( - transformArguments('key', { field: Buffer.from('value') }), - ['HSET', 'key', 'field', Buffer.from('value')] - ); - }); - }); + it('Array', () => { + assert.deepEqual( + HSET.transformArguments('key', [['field', 'value']]), + ['HSET', 'key', 'field', 'value'] + ); }); - testUtils.testWithClient('client.hSet', async client => { - assert.equal( - await client.hSet('key', 'field', 'value'), - 1 + describe('Object', () => { + it('string', () => { + assert.deepEqual( + HSET.transformArguments('key', { field: 'value' }), + ['HSET', 'key', 'field', 'value'] ); - }, GLOBAL.SERVERS.OPEN); + }); - testUtils.testWithCluster('cluster.hSet', async cluster => { - assert.equal( - await cluster.hSet('key', { field: 'value' }), - 1 + it('Buffer', () => { + assert.deepEqual( + HSET.transformArguments('key', { field: Buffer.from('value') }), + ['HSET', 'key', 'field', Buffer.from('value')] ); - }, GLOBAL.CLUSTERS.OPEN); + }); + }); + }); + + testUtils.testAll('hSet', async client => { + assert.equal( + await client.hSet('key', 'field', 'value'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HSETNX.spec.ts b/packages/client/lib/commands/HSETNX.spec.ts index 190fa50ae97..2e39edc81ff 100644 --- a/packages/client/lib/commands/HSETNX.spec.ts +++ b/packages/client/lib/commands/HSETNX.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HSETNX'; +import HSETNX from './HSETNX'; describe('HSETNX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field', 'value'), - ['HSETNX', 'key', 'field', 'value'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HSETNX.transformArguments('key', 'field', 'value'), + ['HSETNX', 'key', 'field', 'value'] + ); + }); - testUtils.testWithClient('client.hSetNX', async client => { - assert.equal( - await client.hSetNX('key', 'field', 'value'), - true - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hSetNX', async client => { + assert.equal( + await client.hSetNX('key', 'field', 'value'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HSTRLEN.spec.ts b/packages/client/lib/commands/HSTRLEN.spec.ts index 79c3150211e..98d96454186 100644 --- a/packages/client/lib/commands/HSTRLEN.spec.ts +++ b/packages/client/lib/commands/HSTRLEN.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HSTRLEN'; +import HSTRLEN from './HSTRLEN'; describe('HSTRLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'field'), - ['HSTRLEN', 'key', 'field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HSTRLEN.transformArguments('key', 'field'), + ['HSTRLEN', 'key', 'field'] + ); + }); - testUtils.testWithClient('client.hStrLen', async client => { - assert.equal( - await client.hStrLen('key', 'field'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hStrLen', async client => { + assert.equal( + await client.hStrLen('key', 'field'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/HSTRLEN.ts b/packages/client/lib/commands/HSTRLEN.ts index 61e2e1b1acd..843c4baf7ef 100644 --- a/packages/client/lib/commands/HSTRLEN.ts +++ b/packages/client/lib/commands/HSTRLEN.ts @@ -4,7 +4,7 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, field: RedisArgument) { - return ['HSETLEN', key, field]; + return ['HSTRLEN', key, field]; }, transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/client/lib/commands/HVALS.spec.ts b/packages/client/lib/commands/HVALS.spec.ts index d0a6c39ce5f..ce450042ecb 100644 --- a/packages/client/lib/commands/HVALS.spec.ts +++ b/packages/client/lib/commands/HVALS.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HVALS'; +import HVALS from './HVALS'; describe('HVALS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['HVALS', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + HVALS.transformArguments('key'), + ['HVALS', 'key'] + ); + }); - testUtils.testWithClient('client.hVals', async client => { - assert.deepEqual( - await client.hVals('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('hVals', async client => { + assert.deepEqual( + await client.hVals('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/INCR.spec.ts b/packages/client/lib/commands/INCR.spec.ts index 321d83edc54..76a849aa4c2 100644 --- a/packages/client/lib/commands/INCR.spec.ts +++ b/packages/client/lib/commands/INCR.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCR'; +import INCR from './INCR'; describe('INCR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['INCR', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + INCR.transformArguments('key'), + ['INCR', 'key'] + ); + }); - testUtils.testWithClient('client.incr', async client => { - assert.equal( - await client.incr('key'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incr', async client => { + assert.equal( + await client.incr('key'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/INCRBY.spec.ts b/packages/client/lib/commands/INCRBY.spec.ts index a671d0ec259..08c84a437b3 100644 --- a/packages/client/lib/commands/INCRBY.spec.ts +++ b/packages/client/lib/commands/INCRBY.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCRBY'; +import INCRBY from './INCRBY'; -describe('INCR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1), - ['INCRBY', 'key', '1'] - ); - }); +describe('INCRBY', () => { + it('transformArguments', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1), + ['INCRBY', 'key', '1'] + ); + }); - testUtils.testWithClient('client.incrBy', async client => { - assert.equal( - await client.incrBy('key', 1), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incrBy', async client => { + assert.equal( + await client.incrBy('key', 1), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/INCRBYFLOAT.spec.ts b/packages/client/lib/commands/INCRBYFLOAT.spec.ts index b2dd5aa5da9..79daac612ea 100644 --- a/packages/client/lib/commands/INCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/INCRBYFLOAT.spec.ts @@ -1,19 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCRBYFLOAT'; +import INCRBYFLOAT from './INCRBYFLOAT'; describe('INCRBYFLOAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1.5), - ['INCRBYFLOAT', 'key', '1.5'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + INCRBYFLOAT.transformArguments('key', 1.5), + ['INCRBYFLOAT', 'key', '1.5'] + ); + }); - testUtils.testWithClient('client.incrByFloat', async client => { - assert.equal( - await client.incrByFloat('key', 1.5), - '1.5' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('incrByFloat', async client => { + assert.equal( + await client.incrByFloat('key', 1.5), + '1.5' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/INFO.ts b/packages/client/lib/commands/INFO.ts index 3adc3efd334..9877c0cf66b 100644 --- a/packages/client/lib/commands/INFO.ts +++ b/packages/client/lib/commands/INFO.ts @@ -1,6 +1,7 @@ import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(section?: RedisArgument) { const args: Array = ['INFO']; diff --git a/packages/client/lib/commands/KEYS.spec.ts b/packages/client/lib/commands/KEYS.spec.ts index c066331ea7c..be1b730161c 100644 --- a/packages/client/lib/commands/KEYS.spec.ts +++ b/packages/client/lib/commands/KEYS.spec.ts @@ -2,10 +2,10 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('KEYS', () => { - testUtils.testWithClient('client.keys', async client => { - assert.deepEqual( - await client.keys('pattern'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.keys', async client => { + assert.deepEqual( + await client.keys('pattern'), + [] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/KEYS.ts b/packages/client/lib/commands/KEYS.ts index 507681a56aa..488ba1154c9 100644 --- a/packages/client/lib/commands/KEYS.ts +++ b/packages/client/lib/commands/KEYS.ts @@ -1,6 +1,7 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(pattern: RedisArgument) { return ['KEYS', pattern]; diff --git a/packages/client/lib/commands/LCS.spec.ts b/packages/client/lib/commands/LCS.spec.ts index a4d9035571e..dd3c5917c3a 100644 --- a/packages/client/lib/commands/LCS.spec.ts +++ b/packages/client/lib/commands/LCS.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LCS'; +import LCS from './LCS'; describe('LCS', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('1', '2'), - ['LCS', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LCS.transformArguments('1', '2'), + ['LCS', '1', '2'] + ); + }); - testUtils.testWithClient('client.lcs', async client => { - assert.equal( - await client.lcs('1', '2'), - '' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lcs', async cluster => { - assert.equal( - await cluster.lcs('{tag}1', '{tag}2'), - '' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lcs', async client => { + assert.equal( + await client.lcs('1', '2'), + '' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LCS_LEN.spec.ts b/packages/client/lib/commands/LCS_LEN.spec.ts index bf4eefd3301..c3cffb0937c 100644 --- a/packages/client/lib/commands/LCS_LEN.spec.ts +++ b/packages/client/lib/commands/LCS_LEN.spec.ts @@ -1,28 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LCS_LEN'; +import LCS_LEN from './LCS_LEN'; describe('LCS_LEN', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('1', '2'), - ['LCS', '1', '2', 'LEN'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LCS_LEN.transformArguments('1', '2'), + ['LCS', '1', '2', 'LEN'] + ); + }); - testUtils.testWithClient('client.lcsLen', async client => { - assert.equal( - await client.lcsLen('1', '2'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lcsLen', async cluster => { - assert.equal( - await cluster.lcsLen('{tag}1', '{tag}2'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lcsLen', async client => { + assert.equal( + await client.lcsLen('1', '2'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LINDEX.spec.ts b/packages/client/lib/commands/LINDEX.spec.ts index aa3aafa789b..6fd68d9c4d4 100644 --- a/packages/client/lib/commands/LINDEX.spec.ts +++ b/packages/client/lib/commands/LINDEX.spec.ts @@ -1,36 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LINDEX'; -describe('LINDEX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0), - ['LINDEX', 'key', '0'] - ); - }); - - describe('client.lIndex', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.lIndex('key', 0), - null - ); - }, GLOBAL.SERVERS.OPEN); +import LINDEX from './LINDEX'; - testUtils.testWithClient('with value', async client => { - const [, lIndexReply] = await Promise.all([ - client.lPush('key', 'element'), - client.lIndex('key', 0) - ]); - - assert.equal(lIndexReply, 'element'); - }, GLOBAL.SERVERS.OPEN); - }); +describe('LINDEX', () => { + it('transformArguments', () => { + assert.deepEqual( + LINDEX.transformArguments('key', 0), + ['LINDEX', 'key', '0'] + ); + }); - testUtils.testWithCluster('cluster.lIndex', async cluster => { - assert.equal( - await cluster.lIndex('key', 0), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lIndex', async client => { + assert.equal( + await client.lIndex('key', 0), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); \ No newline at end of file diff --git a/packages/client/lib/commands/LINSERT.spec.ts b/packages/client/lib/commands/LINSERT.spec.ts index 6454cc48536..296683c23f0 100644 --- a/packages/client/lib/commands/LINSERT.spec.ts +++ b/packages/client/lib/commands/LINSERT.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LINSERT'; +import LINSERT from './LINSERT'; describe('LINSERT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'BEFORE', 'pivot', 'element'), - ['LINSERT', 'key', 'BEFORE', 'pivot', 'element'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LINSERT.transformArguments('key', 'BEFORE', 'pivot', 'element'), + ['LINSERT', 'key', 'BEFORE', 'pivot', 'element'] + ); + }); - testUtils.testWithClient('client.lInsert', async client => { - assert.equal( - await client.lInsert('key', 'BEFORE', 'pivot', 'element'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.lInsert', async cluster => { - assert.equal( - await cluster.lInsert('key', 'BEFORE', 'pivot', 'element'), - 0 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('lInsert', async client => { + assert.equal( + await client.lInsert('key', 'BEFORE', 'pivot', 'element'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LMOVE.spec.ts b/packages/client/lib/commands/LMOVE.spec.ts index c804614de5f..fef7f6deee5 100644 --- a/packages/client/lib/commands/LMOVE.spec.ts +++ b/packages/client/lib/commands/LMOVE.spec.ts @@ -14,7 +14,7 @@ describe('LMOVE', () => { testUtils.testAll('lMove', async client => { assert.equal( - await client.lMove('source', 'destination', 'LEFT', 'RIGHT'), + await client.lMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT'), null ); }, { diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts index f620714f4f4..ae9c2b69260 100644 --- a/packages/client/lib/commands/LMPOP.spec.ts +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -23,7 +23,7 @@ describe('LMPOP', () => { }); }); - testUtils.testAll('client.lmPop', async client => { + testUtils.testAll('lmPop', async client => { assert.deepEqual( await client.lmPop('key', 'RIGHT'), null diff --git a/packages/client/lib/commands/LSET.spec.ts b/packages/client/lib/commands/LSET.spec.ts index 0d34331603b..3f73e813958 100644 --- a/packages/client/lib/commands/LSET.spec.ts +++ b/packages/client/lib/commands/LSET.spec.ts @@ -11,6 +11,7 @@ describe('LSET', () => { }); testUtils.testAll('lSet', async client => { + await client.lPush('key', 'element'); assert.equal( await client.lSet('key', 0, 'element'), 'OK' diff --git a/packages/client/lib/commands/PING.ts b/packages/client/lib/commands/PING.ts index 5ca95f932d4..fabdfae6501 100644 --- a/packages/client/lib/commands/PING.ts +++ b/packages/client/lib/commands/PING.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(message?: RedisArgument) { const args: Array = ['PING']; diff --git a/packages/client/lib/commands/RANDOMKEY.ts b/packages/client/lib/commands/RANDOMKEY.ts index 81d956209ea..42028ebbe38 100644 --- a/packages/client/lib/commands/RANDOMKEY.ts +++ b/packages/client/lib/commands/RANDOMKEY.ts @@ -1,6 +1,7 @@ import { NumberReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { return ['RANDOMKEY']; diff --git a/packages/client/lib/commands/RENAME.ts b/packages/client/lib/commands/RENAME.ts index ded9e7e0b22..484eb350692 100644 --- a/packages/client/lib/commands/RENAME.ts +++ b/packages/client/lib/commands/RENAME.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAME', key, newKey]; diff --git a/packages/client/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts index 01dedc87798..f4bfac9005f 100644 --- a/packages/client/lib/commands/RENAMENX.ts +++ b/packages/client/lib/commands/RENAMENX.ts @@ -1,6 +1,7 @@ import { RedisArgument, SimpleStringReply, Command, NumberReply } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAMENX', key, newKey]; diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index 710a7b09be2..690f31c435b 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -28,6 +28,7 @@ export interface ScanOptions extends ScanCommonOptions { } export default { + FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(cursor: number, options?: ScanOptions) { const args = pushScanArguments(['SCAN'], cursor, options); diff --git a/packages/client/lib/commands/SORT_RO.spec.ts b/packages/client/lib/commands/SORT_RO.spec.ts index d1349df2274..c49efc11b3b 100644 --- a/packages/client/lib/commands/SORT_RO.spec.ts +++ b/packages/client/lib/commands/SORT_RO.spec.ts @@ -89,7 +89,7 @@ describe('SORT_RO', () => { }); }); - testUtils.testAll('client.sortRo', async client => { + testUtils.testAll('sortRo', async client => { assert.deepEqual( await client.sortRo('key'), [] diff --git a/packages/client/lib/commands/SPOP.spec.ts b/packages/client/lib/commands/SPOP.spec.ts index 1800d08622d..b5c67644f00 100644 --- a/packages/client/lib/commands/SPOP.spec.ts +++ b/packages/client/lib/commands/SPOP.spec.ts @@ -1,28 +1,22 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './SPOP'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SPOP from './SPOP'; -// describe('SPOP', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['SPOP', 'key'] -// ); -// }); +describe('SPOP', () => { + it('transformArguments', () => { + assert.deepEqual( + SPOP.transformArguments('key'), + ['SPOP', 'key'] + ); + }); -// it('with count', () => { -// assert.deepEqual( -// transformArguments('key', 2), -// ['SPOP', 'key', '2'] -// ); -// }); -// }); - -// testUtils.testWithClient('client.sPop', async client => { -// assert.equal( -// await client.sPop('key'), -// null -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('sPop', async client => { + assert.equal( + await client.sPop('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/SPOP.ts b/packages/client/lib/commands/SPOP.ts index 3566cd13dc5..4b061a86306 100644 --- a/packages/client/lib/commands/SPOP.ts +++ b/packages/client/lib/commands/SPOP.ts @@ -1,18 +1,10 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument, -// count?: number -// ): RedisCommandArguments { -// const args = ['SPOP', key]; - -// if (typeof count === 'number') { -// args.push(count.toString()); -// } - -// return args; -// } - -// export declare function transformReply(): Array; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument) { + return ['SPOP', key]; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SPOP_COUNT.spec.ts b/packages/client/lib/commands/SPOP_COUNT.spec.ts new file mode 100644 index 00000000000..cff078e9e16 --- /dev/null +++ b/packages/client/lib/commands/SPOP_COUNT.spec.ts @@ -0,0 +1,22 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SPOP_COUNT from './SPOP_COUNT'; + +describe('SPOP_COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + SPOP_COUNT.transformArguments('key', 1), + ['SPOP', 'key', '1'] + ); + }); + + testUtils.testAll('sPopCount', async client => { + assert.deepEqual( + await client.sPopCount('key', 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/SPOP_COUNT.ts b/packages/client/lib/commands/SPOP_COUNT.ts new file mode 100644 index 00000000000..4c68ae8d08e --- /dev/null +++ b/packages/client/lib/commands/SPOP_COUNT.ts @@ -0,0 +1,10 @@ +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, count: number) { + return ['SPOP', key, count.toString()]; + }, + transformReply: undefined as unknown as () => BlobStringReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SREM.spec.ts b/packages/client/lib/commands/SREM.spec.ts index 8df39102bc7..708fa04eae3 100644 --- a/packages/client/lib/commands/SREM.spec.ts +++ b/packages/client/lib/commands/SREM.spec.ts @@ -19,7 +19,7 @@ describe('SREM', () => { }); }); - testUtils.testAll('client.sRem', async client => { + testUtils.testAll('sRem', async client => { assert.equal( await client.sRem('key', 'member'), 0 diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 38f1c0fb09c..946d7ae5ead 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -42,7 +42,9 @@ import CLUSTER_MYID from './CLUSTER_MYID'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; import DECR from './DECR'; import DECRBY from './DECRBY'; +import GEODIST from './GEODIST'; import GET from './GET'; +import GETBIT from './GETBIT'; import GETDEL from './GETDEL'; import GETEX from './GETEX'; import GETRANGE from './GETRANGE'; @@ -69,6 +71,7 @@ import INCR from './INCR'; import INCRBY from './INCRBY'; import INCRBYFLOAT from './INCRBYFLOAT'; import INFO from './INFO'; +import KEYS from './KEYS'; // import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; // import LCS_IDX from './LCS_IDX'; import LCS_LEN from './LCS_LEN'; @@ -128,6 +131,8 @@ import SMISMEMBER from './SMISMEMBER'; import SORT_RO from './SORT_RO'; import SORT_STORE from './SORT_STORE'; import SORT from './SORT'; +import SPOP_COUNT from './SPOP_COUNT'; +import SPOP from './SPOP'; import SPUBLISH from './SPUBLISH'; import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; import SRANDMEMBER from './SRANDMEMBER'; @@ -257,6 +262,8 @@ export default { decrBy: DECRBY, GET, get: GET, + GETBIT, + getBit: GETBIT, GETDEL, getDel: GETDEL, GETEX, @@ -284,7 +291,7 @@ export default { HLEN, hLen: HLEN, HMGET, - hMGet: HMGET, + hmGet: HMGET, HRANDFIELD_COUNT_WITHVALUES, hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, HRANDFIELD_COUNT, @@ -296,7 +303,7 @@ export default { HSET, hSet: HSET, HSETNX, - hSetNx: HSETNX, + hSetNX: HSETNX, HSTRLEN, hStrLen: HSTRLEN, HVALS, @@ -309,6 +316,8 @@ export default { incrByFloat: INCRBYFLOAT, INFO, info: INFO, + KEYS, + keys: KEYS, // LCS_IDX_WITHMATCHLEN, // LCS_IDX, LCS_LEN, @@ -428,6 +437,10 @@ export default { sortStore: SORT_STORE, SORT, sort: SORT, + SPOP_COUNT, + sPopCount: SPOP_COUNT, + SPOP, + sPop: SPOP, SPUBLISH, sPublish: SPUBLISH, SRANDMEMBER_COUNT, From a8679f37eca6d5af29a04485c6089729b33e8876 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:10:04 -0400 Subject: [PATCH 089/325] clean code --- packages/client/lib/commands/LRANGE.spec.ts | 1 - packages/client/lib/commands/LREM.spec.ts | 1 - todo.md | 1 - 3 files changed, 3 deletions(-) diff --git a/packages/client/lib/commands/LRANGE.spec.ts b/packages/client/lib/commands/LRANGE.spec.ts index 12f0c8f7b9d..a5a70db6ee3 100644 --- a/packages/client/lib/commands/LRANGE.spec.ts +++ b/packages/client/lib/commands/LRANGE.spec.ts @@ -1,4 +1,3 @@ - import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import LRANGE from './LRANGE'; diff --git a/packages/client/lib/commands/LREM.spec.ts b/packages/client/lib/commands/LREM.spec.ts index bbc3f6096e9..40aff2e8af6 100644 --- a/packages/client/lib/commands/LREM.spec.ts +++ b/packages/client/lib/commands/LREM.spec.ts @@ -1,4 +1,3 @@ - import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import LREM from './LREM'; diff --git a/todo.md b/todo.md index 53d90d83ea8..c969748d183 100644 --- a/todo.md +++ b/todo.md @@ -11,7 +11,6 @@ # waiting List categoreis -- Hash - List - Set - Bitmap From 65c691fd756b72d34cf3c8331e584e9cec90f879 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:23:45 -0400 Subject: [PATCH 090/325] fix SMOVE --- docs/v4-to-v5.md | 1 + packages/client/lib/commands/SMOVE.spec.ts | 37 ++++++++++++---------- packages/client/lib/commands/SMOVE.ts | 25 ++++++++------- packages/client/lib/commands/index.ts | 3 ++ todo.md | 1 - 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 481bd95c696..29d23f49298 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -85,6 +85,7 @@ Some command arguments/replies have changed to align more closely to data types - `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] - `SISMEMBER`: `boolean` -> `number` [^boolean-to-number] - `SMISMEMBER`: `Array` -> `Array` [^boolean-to-number] +- `SMOVE`: `boolean` -> `number` [^boolean-to-number] [^enum-to-constants]: TODO diff --git a/packages/client/lib/commands/SMOVE.spec.ts b/packages/client/lib/commands/SMOVE.spec.ts index d3a9ca6eda6..60007ceffda 100644 --- a/packages/client/lib/commands/SMOVE.spec.ts +++ b/packages/client/lib/commands/SMOVE.spec.ts @@ -1,19 +1,22 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './SMOVE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SMOVE from './SMOVE'; -// describe('SMOVE', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('source', 'destination', 'member'), -// ['SMOVE', 'source', 'destination', 'member'] -// ); -// }); +describe('SMOVE', () => { + it('transformArguments', () => { + assert.deepEqual( + SMOVE.transformArguments('source', 'destination', 'member'), + ['SMOVE', 'source', 'destination', 'member'] + ); + }); -// testUtils.testWithClient('client.sMove', async client => { -// assert.equal( -// await client.sMove('source', 'destination', 'member'), -// false -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('sMove', async client => { + assert.equal( + await client.sMove('{tag}source', '{tag}destination', 'member'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/SMOVE.ts b/packages/client/lib/commands/SMOVE.ts index d6759c62122..183b363fb90 100644 --- a/packages/client/lib/commands/SMOVE.ts +++ b/packages/client/lib/commands/SMOVE.ts @@ -1,13 +1,14 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// source: RedisCommandArgument, -// destination: RedisCommandArgument, -// member: RedisCommandArgument -// ): RedisCommandArguments { -// return ['SMOVE', source, destination, member]; -// } - -// export { transformBooleanReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + source: RedisArgument, + destination: RedisArgument, + member: RedisArgument + ) { + return ['SMOVE', source, destination, member]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index e3985f82f87..143d9ce3abf 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -139,6 +139,7 @@ import SINTERSTORE from './SINTERSTORE'; import SISMEMBER from './SISMEMBER'; import SMEMBERS from './SMEMBERS'; import SMISMEMBER from './SMISMEMBER'; +import SMOVE from './SMOVE'; import SORT_RO from './SORT_RO'; import SORT_STORE from './SORT_STORE'; import SORT from './SORT'; @@ -479,6 +480,8 @@ export default { sMembers: SMEMBERS, SMISMEMBER, smIsMember: SMISMEMBER, + SMOVE, + sMove: SMOVE, SORT_RO, sortRo: SORT_RO, SORT_STORE, diff --git a/todo.md b/todo.md index c969748d183..3d7d0b36744 100644 --- a/todo.md +++ b/todo.md @@ -11,7 +11,6 @@ # waiting List categoreis -- List - Set - Bitmap From 92b38a1f37162cf0ea152472c55322ea4da9280f Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:26:56 -0400 Subject: [PATCH 091/325] fix SSCAN --- packages/client/lib/commands/SSCAN.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/SSCAN.spec.ts b/packages/client/lib/commands/SSCAN.spec.ts index 4cfb59445d1..3fe9edec8c2 100644 --- a/packages/client/lib/commands/SSCAN.spec.ts +++ b/packages/client/lib/commands/SSCAN.spec.ts @@ -40,7 +40,7 @@ describe('SSCAN', () => { }); }); - testUtils.testWithClient('client.sScan', async client => { + testUtils.testAll('sScan', async client => { assert.deepEqual( await client.sScan('key', 0), { @@ -48,5 +48,8 @@ describe('SSCAN', () => { members: [] } ); - }, GLOBAL.SERVERS.OPEN); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 627c9122efc839ec0632fb8a6cd0e9f5c0c7b3ba Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:40:36 -0400 Subject: [PATCH 092/325] fix SUNION --- packages/client/lib/commands/SUNION.spec.ts | 53 +++++++++++---------- packages/client/lib/commands/SUNION.ts | 25 +++++----- packages/client/lib/commands/index.ts | 3 ++ 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/client/lib/commands/SUNION.spec.ts b/packages/client/lib/commands/SUNION.spec.ts index b0ddf782f9d..d91baa9c66e 100644 --- a/packages/client/lib/commands/SUNION.spec.ts +++ b/packages/client/lib/commands/SUNION.spec.ts @@ -1,28 +1,31 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './SUNION'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SUNION from './SUNION'; -// describe('SUNION', () => { -// describe('transformArguments', () => { -// it('string', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['SUNION', 'key'] -// ); -// }); +describe('SUNION', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SUNION.transformArguments('key'), + ['SUNION', 'key'] + ); + }); -// it('array', () => { -// assert.deepEqual( -// transformArguments(['1', '2']), -// ['SUNION', '1', '2'] -// ); -// }); -// }); + it('array', () => { + assert.deepEqual( + SUNION.transformArguments(['1', '2']), + ['SUNION', '1', '2'] + ); + }); + }); -// testUtils.testWithClient('client.sUnion', async client => { -// assert.deepEqual( -// await client.sUnion('key'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('sUnion', async client => { + assert.deepEqual( + await client.sUnion('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/SUNION.ts b/packages/client/lib/commands/SUNION.ts index f9e7172acbb..42042217e2b 100644 --- a/packages/client/lib/commands/SUNION.ts +++ b/packages/client/lib/commands/SUNION.ts @@ -1,14 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// keys: RedisCommandArgument | Array -// ): RedisCommandArguments { -// return pushVariadicArguments(['SUNION'], keys); -// } - -// export declare function transformReply(): Array; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(keys: RedisVariadicArgument) { + return pushVariadicArguments(['SUNION'], keys); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 143d9ce3abf..3629b0357d6 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -151,6 +151,7 @@ import SRANDMEMBER from './SRANDMEMBER'; import SREM from './SREM'; import SSCAN from './SSCAN'; import STRLEN from './STRLEN'; +import SUNION from './SUNION'; import TOUCH from './TOUCH'; import TTL from './TTL'; import TYPE from './TYPE'; @@ -504,6 +505,8 @@ export default { sScan: SSCAN, STRLEN, strLen: STRLEN, + SUNION, + sUnion: SUNION, TOUCH, touch: TOUCH, TTL, From 4de409e0ad75cc7e0645aabb11d2d26aafafa4dc Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:51:12 -0400 Subject: [PATCH 093/325] fix SUNIONSTORE --- .../client/lib/commands/SUNIONSTORE.spec.ts | 53 ++++++++++--------- packages/client/lib/commands/SUNIONSTORE.ts | 25 ++++----- packages/client/lib/commands/index.ts | 3 ++ 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/packages/client/lib/commands/SUNIONSTORE.spec.ts b/packages/client/lib/commands/SUNIONSTORE.spec.ts index 4cf50132aa2..e9d288c0298 100644 --- a/packages/client/lib/commands/SUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/SUNIONSTORE.spec.ts @@ -1,28 +1,31 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './SUNIONSTORE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SUNIONSTORE from './SUNIONSTORE'; -// describe('SUNIONSTORE', () => { -// describe('transformArguments', () => { -// it('string', () => { -// assert.deepEqual( -// transformArguments('destination', 'key'), -// ['SUNIONSTORE', 'destination', 'key'] -// ); -// }); +describe('SUNIONSTORE', () => { + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SUNIONSTORE.transformArguments('destination', 'key'), + ['SUNIONSTORE', 'destination', 'key'] + ); + }); -// it('array', () => { -// assert.deepEqual( -// transformArguments('destination', ['1', '2']), -// ['SUNIONSTORE', 'destination', '1', '2'] -// ); -// }); -// }); + it('array', () => { + assert.deepEqual( + SUNIONSTORE.transformArguments('destination', ['1', '2']), + ['SUNIONSTORE', 'destination', '1', '2'] + ); + }); + }); -// testUtils.testWithClient('client.sUnionStore', async client => { -// assert.equal( -// await client.sUnionStore('destination', 'key'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('sUnionStore', async client => { + assert.equal( + await client.sUnionStore('{tag}destination', '{tag}key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/SUNIONSTORE.ts b/packages/client/lib/commands/SUNIONSTORE.ts index 1d5ee097caf..9adaa9288f3 100644 --- a/packages/client/lib/commands/SUNIONSTORE.ts +++ b/packages/client/lib/commands/SUNIONSTORE.ts @@ -1,13 +1,14 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// destination: RedisCommandArgument, -// keys: RedisCommandArgument | Array -// ): RedisCommandArguments { -// return pushVariadicArguments(['SUNIONSTORE', destination], keys); -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + keys: RedisVariadicArgument + ) { + return pushVariadicArguments(['SUNIONSTORE', destination], keys); + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 3629b0357d6..81dc8bd13d5 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -152,6 +152,7 @@ import SREM from './SREM'; import SSCAN from './SSCAN'; import STRLEN from './STRLEN'; import SUNION from './SUNION'; +import SUNIONSTORE from './SUNIONSTORE'; import TOUCH from './TOUCH'; import TTL from './TTL'; import TYPE from './TYPE'; @@ -507,6 +508,8 @@ export default { strLen: STRLEN, SUNION, sUnion: SUNION, + SUNIONSTORE, + sUnionStore: SUNIONSTORE, TOUCH, touch: TOUCH, TTL, From f6be2c77d8669ab3d94096a298853e0e7ec83eba Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 18:59:43 -0400 Subject: [PATCH 094/325] fix BITCOUNT spec --- packages/client/lib/commands/BITCOUNT.spec.ts | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/packages/client/lib/commands/BITCOUNT.spec.ts b/packages/client/lib/commands/BITCOUNT.spec.ts index 76e7b03f7c9..6744a6014fd 100644 --- a/packages/client/lib/commands/BITCOUNT.spec.ts +++ b/packages/client/lib/commands/BITCOUNT.spec.ts @@ -1,44 +1,47 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BITCOUNT'; +import BITCOUNT from './BITCOUNT'; describe('BITCOUNT', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key'), - ['BITCOUNT', 'key'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + BITCOUNT.transformArguments('key'), + ['BITCOUNT', 'key'] + ); + }); - describe('with range', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', { - start: 0, - end: 1 - }), - ['BITCOUNT', 'key', '0', '1'] - ); - }); + describe('with range', () => { + it('simple', () => { + assert.deepEqual( + BITCOUNT.transformArguments('key', { + start: 0, + end: 1 + }), + ['BITCOUNT', 'key', '0', '1'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments('key', { - start: 0, - end: 1, - mode: 'BIT' - }), - ['BITCOUNT', 'key', '0', '1', 'BIT'] - ); - }); - }); + it('with mode', () => { + assert.deepEqual( + BITCOUNT.transformArguments('key', { + start: 0, + end: 1, + mode: 'BIT' + }), + ['BITCOUNT', 'key', '0', '1', 'BIT'] + ); + }); }); + }); - testUtils.testWithClient('client.bitCount', async client => { - assert.equal( - await client.bitCount('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bitCount', async client => { + assert.equal( + await client.bitCount('key'), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From d5ef57893cd0a98031293af554a383a4e996b6d3 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 3 May 2023 19:03:43 -0400 Subject: [PATCH 095/325] fix BITPOS spec --- packages/client/lib/commands/BITPOS.spec.ts | 76 ++++++++++----------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/packages/client/lib/commands/BITPOS.spec.ts b/packages/client/lib/commands/BITPOS.spec.ts index 2a0758fe5da..8891f43a150 100644 --- a/packages/client/lib/commands/BITPOS.spec.ts +++ b/packages/client/lib/commands/BITPOS.spec.ts @@ -1,49 +1,45 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BITPOS'; +import BITPOS from './BITPOS'; -describe('BITPOS', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 1), - ['BITPOS', 'key', '1'] - ); - }); - - it('with start', () => { - assert.deepEqual( - transformArguments('key', 1, 1), - ['BITPOS', 'key', '1', '1'] - ); - }); +describe.only('BITPOS', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + BITPOS.transformArguments('key', 1), + ['BITPOS', 'key', '1'] + ); + }); - it('with start and end', () => { - assert.deepEqual( - transformArguments('key', 1, 1, -1), - ['BITPOS', 'key', '1', '1', '-1'] - ); - }); + it('with start', () => { + assert.deepEqual( + BITPOS.transformArguments('key', 1, 1), + ['BITPOS', 'key', '1', '1'] + ); + }); - it('with start, end and mode', () => { - assert.deepEqual( - transformArguments('key', 1, 1, -1, 'BIT'), - ['BITPOS', 'key', '1', '1', '-1', 'BIT'] - ); - }); + it('with start and end', () => { + assert.deepEqual( + BITPOS.transformArguments('key', 1, 1, -1), + ['BITPOS', 'key', '1', '1', '-1'] + ); }); - testUtils.testWithClient('client.bitPos', async client => { - assert.equal( - await client.bitPos('key', 1, 1), - -1 - ); - }, GLOBAL.SERVERS.OPEN); + it('with start, end and mode', () => { + assert.deepEqual( + BITPOS.transformArguments('key', 1, 1, -1, 'BIT'), + ['BITPOS', 'key', '1', '1', '-1', 'BIT'] + ); + }); + }); - testUtils.testWithCluster('cluster.bitPos', async cluster => { - assert.equal( - await cluster.bitPos('key', 1, 1), - -1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('bitPos', async client => { + assert.equal( + await client.bitPos('key', 1, 1), + -1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); From 6a0b4db4f750c4e6557ad54cf17eac82a1d5925c Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 8 May 2023 11:04:22 +0300 Subject: [PATCH 096/325] fix GEO* commands --- packages/client/lib/commands/GEOADD.spec.ts | 171 +++++++++--------- packages/client/lib/commands/GEOADD.ts | 10 +- packages/client/lib/commands/GEODIST.spec.ts | 91 +++++----- packages/client/lib/commands/GEODIST.ts | 2 +- packages/client/lib/commands/GEOHASH.spec.ts | 50 +++-- packages/client/lib/commands/GEOPOS.spec.ts | 104 +++++------ .../client/lib/commands/GEORADIUS.spec.ts | 51 +++--- packages/client/lib/commands/GEORADIUS.ts | 49 ++--- .../lib/commands/GEORADIUSBYMEMBER.spec.ts | 36 ++-- .../client/lib/commands/GEORADIUSBYMEMBER.ts | 47 ++--- .../commands/GEORADIUSBYMEMBERSTORE.spec.ts | 53 ------ .../lib/commands/GEORADIUSBYMEMBERSTORE.ts | 25 --- .../lib/commands/GEORADIUSBYMEMBER_RO.spec.ts | 36 ++-- .../lib/commands/GEORADIUSBYMEMBER_RO.ts | 34 +--- .../GEORADIUSBYMEMBER_RO_WITH.spec.ts | 59 +++--- .../lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts | 39 +--- .../commands/GEORADIUSBYMEMBER_STORE.spec.ts | 39 ++++ .../lib/commands/GEORADIUSBYMEMBER_STORE.ts | 31 ++++ .../commands/GEORADIUSBYMEMBER_WITH.spec.ts | 59 +++--- .../lib/commands/GEORADIUSBYMEMBER_WITH.ts | 56 +++--- .../lib/commands/GEORADIUSSTORE.spec.ts | 53 ------ .../client/lib/commands/GEORADIUSSTORE.ts | 25 --- .../client/lib/commands/GEORADIUS_RO.spec.ts | 51 +++--- packages/client/lib/commands/GEORADIUS_RO.ts | 34 +--- .../lib/commands/GEORADIUS_RO_WITH.spec.ts | 72 ++++---- .../client/lib/commands/GEORADIUS_RO_WITH.ts | 39 +--- .../lib/commands/GEORADIUS_STORE.spec.ts | 48 +++++ .../client/lib/commands/GEORADIUS_STORE.ts | 31 ++++ .../lib/commands/GEORADIUS_WITH.spec.ts | 72 ++++---- .../client/lib/commands/GEORADIUS_WITH.ts | 59 +++--- .../client/lib/commands/GEOSEARCH.spec.ts | 98 +++++++--- packages/client/lib/commands/GEOSEARCH.ts | 107 +++++++++-- .../lib/commands/GEOSEARCHSTORE.spec.ts | 109 ++++------- .../client/lib/commands/GEOSEARCHSTORE.ts | 57 +++--- .../lib/commands/GEOSEARCH_WITH.spec.ts | 73 ++++---- .../client/lib/commands/GEOSEARCH_WITH.ts | 82 +++++++-- packages/client/lib/commands/index.ts | 51 ++++++ 37 files changed, 1114 insertions(+), 989 deletions(-) delete mode 100644 packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts delete mode 100644 packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts create mode 100644 packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts create mode 100644 packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts delete mode 100644 packages/client/lib/commands/GEORADIUSSTORE.spec.ts delete mode 100644 packages/client/lib/commands/GEORADIUSSTORE.ts create mode 100644 packages/client/lib/commands/GEORADIUS_STORE.spec.ts create mode 100644 packages/client/lib/commands/GEORADIUS_STORE.ts diff --git a/packages/client/lib/commands/GEOADD.spec.ts b/packages/client/lib/commands/GEOADD.spec.ts index 6425c881c9d..3b9584aed0a 100644 --- a/packages/client/lib/commands/GEOADD.spec.ts +++ b/packages/client/lib/commands/GEOADD.spec.ts @@ -1,95 +1,100 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOADD'; +import GEOADD from './GEOADD'; describe('GEOADD', () => { - describe('transformArguments', () => { - it('one member', () => { - assert.deepEqual( - transformArguments('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - ['GEOADD', 'key', '1', '2', 'member'] - ); - }); + describe('transformArguments', () => { + it('one member', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + ['GEOADD', 'key', '1', '2', 'member'] + ); + }); - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', [{ - longitude: 1, - latitude: 2, - member: '3', - }, { - longitude: 4, - latitude: 5, - member: '6', - }]), - ['GEOADD', 'key', '1', '2', '3', '4', '5', '6'] - ); - }); + it('multiple members', () => { + assert.deepEqual( + GEOADD.transformArguments('key', [{ + longitude: 1, + latitude: 2, + member: '3', + }, { + longitude: 4, + latitude: 5, + member: '6', + }]), + ['GEOADD', 'key', '1', '2', '3', '4', '5', '6'] + ); + }); - it('with NX', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - NX: true - }), - ['GEOADD', 'key', 'NX', '1', '2', 'member'] - ); - }); + it('with condition', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + condition: 'NX' + }), + ['GEOADD', 'key', 'NX', '1', '2', 'member'] + ); + }); - it('with CH', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - CH: true - }), - ['GEOADD', 'key', 'CH', '1', '2', 'member'] - ); - }); + it('with NX (backwards compatibility)', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + NX: true + }), + ['GEOADD', 'key', 'NX', '1', '2', 'member'] + ); + }); - it('with XX, CH', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - XX: true, - CH: true - }), - ['GEOADD', 'key', 'XX', 'CH', '1', '2', 'member'] - ); - }); + it('with CH', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + CH: true + }), + ['GEOADD', 'key', 'CH', '1', '2', 'member'] + ); }); - testUtils.testWithClient('client.geoAdd', async client => { - assert.equal( - await client.geoAdd('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + it('with condition, CH', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + condition: 'XX', + CH: true + }), + ['GEOADD', 'key', 'XX', 'CH', '1', '2', 'member'] + ); + }); + }); - testUtils.testWithCluster('cluster.geoAdd', async cluster => { - assert.equal( - await cluster.geoAdd('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoAdd', async client => { + assert.equal( + await client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOADD.ts b/packages/client/lib/commands/GEOADD.ts index 2a34b5d5607..f89f6b80e82 100644 --- a/packages/client/lib/commands/GEOADD.ts +++ b/packages/client/lib/commands/GEOADD.ts @@ -1,12 +1,12 @@ -import { CommandArguments, RedisArgument, NumberReply, Command } from '../RESP/types'; -import { GeoCoordinates } from './generic-transformers'; +import { RedisArgument, CommandArguments, NumberReply, Command } from '../RESP/types'; +import { GeoCoordinates } from './GEOSEARCH'; -interface GeoMember extends GeoCoordinates { +export interface GeoMember extends GeoCoordinates { member: RedisArgument; } -interface GeoAddOptions { - condition: 'NX' | 'XX'; +export interface GeoAddOptions { + condition?: 'NX' | 'XX'; /** * @deprecated Use `{ condition: 'NX' }` instead. */ diff --git a/packages/client/lib/commands/GEODIST.spec.ts b/packages/client/lib/commands/GEODIST.spec.ts index bbc62480ee1..2e0af2a9575 100644 --- a/packages/client/lib/commands/GEODIST.spec.ts +++ b/packages/client/lib/commands/GEODIST.spec.ts @@ -1,57 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEODIST'; +import GEODIST from './GEODIST'; describe('GEODIST', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', '1', '2'), - ['GEODIST', 'key', '1', '2'] - ); - }); - - it('with unit', () => { - assert.deepEqual( - transformArguments('key', '1', '2', 'm'), - ['GEODIST', 'key', '1', '2', 'm'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + GEODIST.transformArguments('key', '1', '2'), + ['GEODIST', 'key', '1', '2'] + ); }); - describe('client.geoDist', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.geoDist('key', '1', '2'), - null - ); - }, GLOBAL.SERVERS.OPEN); + it('with unit', () => { + assert.deepEqual( + GEODIST.transformArguments('key', '1', '2', 'm'), + ['GEODIST', 'key', '1', '2', 'm'] + ); + }); + }); - testUtils.testWithClient('with value', async client => { - const [, dist] = await Promise.all([ - client.geoAdd('key', [{ - member: '1', - longitude: 1, - latitude: 1 - }, { - member: '2', - longitude: 2, - latitude: 2 - }]), - client.geoDist('key', '1', '2') - ]); + testUtils.testAll('geoDist null', async client => { + assert.equal( + await client.geoDist('key', '1', '2'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); - assert.equal( - dist, - 157270.0561 - ); - }, GLOBAL.SERVERS.OPEN); - }); + testUtils.testAll('geoDist with member', async client => { + const [, dist] = await Promise.all([ + client.geoAdd('key', [{ + member: '1', + longitude: 1, + latitude: 1 + }, { + member: '2', + longitude: 2, + latitude: 2 + }]), + client.geoDist('key', '1', '2') + ]); - testUtils.testWithCluster('cluster.geoDist', async cluster => { - assert.equal( - await cluster.geoDist('key', '1', '2'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal( + dist, + 157270.0561 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEODIST.ts b/packages/client/lib/commands/GEODIST.ts index da6dee1b774..dc5bcf1f12c 100644 --- a/packages/client/lib/commands/GEODIST.ts +++ b/packages/client/lib/commands/GEODIST.ts @@ -13,7 +13,7 @@ export default { const args = ['GEODIST', key, member1, member2]; if (unit) { - args.push(unit); + args.push(unit); } return args; diff --git a/packages/client/lib/commands/GEOHASH.spec.ts b/packages/client/lib/commands/GEOHASH.spec.ts index c421c148f43..0d575b487ab 100644 --- a/packages/client/lib/commands/GEOHASH.spec.ts +++ b/packages/client/lib/commands/GEOHASH.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOHASH'; +import GEOHASH from './GEOHASH'; describe('GEOHASH', () => { - describe('transformArguments', () => { - it('single member', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['GEOHASH', 'key', 'member'] - ); - }); - - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['GEOHASH', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + GEOHASH.transformArguments('key', 'member'), + ['GEOHASH', 'key', 'member'] + ); }); - testUtils.testWithClient('client.geoHash', async client => { - assert.deepEqual( - await client.geoHash('key', 'member'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + it('multiple members', () => { + assert.deepEqual( + GEOHASH.transformArguments('key', ['1', '2']), + ['GEOHASH', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.geoHash', async cluster => { - assert.deepEqual( - await cluster.geoHash('key', 'member'), - [null] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoHash', async client => { + assert.deepEqual( + await client.geoHash('key', 'member'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOPOS.spec.ts b/packages/client/lib/commands/GEOPOS.spec.ts index 9c08ccd08f5..297faba490b 100644 --- a/packages/client/lib/commands/GEOPOS.spec.ts +++ b/packages/client/lib/commands/GEOPOS.spec.ts @@ -1,73 +1,51 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEOPOS'; +import GEOPOS from './GEOPOS'; describe('GEOPOS', () => { - describe('transformArguments', () => { - it('single member', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['GEOPOS', 'key', 'member'] - ); - }); - - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['GEOPOS', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + GEOPOS.transformArguments('key', 'member'), + ['GEOPOS', 'key', 'member'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.deepEqual( - transformReply([null]), - [null] - ); - }); - - it('with member', () => { - assert.deepEqual( - transformReply([['1', '2']]), - [{ - longitude: '1', - latitude: '2' - }] - ); - }); + it('multiple members', () => { + assert.deepEqual( + GEOPOS.transformArguments('key', ['1', '2']), + ['GEOPOS', 'key', '1', '2'] + ); }); - - describe('client.geoPos', () => { - testUtils.testWithClient('null', async client => { - assert.deepEqual( - await client.geoPos('key', 'member'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with member', async client => { - const coordinates = { - longitude: '-122.06429868936538696', - latitude: '37.37749628831998194' - }; - - await client.geoAdd('key', { - member: 'member', - ...coordinates - }); - - assert.deepEqual( - await client.geoPos('key', 'member'), - [coordinates] - ); - }, GLOBAL.SERVERS.OPEN); + }); + + testUtils.testAll('geoPos null', async client => { + assert.deepEqual( + await client.geoPos('key', 'member'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('geoPos with member', async client => { + const coordinates = { + longitude: '-122.06429868936538696', + latitude: '37.37749628831998194' + }; + + await client.geoAdd('key', { + member: 'member', + ...coordinates }); - testUtils.testWithCluster('cluster.geoPos', async cluster => { - assert.deepEqual( - await cluster.geoPos('key', 'member'), - [null] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.deepEqual( + await client.geoPos('key', 'member'), + [coordinates] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS.spec.ts b/packages/client/lib/commands/GEORADIUS.spec.ts index 786b2665029..28975864877 100644 --- a/packages/client/lib/commands/GEORADIUS.spec.ts +++ b/packages/client/lib/commands/GEORADIUS.spec.ts @@ -1,35 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUS'; +import GEORADIUS from './GEORADIUS'; describe('GEORADIUS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - ['GEORADIUS', 'key', '1', '2', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUS.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + ['GEORADIUS', 'key', '1', '2', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadius', async client => { - assert.deepEqual( - await client.geoRadius('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadius', async cluster => { - assert.deepEqual( - await cluster.geoRadius('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadius', async client => { + assert.deepEqual( + await client.geoRadius('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS.ts b/packages/client/lib/commands/GEORADIUS.ts index 4b5af7a078e..e777432f090 100644 --- a/packages/client/lib/commands/GEORADIUS.ts +++ b/packages/client/lib/commands/GEORADIUS.ts @@ -1,25 +1,32 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { GeoCoordinates, GeoUnits, GeoSearchOptions, pushGeoSearchOptions } from './GEOSEARCH'; -// export const FIRST_KEY_INDEX = 1; +export function transformGeoRadiusArguments( + command: RedisArgument, + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + options?: GeoSearchOptions +) { + const args = [ + command, + key, + from.longitude.toString(), + from.latitude.toString(), + radius.toString(), + unit + ]; -// export const IS_READ_ONLY = true; + pushGeoSearchOptions(args, options); -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUS'], -// key, -// coordinates, -// radius, -// unit, -// options -// ); -// } + return args; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transformGeoRadiusArguments.bind(undefined, 'GEORADIUS'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; -// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts index 8cc4212c839..b44a649bcea 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUSBYMEMBER'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; describe('GEORADIUSBYMEMBER', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm'), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUSBYMEMBER.transformArguments('key', 'member', 3, 'm'), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusByMember', async client => { - assert.deepEqual( - await client.geoRadiusByMember('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMember', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMember('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusByMember', async client => { + assert.deepEqual( + await client.geoRadiusByMember('key', 'member', 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts index ab6950ac8db..13b52a30630 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts @@ -1,25 +1,30 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { GeoUnits, GeoSearchOptions, pushGeoSearchOptions } from './GEOSEARCH'; -// export const FIRST_KEY_INDEX = 1; +export function transformGeoRadiusByMemberArguments( + command: RedisArgument, + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + options?: GeoSearchOptions +) { + const args = [ + command, + key, + from, + radius.toString(), + unit + ]; -// export const IS_READ_ONLY = true; + pushGeoSearchOptions(args, options); -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUSBYMEMBER'], -// key, -// member, -// radius, -// unit, -// options -// ); -// } + return args; +} -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transformGeoRadiusByMemberArguments.bind(undefined, 'GEORADIUSBYMEMBER'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts deleted file mode 100644 index 100ecc03368..00000000000 --- a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEORADIUSBYMEMBERSTORE'; - -describe('GEORADIUSBYMEMBERSTORE', () => { - describe('transformArguments', () => { - it('STORE', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', 'dest', { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STORE', 'dest'] - ); - }); - - it('STOREDIST', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', 'dest', { STOREDIST: true }), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STOREDIST', 'dest'] - ); - }); - }); - - testUtils.testWithClient('client.geoRadiusByMemberStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoRadiusByMemberStore('source', 'member', 3 , 'm', 'dest'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMemberStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoRadiusByMemberStore('{tag}source', 'member', 3 , 'm','{tag}destination'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); -}); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts deleted file mode 100644 index ea1674cf3fc..00000000000 --- a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts +++ /dev/null @@ -1,25 +0,0 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// destination: RedisCommandArgument, -// options?: GeoRadiusStoreOptions, -// ): RedisCommandArguments { -// return pushGeoRadiusStoreArguments( -// ['GEORADIUSBYMEMBER'], -// key, -// member, -// radius, -// unit, -// destination, -// options -// ); -// } - -// export declare function transformReply(): number diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts index f3a47856e86..47e4dabbbcc 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUSBYMEMBER_RO'; +import GEORADIUSBYMEMBER_RO from './GEORADIUSBYMEMBER_RO'; describe('GEORADIUSBYMEMBER_RO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm'), - ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_RO.transformArguments('key', 'member', 3, 'm'), + ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberRo', async client => { - assert.deepEqual( - await client.geoRadiusByMemberRo('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMemberRo', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberRo('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusByMemberRo', async client => { + assert.deepEqual( + await client.geoRadiusByMemberRo('key', 'member', 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts index 1ad9450ae38..7f85ed15df7 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts @@ -1,25 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUSBYMEMBER_RO'], -// key, -// member, -// radius, -// unit, -// options -// ); -// } - -// export declare function transformReply(): Array; +import { Command } from '../RESP/types'; +import GEORADIUSBYMEMBER, { transformGeoRadiusByMemberArguments } from './GEORADIUSBYMEMBER'; + +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusByMemberArguments.bind(undefined, 'GEORADIUSBYMEMBER_RO'), + transformReply: GEORADIUSBYMEMBER.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts index 7904a763998..166088495e1 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts @@ -1,31 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUSBYMEMBER_RO_WITH'; +import GEORADIUSBYMEMBER_RO_WITH from './GEORADIUSBYMEMBER_RO_WITH'; +import { CommandArguments } from '../RESP/types'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; describe('GEORADIUSBYMEMBER_RO WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUSBYMEMBER_RO_WITH.transformArguments('key', 'member', 3, 'm', [ + GEO_REPLY_WITH.DISTANCE + ]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberRoWith', async client => { - assert.deepEqual( - await client.geoRadiusByMemberRoWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusByMemberRoWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusByMemberRoWith('key', 'member', 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusByMemberRoWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberRoWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates?.longitude, 'string'); + assert.equal(typeof reply[0].coordinates?.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts index 116bb9200fa..5fb945a1f9c 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts @@ -1,30 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -// import { transformArguments as geoRadiusTransformArguments } from './GEORADIUSBYMEMBER_RO'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER_RO'; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = geoRadiusTransformArguments( -// key, -// member, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +import { Command } from '../RESP/types'; +import GEORADIUSBYMEMBER_WITH, { transformGeoRadiusByMemberWithArguments } from './GEORADIUSBYMEMBER_WITH'; + +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER_WITH.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusByMemberWithArguments.bind(undefined, 'GEORADIUSBYMEMBER_RO'), + transformReply: GEORADIUSBYMEMBER_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts new file mode 100644 index 00000000000..6eab34211a7 --- /dev/null +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts @@ -0,0 +1,39 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import GEORADIUSBYMEMBER_STORE from './GEORADIUSBYMEMBER_STORE'; + +describe('GEORADIUSBYMEMBER STORE', () => { + describe('transformArguments', () => { + it('STORE', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_STORE.transformArguments('key', 'member', 3, 'm', 'destination'), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STORE', 'destination'] + ); + }); + + it('STOREDIST', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_STORE.transformArguments('key', 'member', 3, 'm', 'destination', { + STOREDIST: true + }), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STOREDIST', 'destination'] + ); + }); + }); + + testUtils.testAll('geoRadiusByMemberStore', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('{tag}source', { + longitude: 1, + latitude: 2, + member: 'member' + }), + client.geoRadiusByMemberStore('{tag}source', 'member', 3, 'm', '{tag}destination') + ]); + + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts new file mode 100644 index 00000000000..90419963110 --- /dev/null +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts @@ -0,0 +1,31 @@ +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import GEORADIUSBYMEMBER, { transformGeoRadiusByMemberArguments } from './GEORADIUSBYMEMBER'; +import { GeoSearchOptions, GeoUnits } from './GEOSEARCH'; + +export interface GeoRadiusStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} + +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUSBYMEMBER.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + destination: RedisArgument, + options?: GeoRadiusStoreOptions + ) { + const args = transformGeoRadiusByMemberArguments('GEORADIUSBYMEMBER', key, from, radius, unit, options); + + if (options?.STOREDIST) { + args.push('STOREDIST', destination); + } else { + args.push('STORE', destination); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts index 24bffd9e89f..3160c65cfb8 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts @@ -1,31 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUSBYMEMBER_WITH'; +import GEORADIUSBYMEMBER_WITH from './GEORADIUSBYMEMBER_WITH'; +import { CommandArguments } from '../RESP/types'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; describe('GEORADIUSBYMEMBER WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUSBYMEMBER_WITH.transformArguments('key', 'member', 3, 'm', [ + GEO_REPLY_WITH.DISTANCE + ]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberWith', async client => { - assert.deepEqual( - await client.geoRadiusByMemberWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusByMemberWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusByMemberWith('key', 'member', 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusByMemberWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts index 09bb5bbbb44..31480430b5f 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts @@ -1,30 +1,36 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUSBYMEMBER'; +import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; +import { GeoSearchOptions, GeoUnits, pushGeoSearchOptions } from './GEOSEARCH'; +import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; +export function transformGeoRadiusByMemberWithArguments( + command: RedisArgument, + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + replyWith: Array, + options?: GeoSearchOptions +) { + const args: CommandArguments = [ + command, + key, + from, + radius.toString(), + unit + ]; -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusArguments( -// key, -// member, -// radius, -// unit, -// options -// ); + pushGeoSearchOptions(args, options); -// args.push(...replyWith); + args.push(...replyWith); + args.preserve = replyWith; -// args.preserve = replyWith; + return args; +} -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUSBYMEMBER.IS_READ_ONLY, + transformArguments: transformGeoRadiusByMemberWithArguments.bind(undefined, 'GEORADIUSBYMEMBER'), + transformReply: GEOSEARCH_WITH.transformReply +} as const satisfies Command; \ No newline at end of file diff --git a/packages/client/lib/commands/GEORADIUSSTORE.spec.ts b/packages/client/lib/commands/GEORADIUSSTORE.spec.ts deleted file mode 100644 index 4c6372732e5..00000000000 --- a/packages/client/lib/commands/GEORADIUSSTORE.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEORADIUSSTORE'; - -describe('GEORADIUSSTORE', () => { - describe('transformArguments', () => { - it('STORE', () => { - assert.deepEqual( - transformArguments('key', {longitude: 1, latitude: 2}, 3 , 'm', 'dest', { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEORADIUS', 'key', '1', '2', '3', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STORE', 'dest'] - ); - }); - - it('STOREDIST', () => { - assert.deepEqual( - transformArguments('key', {longitude: 1, latitude: 2}, 3 , 'm', 'dest', { STOREDIST: true }), - ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STOREDIST', 'dest'] - ); - }); - }); - - testUtils.testWithClient('client.geoRadiusStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoRadiusStore('source', {longitude: 1, latitude: 1}, 3 , 'm', 'dest'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoRadiusStore('{tag}source', {longitude: 1, latitude: 1}, 3 , 'm', '{tag}destination'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); -}); diff --git a/packages/client/lib/commands/GEORADIUSSTORE.ts b/packages/client/lib/commands/GEORADIUSSTORE.ts deleted file mode 100644 index 03445259648..00000000000 --- a/packages/client/lib/commands/GEORADIUSSTORE.ts +++ /dev/null @@ -1,25 +0,0 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoCoordinates, GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// destination: RedisCommandArgument, -// options?: GeoRadiusStoreOptions, -// ): RedisCommandArguments { -// return pushGeoRadiusStoreArguments( -// ['GEORADIUS'], -// key, -// coordinates, -// radius, -// unit, -// destination, -// options -// ); -// } - -// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/GEORADIUS_RO.spec.ts b/packages/client/lib/commands/GEORADIUS_RO.spec.ts index b3cdca18d3f..6f6aeb80e67 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.spec.ts @@ -1,35 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUS_RO'; +import GEORADIUS_RO from './GEORADIUS_RO'; describe('GEORADIUS_RO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - ['GEORADIUS_RO', 'key', '1', '2', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUS_RO.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + ['GEORADIUS_RO', 'key', '1', '2', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusRo', async client => { - assert.deepEqual( - await client.geoRadiusRo('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusRo', async cluster => { - assert.deepEqual( - await cluster.geoRadiusRo('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusRo', async client => { + assert.deepEqual( + await client.geoRadiusRo('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_RO.ts b/packages/client/lib/commands/GEORADIUS_RO.ts index d9c01007ed9..be8bb4b530d 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.ts @@ -1,25 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUS_RO'], -// key, -// coordinates, -// radius, -// unit, -// options -// ); -// } - -// export declare function transformReply(): Array; +import { Command } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; + +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusArguments.bind(undefined, 'GEORADIUS_RO'), + transformReply: GEORADIUS.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts index 21b00ff90b8..639b1917028 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts @@ -1,40 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUS_RO_WITH'; +import GEORADIUS_RO_WITH from './GEORADIUS_RO_WITH'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEORADIUS_RO WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUS_RO', 'key', '1', '2', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUS_RO', 'key', '1', '2', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUS_RO_WITH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusRoWith', async client => { - assert.deepEqual( - await client.geoRadiusRoWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusRoWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusRoWith('key', { + longitude: 1, + latitude: 2 + }, 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusReadOnlyWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusRoWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts index 156f5cfa9f4..37cf594ce9d 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts @@ -1,30 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusRoArguments } from './GEORADIUS_RO'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS_RO'; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusRoArguments( -// key, -// coordinates, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +import { Command } from '../RESP/types'; +import GEORADIUS_WITH, { transformGeoRadiusWithArguments } from './GEORADIUS_WITH'; + +export default { + FIRST_KEY_INDEX: GEORADIUS_WITH.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusWithArguments.bind(undefined, 'GEORADIUS_RO'), + transformReply: GEORADIUS_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_STORE.spec.ts b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts new file mode 100644 index 00000000000..3fff9bc43dc --- /dev/null +++ b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts @@ -0,0 +1,48 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import GEORADIUS_STORE from './GEORADIUS_STORE'; + +describe('GEORADIUS STORE', () => { + describe('transformArguments', () => { + it('STORE', () => { + assert.deepEqual( + GEORADIUS_STORE.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', 'destination'), + ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STORE', 'destination'] + ); + }); + + it('STOREDIST', () => { + assert.deepEqual( + GEORADIUS_STORE.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', 'destination', { + STOREDIST: true + }), + ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STOREDIST', 'destination'] + ); + }); + }); + + testUtils.testAll('geoRadiusStore', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('{tag}source', { + longitude: 1, + latitude: 2, + member: 'member' + }), + client.geoRadiusStore('{tag}source', { + longitude: 1, + latitude: 2 + }, 1, 'm', '{tag}destination') + ]); + + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/GEORADIUS_STORE.ts b/packages/client/lib/commands/GEORADIUS_STORE.ts new file mode 100644 index 00000000000..3a553ebf8be --- /dev/null +++ b/packages/client/lib/commands/GEORADIUS_STORE.ts @@ -0,0 +1,31 @@ +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; +import { GeoCoordinates, GeoSearchOptions, GeoUnits } from './GEOSEARCH'; + +export interface GeoRadiusStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} + +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUS.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + destination: RedisArgument, + options?: GeoRadiusStoreOptions + ) { + const args = transformGeoRadiusArguments('GEORADIUS', key, from, radius, unit, options); + + if (options?.STOREDIST) { + args.push('STOREDIST', destination); + } else { + args.push('STORE', destination); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts index 44366198beb..2219aa8490e 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts @@ -1,40 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUS_WITH'; +import GEORADIUS_WITH from './GEORADIUS_WITH'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEORADIUS WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUS', 'key', '1', '2', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUS', 'key', '1', '2', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUS_WITH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusWith', async client => { - assert.deepEqual( - await client.geoRadiusWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusWith('key', { + longitude: 1, + latitude: 2 + }, 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates?.longitude, 'string'); + assert.equal(typeof reply[0].coordinates?.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_WITH.ts b/packages/client/lib/commands/GEORADIUS_WITH.ts index d41132ce2d6..d72d8d49322 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.ts @@ -1,30 +1,33 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUS'; +import { CommandArguments, Command, RedisArgument } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; +import { GeoCoordinates, GeoSearchOptions, GeoUnits } from './GEOSEARCH'; +import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; +export function transformGeoRadiusWithArguments( + command: RedisArgument, + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + replyWith: Array, + options?: GeoSearchOptions +) { + const args: CommandArguments = transformGeoRadiusArguments( + command, + key, + from, + radius, + unit, + options + ); + args.push(...replyWith); + args.preserve = replyWith; + return args; +} -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusArguments( -// key, -// coordinates, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUS.IS_READ_ONLY, + transformArguments: transformGeoRadiusWithArguments.bind(undefined, 'GEORADIUS'), + transformReply: GEOSEARCH_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCH.spec.ts b/packages/client/lib/commands/GEOSEARCH.spec.ts index ec0d4bcc4f8..7f06d646b18 100644 --- a/packages/client/lib/commands/GEOSEARCH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH.spec.ts @@ -1,37 +1,87 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOSEARCH'; +import GEOSEARCH from './GEOSEARCH'; describe('GEOSEARCH', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', { - radius: 1, - unit: 'm' - }), - ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] - ); + describe('transformArguments', () => { + it('FROMMEMBER, BYRADIUS, without options', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] + ); + }); + + it('FROMLONLAT, BYBOX, without options', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, { + width: 1, + height: 2, + unit: 'm' + }), + ['GEOSEARCH', 'key', 'FROMLONLAT', '1', '2', 'BYBOX', '1', '2', 'm'] + ); }); - testUtils.testWithClient('client.geoSearch', async client => { + it('with SORT', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + SORT: 'ASC' + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC'] + ); + }); + + describe('with COUNT', () => { + it('number', () => { assert.deepEqual( - await client.geoSearch('key', 'member', { - radius: 1, - unit: 'm' - }), - [] + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + COUNT: 1 + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'COUNT', '1'] ); - }, GLOBAL.SERVERS.OPEN); + }); - testUtils.testWithCluster('cluster.geoSearch', async cluster => { + it('with ANY', () => { assert.deepEqual( - await cluster.geoSearch('key', 'member', { - radius: 1, - unit: 'm' - }), - [] + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + COUNT: { + value: 1, + ANY: true + } + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'COUNT', '1', 'ANY'] ); - }, GLOBAL.CLUSTERS.OPEN); + }); + }); + }); + + testUtils.testAll('geoSearch', async client => { + assert.deepEqual( + await client.geoSearch('key', 'member', { + radius: 1, + unit: 'm' + }), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCH.ts b/packages/client/lib/commands/GEOSEARCH.ts index 31a65ee8dce..4e81f361dd9 100644 --- a/packages/client/lib/commands/GEOSEARCH.ts +++ b/packages/client/lib/commands/GEOSEARCH.ts @@ -1,17 +1,98 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; +export type GeoUnits = 'm' | 'km' | 'mi' | 'ft'; -// export const IS_READ_ONLY = true; +export interface GeoCoordinates { + longitude: RedisArgument | number; + latitude: RedisArgument | number; +} -// export function transformArguments( -// key: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); -// } +export type GeoSearchFrom = RedisArgument | GeoCoordinates; -// export declare function transformReply(): Array; +export interface GeoSearchByRadius { + radius: number; + unit: GeoUnits; +} + +export interface GeoSearchByBox { + width: number; + height: number; + unit: GeoUnits; +} + +export type GeoSearchBy = GeoSearchByRadius | GeoSearchByBox; + +export function pushGeoSearchArguments( + args: CommandArguments, + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchOptions +) { + args.push(key); + + if (typeof from === 'string' || from instanceof Buffer) { + args.push('FROMMEMBER', from); + } else { + args.push('FROMLONLAT', from.longitude.toString(), from.latitude.toString()); + } + + if ('radius' in by) { + args.push('BYRADIUS', by.radius.toString(), by.unit); + } else { + args.push('BYBOX', by.width.toString(), by.height.toString(), by.unit); + } + + if (options?.SORT) { + args.push(options.SORT); + } + + pushGeoSearchOptions(args, options); + + return args; +} + +export type GeoCountArgument = number | { + value: number; + ANY?: boolean; +}; + +export interface GeoSearchOptions { + SORT?: 'ASC' | 'DESC'; + COUNT?: GeoCountArgument; +} + +export function pushGeoSearchOptions( + args: CommandArguments, + options?: GeoSearchOptions +) { + if (options?.SORT) { + args.push(options.SORT); + } + + if (options?.COUNT) { + if (typeof options.COUNT === 'number') { + args.push('COUNT', options.COUNT.toString()); + } else { + args.push('COUNT', options.COUNT.value.toString()); + + if (options.COUNT.ANY) { + args.push('ANY'); + } + } + } +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchOptions + ) { + return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts index eb32fa134e4..6b270af8dca 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts @@ -1,81 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEOSEARCHSTORE'; +import GEOSEARCHSTORE from './GEOSEARCHSTORE'; describe('GEOSEARCHSTORE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); - - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }, { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC', 'COUNT', '1', 'ANY'] - ); - }); - - it('with STOREDIST', () => { - assert.deepEqual( - transformArguments('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }, { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - }, - STOREDIST: true - }), - ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STOREDIST'] - ); - }); + testUtils.isVersionGreaterThanHook([6, 2]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + GEOSEARCHSTORE.transformArguments('source', 'destination', 'member', { + radius: 1, + unit: 'm' + }), + ['GEOSEARCHSTORE', 'source', 'destination', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] + ); }); - it('transformReply with empty array (https://github.com/redis/redis/issues/9261)', () => { - assert.throws( - () => (transformReply as any)([]), - TypeError - ); + it('with STOREDIST', () => { + assert.deepEqual( + GEOSEARCHSTORE.transformArguments('destination', 'source', 'member', { + radius: 1, + unit: 'm' + }, { + STOREDIST: true + }), + ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'STOREDIST'] + ); }); - - testUtils.testWithClient('client.geoSearchStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoSearchStore('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoSearchStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoSearchStore('{tag}destination', '{tag}source', 'member', { - radius: 1, - unit: 'm' - }), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + }); + + testUtils.testAll('geoSearchStore', async client => { + assert.equal( + await client.geoSearchStore('{tag}destination', '{tag}source', 'member', { + radius: 1, + unit: 'm' + }), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.ts b/packages/client/lib/commands/GEOSEARCHSTORE.ts index a8cdb82d71b..15635560217 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.ts @@ -1,38 +1,27 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './GEOSEARCH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +export interface GeoSearchStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} -// interface GeoSearchStoreOptions extends GeoSearchOptions { -// STOREDIST?: true; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + source: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchStoreOptions + ) { + const args = pushGeoSearchArguments(['GEOSEARCHSTORE', destination], source, from, by, options); -// export function transformArguments( -// destination: RedisCommandArgument, -// source: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// options?: GeoSearchStoreOptions -// ): RedisCommandArguments { -// const args = pushGeoSearchArguments( -// ['GEOSEARCHSTORE', destination], -// source, -// from, -// by, -// options -// ); + if (options?.STOREDIST) { + args.push('STOREDIST'); + } -// if (options?.STOREDIST) { -// args.push('STOREDIST'); -// } - -// return args; -// } - -// export function transformReply(reply: number): number { -// if (typeof reply !== 'number') { -// throw new TypeError(`https://github.com/redis/redis/issues/9261`); -// } - -// return reply; -// } + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts index c1f5213775a..a01f47d287a 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts @@ -1,42 +1,49 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEOSEARCH_WITH'; +import GEOSEARCH_WITH, { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEOSEARCH WITH', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEOSEARCH_WITH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoSearchWith', async client => { - assert.deepEqual( - await client.geoSearchWith('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('.geoSearchWith', async client => { + const [ , reply ] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoSearchWith('key', 'member', { + radius: 1, + unit: 'm' + }, [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoSearchWith', async cluster => { - assert.deepEqual( - await cluster.geoSearchWith('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts index e706b08b9e8..7dfb65c34cf 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.ts @@ -1,23 +1,71 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions } from './generic-transformers'; -// import { transformArguments as geoSearchTransformArguments } from './GEOSEARCH'; +import { ArrayReply, BlobStringReply, NumberReply, DoubleReply, Command, RedisArgument } from '../RESP/types'; +import GEOSEARCH, { GeoSearchBy, GeoSearchFrom, GeoSearchOptions } from './GEOSEARCH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +export const GEO_REPLY_WITH = { + DISTANCE: 'WITHDIST', + HASH: 'WITHHASH', + COORDINATES: 'WITHCOORD' +} as const; -// export function transformArguments( -// key: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = geoSearchTransformArguments(key, from, by, options); +export type GeoReplyWith = typeof GEO_REPLY_WITH[keyof typeof GEO_REPLY_WITH]; -// args.push(...replyWith); +export interface GeoReplyWithMember { + member: BlobStringReply; + distance?: BlobStringReply; + hash?: NumberReply; + coordinates?: { + longitude: DoubleReply; + latitude: DoubleReply; + }; +} -// args.preserve = replyWith; +export default { + FIRST_KEY_INDEX: GEOSEARCH.FIRST_KEY_INDEX, + IS_READ_ONLY: GEOSEARCH.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + replyWith: Array, + options?: GeoSearchOptions + ) { + const args = GEOSEARCH.transformArguments(key, from, by, options); + args.push(...replyWith); + args.preserve = replyWith; + return args; + }, + transformReply( + reply: ArrayReply<[BlobStringReply, ...Array]>, + replyWith: Array + ) { + const replyWithSet = new Set(replyWith); + let index = 0; + const distanceIndex = replyWithSet.has(GEO_REPLY_WITH.DISTANCE) && ++index, + hashIndex = replyWithSet.has(GEO_REPLY_WITH.HASH) && ++index, + coordinatesIndex = replyWithSet.has(GEO_REPLY_WITH.COORDINATES) && ++index; + + return reply.map(raw => { + const item: GeoReplyWithMember = { + member: raw[0] + }; -// return args; -// } + if (distanceIndex) { + item.distance = raw[distanceIndex]; + } + + if (hashIndex) { + item.hash = raw[hashIndex]; + } + + if (coordinatesIndex) { + const [longitude, latitude] = raw[coordinatesIndex]; + item.coordinates = { + longitude, + latitude + }; + } -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; + return item; + }); + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index e3985f82f87..e359018ff53 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -45,6 +45,23 @@ import DECR from './DECR'; import DECRBY from './DECRBY'; import DEL from './DEL'; import DUMP from './DUMP'; +import GEOADD from './GEOADD'; +import GEODIST from './GEODIST'; +import GEOHASH from './GEOHASH'; +import GEOPOS from './GEOPOS'; +import GEORADIUS_RO_WITH from './GEORADIUS_RO_WITH'; +import GEORADIUS_RO from './GEORADIUS_RO'; +import GEORADIUS_STORE from './GEORADIUS_STORE'; +import GEORADIUS_WITH from './GEORADIUS_WITH'; +import GEORADIUS from './GEORADIUS'; +import GEORADIUSBYMEMBER_RO_WITH from './GEORADIUSBYMEMBER_RO_WITH'; +import GEORADIUSBYMEMBER_RO from './GEORADIUSBYMEMBER_RO'; +import GEORADIUSBYMEMBER_STORE from './GEORADIUSBYMEMBER_STORE'; +import GEORADIUSBYMEMBER_WITH from './GEORADIUSBYMEMBER_WITH'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; +import GEOSEARCH_WITH from './GEOSEARCH_WITH'; +import GEOSEARCH from './GEOSEARCH'; +import GEOSEARCHSTORE from './GEOSEARCHSTORE'; import GET from './GET'; import GETBIT from './GETBIT'; import GETDEL from './GETDEL'; @@ -290,6 +307,40 @@ export default { del: DEL, DUMP, dump: DUMP, + GEOADD, + geoAdd: GEOADD, + GEODIST, + geoDist: GEODIST, + GEOHASH, + geoHash: GEOHASH, + GEOPOS, + geoPos: GEOPOS, + GEORADIUS_RO_WITH, + geoRadiusRoWith: GEORADIUS_RO_WITH, + GEORADIUS_RO, + geoRadiusRo: GEORADIUS_RO, + GEORADIUS_STORE, + geoRadiusStore: GEORADIUS_STORE, + GEORADIUS_WITH, + geoRadiusWith: GEORADIUS_WITH, + GEORADIUS, + geoRadius: GEORADIUS, + GEORADIUSBYMEMBER_RO_WITH, + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH, + GEORADIUSBYMEMBER_RO, + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO, + GEORADIUSBYMEMBER_STORE, + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE, + GEORADIUSBYMEMBER_WITH, + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH, + GEORADIUSBYMEMBER, + geoRadiusByMember: GEORADIUSBYMEMBER, + GEOSEARCH_WITH, + geoSearchWith: GEOSEARCH_WITH, + GEOSEARCH, + geoSearch: GEOSEARCH, + GEOSEARCHSTORE, + geoSearchStore: GEOSEARCHSTORE, GET, get: GET, GETBIT, From 01e6821caac7db17bfc3b76830354d570e657d94 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 8 May 2023 11:05:17 +0300 Subject: [PATCH 097/325] wip --- docs/v4-to-v5.md | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 481bd95c696..cc2c64f15d1 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -39,7 +39,7 @@ To override just a specific option, use the following functions: ## Quit VS Disconnect -The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection. +The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection. Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`. @@ -48,17 +48,31 @@ TODO difference between `close` and `disconnect`... ## Scan Iterators TODO +Yields chunks instead of individual items. Allows multi key operations. +See the [Scan Iterators guide](./scan-iterators.md). -Yields chunks instead of individual items: +## Legacy Mode + +TODO ```javascript -for await (const chunk of client.scanIterator()) { - // `chunk` type is `Array` - // will allow multi keys operations - await client.del(chunk); -} +const client = createClient(), + legacyClient = client.legacy(); + +// use `client` for the new API +await client.set('key', 'value'); + +// use `legacyClient` for the "legacy" callback API +legacyClient.set('key', 'value', (err, reply) => { + // ... +}); ``` +## Isolation Pool + +TODO +The `isolationPool` has been moved to it's on class `ClientPool`. You can create pool from a client using `client.createPool()`. + ## Commands Some command arguments/replies have changed to align more closely to data types returned by Redis: @@ -85,6 +99,10 @@ Some command arguments/replies have changed to align more closely to data types - `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] - `SISMEMBER`: `boolean` -> `number` [^boolean-to-number] - `SMISMEMBER`: `Array` -> `Array` [^boolean-to-number] +- `TS.ADD`: `boolean` -> `number` [^boolean-to-number] +- `GEOSEARCH_WITH`/`GEORADIUS_WITH`: `GeoReplyWith` -> `GEO_REPLY_WITH` [^enum-to-constants] +- `GEORADIUSSTORE` -> `GEORADIUS_STORE` +- `GEORADIUSBYMEMBERSTORE` -> `GEORADIUSBYMEMBER_STORE` [^enum-to-constants]: TODO From ebdad8eed91fc3d441dd540efe2ed9d010f1f061 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 8 May 2023 14:18:53 +0300 Subject: [PATCH 098/325] geo --- packages/client/lib/commands/GEODIST.ts | 2 +- .../lib/commands/generic-transformers.ts | 189 ------------------ 2 files changed, 1 insertion(+), 190 deletions(-) diff --git a/packages/client/lib/commands/GEODIST.ts b/packages/client/lib/commands/GEODIST.ts index dc5bcf1f12c..3e684d67579 100644 --- a/packages/client/lib/commands/GEODIST.ts +++ b/packages/client/lib/commands/GEODIST.ts @@ -1,5 +1,5 @@ import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; -import { GeoUnits } from './generic-transformers'; +import { GeoUnits } from './GEOSEARCH'; export default { FIRST_KEY_INDEX: 1, diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 9a8eef476e4..78bc9838429 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -178,195 +178,6 @@ export function transformLMPopArguments( return args; } -type GeoCountArgument = number | { - value: number; - ANY?: true -}; - -export function pushGeoCountArgument( - args: CommandArguments, - count: GeoCountArgument | undefined -): CommandArguments { - if (typeof count === 'number') { - args.push('COUNT', count.toString()); - } else if (count) { - args.push('COUNT', count.value.toString()); - - if (count.ANY) { - args.push('ANY'); - } - } - - return args; -} - -export type GeoUnits = 'm' | 'km' | 'mi' | 'ft'; - -export interface GeoCoordinates { - longitude: RedisArgument | number; - latitude: RedisArgument | number; -} - -type GeoSearchFromMember = string; - -export type GeoSearchFrom = GeoSearchFromMember | GeoCoordinates; - -interface GeoSearchByRadius { - radius: number; - unit: GeoUnits; -} - -interface GeoSearchByBox { - width: number; - height: number; - unit: GeoUnits; -} - -export type GeoSearchBy = GeoSearchByRadius | GeoSearchByBox; - -export interface GeoSearchOptions { - SORT?: 'ASC' | 'DESC'; - COUNT?: GeoCountArgument; -} - -export function pushGeoSearchArguments( - args: CommandArguments, - key: RedisArgument, - from: GeoSearchFrom, - by: GeoSearchBy, - options?: GeoSearchOptions -): CommandArguments { - args.push(key); - - if (typeof from === 'string') { - args.push('FROMMEMBER', from); - } else { - args.push('FROMLONLAT', from.longitude.toString(), from.latitude.toString()); - } - - if ('radius' in by) { - args.push('BYRADIUS', by.radius.toString()); - } else { - args.push('BYBOX', by.width.toString(), by.height.toString()); - } - - args.push(by.unit); - - if (options?.SORT) { - args.push(options.SORT); - } - - pushGeoCountArgument(args, options?.COUNT); - - return args; -} - -export function pushGeoRadiusArguments( - args: CommandArguments, - key: RedisArgument, - from: GeoSearchFrom, - radius: number, - unit: GeoUnits, - options?: GeoSearchOptions -): CommandArguments { - args.push(key); - - if (typeof from === 'string') { - args.push(from); - } else { - args.push( - from.longitude.toString(), - from.latitude.toString() - ); - } - - args.push( - radius.toString(), - unit - ); - - if (options?.SORT) { - args.push(options.SORT); - } - - pushGeoCountArgument(args, options?.COUNT); - - return args; -} - -export interface GeoRadiusStoreOptions extends GeoSearchOptions { - STOREDIST?: boolean; -} - -export function pushGeoRadiusStoreArguments( - args: CommandArguments, - key: RedisArgument, - from: GeoSearchFrom, - radius: number, - unit: GeoUnits, - destination: RedisArgument, - options?: GeoRadiusStoreOptions -): CommandArguments { - pushGeoRadiusArguments(args, key, from, radius, unit, options); - - if (options?.STOREDIST) { - args.push('STOREDIST', destination); - } else { - args.push('STORE', destination); - } - - return args; -} - -export enum GeoReplyWith { - DISTANCE = 'WITHDIST', - HASH = 'WITHHASH', - COORDINATES = 'WITHCOORD' -} - -export interface GeoReplyWithMember { - member: string; - distance?: number; - hash?: string; - coordinates?: { - longitude: string; - latitude: string; - }; -} - -export function transformGeoMembersWithReply(reply: Array>, replyWith: Array): Array { - const replyWithSet = new Set(replyWith); - - let index = 0; - const distanceIndex = replyWithSet.has(GeoReplyWith.DISTANCE) && ++index, - hashIndex = replyWithSet.has(GeoReplyWith.HASH) && ++index, - coordinatesIndex = replyWithSet.has(GeoReplyWith.COORDINATES) && ++index; - - return reply.map(member => { - const transformedMember: GeoReplyWithMember = { - member: member[0] - }; - - if (distanceIndex) { - transformedMember.distance = member[distanceIndex]; - } - - if (hashIndex) { - transformedMember.hash = member[hashIndex]; - } - - if (coordinatesIndex) { - const [longitude, latitude] = member[coordinatesIndex]; - transformedMember.coordinates = { - longitude, - latitude - }; - } - - return transformedMember; - }); -} - export function transformEXAT(EXAT: number | Date): string { return (typeof EXAT === 'number' ? EXAT : Math.floor(EXAT.getTime() / 1000)).toString(); } From a6c0d1dbb30f4db84c47a1260baa9db0b615f512 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 9 May 2023 12:47:19 +0300 Subject: [PATCH 099/325] legacy mode and isolation pool --- packages/client/lib/client/index.ts | 251 +++++------------- packages/client/lib/client/legacy-mode.ts | 107 ++++++++ packages/client/lib/client/pool.ts | 84 ++++++ packages/client/lib/commands/READONLY.spec.ts | 12 +- packages/client/lib/commands/SCAN.ts | 2 +- packages/client/lib/commands/index.ts | 3 + 6 files changed, 272 insertions(+), 187 deletions(-) create mode 100644 packages/client/lib/client/legacy-mode.ts create mode 100644 packages/client/lib/client/pool.ts diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 493d32de9d5..df736f3f600 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -11,9 +11,10 @@ import { Command, CommandArguments, CommandSignature, Flags, CommanderConfig, Re import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; -import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; import { ReplyWithFlags, CommandReply } from '../RESP/types'; import SCAN, { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; +import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; +import { RedisClientPool } from './pool'; export interface RedisClientOptions< M extends RedisModules = RedisModules, @@ -59,14 +60,6 @@ export interface RedisClientOptions< * Connect in [`READONLY`](https://redis.io/commands/readonly) mode */ readonly?: boolean; - /** - * TODO - */ - legacyMode?: boolean; - /** - * TODO - */ - isolationPoolOptions?: PoolOptions; /** * Send `PING` command at interval (in ms). * Useful with Redis deployments that do not use TCP Keep-Alive. @@ -78,36 +71,36 @@ type WithCommands< RESP extends RespVersions, FLAGS extends Flags > = { - [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, FLAGS>; -}; + [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, FLAGS>; + }; type WithModules< M extends RedisModules, RESP extends RespVersions, FLAGS extends Flags > = { - [P in keyof M]: { - [C in keyof M[P]]: CommandSignature; + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; }; -}; type WithFunctions< F extends RedisFunctions, RESP extends RespVersions, FLAGS extends Flags > = { - [L in keyof F]: { - [C in keyof F[L]]: CommandSignature; + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; }; -}; type WithScripts< S extends RedisScripts, RESP extends RespVersions, FLAGS extends Flags > = { - [P in keyof S]: CommandSignature; -}; + [P in keyof S]: CommandSignature; + }; export type RedisClientType< M extends RedisModules = {}, @@ -116,19 +109,17 @@ export type RedisClientType< RESP extends RespVersions = 2, FLAGS extends Flags = {} > = ( - RedisClient & - WithCommands & - WithModules & - WithFunctions & - WithScripts -); + RedisClient & + WithCommands & + WithModules & + WithFunctions & + WithScripts + ); export interface ClientCommandOptions extends QueueCommandOptions { - isolated?: boolean; + // isolated?: boolean; } -// type ClientLegacyCallback = (err: Error | null, reply?: RedisCommandRawReply) => void; - type ProxyClient = RedisClient<{}, {}, {}, RespVersions, Flags> & { commandOptions?: ClientCommandOptions }; type NamespaceProxyClient = { self: ProxyClient }; @@ -148,7 +139,7 @@ export default class RedisClient< const transformReply = getTransformReply(command, resp); return async function (this: ProxyClient) { const args = command.transformArguments.apply(undefined, arguments as any), - reply = await this._sendCommand(args, this.commandOptions); + reply = await this.sendCommand(args, this.commandOptions); return transformReply ? transformReply(reply, args.preserve) : reply; @@ -159,7 +150,7 @@ export default class RedisClient< const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyClient) { const args = command.transformArguments.apply(undefined, arguments as any), - reply = await this.self._sendCommand(args, this.self.commandOptions); + reply = await this.self.sendCommand(args, this.self.commandOptions); return transformReply ? transformReply(reply, args.preserve) : reply; @@ -171,7 +162,7 @@ export default class RedisClient< transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyClient) { const fnArgs = fn.transformArguments.apply(undefined, arguments as any), - reply = await this.self._sendCommand( + reply = await this.self.sendCommand( prefix.concat(fnArgs), this.self.commandOptions ); @@ -187,12 +178,12 @@ export default class RedisClient< return async function (this: ProxyClient) { const scriptArgs = script.transformArguments.apply(undefined, arguments as any), args = prefix.concat(scriptArgs), - reply = await this._sendCommand(args, this.commandOptions).catch((err: unknown) => { + reply = await this.sendCommand(args, this.commandOptions).catch((err: unknown) => { if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; args[0] = 'EVAL'; args[1] = script.SCRIPT; - return this._sendCommand(args, this.commandOptions); + return this.sendCommand(args, this.commandOptions); }); return transformReply ? transformReply(reply, scriptArgs.preserve) : @@ -230,7 +221,7 @@ export default class RedisClient< F extends RedisFunctions = {}, S extends RedisScripts = {}, RESP extends RespVersions = 2 - >(options?: RedisClientOptions) { + >(this: void, options?: RedisClientOptions) { return RedisClient.factory(options)(options); } @@ -278,8 +269,6 @@ export default class RedisClient< private readonly _options?: RedisClientOptions; private readonly _socket: RedisSocket; private readonly _queue: RedisCommandsQueue; - private _isolationPool?: Pool>; - // readonly #v4: Record = {}; private _selectedDB = 0; get options(): RedisClientOptions | undefined { @@ -298,20 +287,11 @@ export default class RedisClient< return this._queue.isPubSubActive; } - // get v4(): Record { - // if (!this.client.#options?.legacyMode) { - // throw new Error('the client is not in "legacy mode"'); - // } - - // return this.client.#v4; - // } - constructor(options?: RedisClientOptions) { super(); this._options = this._initiateOptions(options); this._queue = this._initiateQueue(); this._socket = this._initiateSocket(); - // this.#legacyMode(); } private _initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { @@ -353,12 +333,12 @@ export default class RedisClient< } if (this._options?.readonly) { - // promises.push( - // this.#queue.addCommand( - // COMMANDS.READONLY.transformArguments(), - // { asap: true } - // ) - // ); + promises.push( + this._queue.addCommand( + COMMANDS.READONLY.transformArguments(), + { asap: true } + ) + ); } if (this._options?.RESP) { @@ -383,24 +363,24 @@ export default class RedisClient< ); } else { if (this._options?.name) { - // promises.push( - // this.#queue.addCommand( - // COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), - // { asap: true } - // ) - // ); + promises.push( + this._queue.addCommand( + COMMANDS.CLIENT_SETNAME.transformArguments(this._options.name), + { asap: true } + ) + ); } if (this._options?.username || this._options?.password) { - // promises.push( - // this.#queue.addCommand( - // COMMANDS.AUTH.transformArguments({ - // username: this.#options.username, - // password: this.#options.password ?? '' - // }), - // { asap: true } - // ) - // ); + promises.push( + this._queue.addCommand( + COMMANDS.AUTH.transformArguments({ + username: this._options.username, + password: this._options.password ?? '' + }), + { asap: true } + ) + ); } } @@ -436,66 +416,6 @@ export default class RedisClient< .on('end', () => this.emit('end')); } - // #legacyMode(): void { - // if (!this.#options?.legacyMode) return; - - // (this as any).#v4.sendCommand = this.#sendCommand.bind(this); - // (this as any).sendCommand = (...args: Array): void => { - // const result = this.#legacySendCommand(...args); - // if (result) { - // result.promise - // .then(reply => result.callback(null, reply)) - // .catch(err => result.callback(err)); - // } - // }; - - // for (const [name, command] of Object.entries(COMMANDS)) { - // this.#defineLegacyCommand(name, command); - // (this as any)[name.toLowerCase()] ??= (this as any)[name]; - // } - - // // hard coded commands - // this.#defineLegacyCommand('SELECT'); - // this.#defineLegacyCommand('select'); - // this.#defineLegacyCommand('SUBSCRIBE'); - // this.#defineLegacyCommand('subscribe'); - // this.#defineLegacyCommand('PSUBSCRIBE'); - // this.#defineLegacyCommand('pSubscribe'); - // this.#defineLegacyCommand('UNSUBSCRIBE'); - // this.#defineLegacyCommand('unsubscribe'); - // this.#defineLegacyCommand('PUNSUBSCRIBE'); - // this.#defineLegacyCommand('pUnsubscribe'); - // this.#defineLegacyCommand('QUIT'); - // this.#defineLegacyCommand('quit'); - // } - - // #legacySendCommand(...args: Array) { - // const callback = typeof args[args.length - 1] === 'function' ? - // args.pop() as ClientLegacyCallback : - // undefined; - - // const promise = this.#sendCommand(transformLegacyCommandArguments(args)); - // if (callback) return { - // promise, - // callback - // }; - // promise.catch(err => this.emit('error', err)); - // } - - // #defineLegacyCommand(name: string, command?: RedisCommand): void { - // this.#v4[name] = (this as any)[name].bind(this); - // (this as any)[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? - // (...args: Array) => { - // const result = this.#legacySendCommand(name, ...args); - // if (result) { - // result.promise - // .then(reply => result.callback(null, command.transformReply!(reply))) - // .catch(err => result.callback(err)); - // } - // } : - // (...args: Array) => (this as any).sendCommand(name, ...args); - // } - private _pingTimer?: NodeJS.Timer; private _setPingTimer(): void { @@ -505,8 +425,7 @@ export default class RedisClient< this._pingTimer = setTimeout(() => { if (!this._socket.isReady) return; - // using _sendCommand to support legacy mode - this._sendCommand(['PING']) + this.sendCommand(['PING']) .then(reply => this.emit('ping-interval', reply)) .catch(err => this.emit('error', err)) .finally(() => this._setPingTimer()); @@ -559,10 +478,21 @@ export default class RedisClient< } /** - * Override the `isolated` command option to `true` + * Get the "legacy" (v3/callback) interface */ - isolated() { - return this._commandOptionsProxy('isolated', true); + legacy(): RedisLegacyClientType { + return new RedisLegacyClient( + this as unknown as RedisClientType + ) as RedisLegacyClientType; + } + + /** + * Create `RedisClientPool` using this client as a prototype + */ + pool() { + return RedisClientPool.fromClient( + this as unknown as RedisClientType + ); } duplicate(overrides?: Partial>) { @@ -572,36 +502,16 @@ export default class RedisClient< }) as RedisClientType; } - async connect(): Promise { - await this._socket.connect(); - this.self._isolationPool = createPool({ - create: async () => { - const duplicate = this.duplicate({ - isolationPoolOptions: undefined - }).on('error', err => this.emit('error', err)); - await duplicate.connect(); - return duplicate; - }, - destroy: client => client.disconnect() - }, this._options?.isolationPoolOptions); + connect() { + return this._socket.connect(); } - sendCommand = this._sendCommand.bind(this); - - // using `_` to avoid conflicts with the legacy mode - _sendCommand( + sendCommand( args: CommandArguments, options?: ClientCommandOptions ): Promise { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); - } else if (options?.isolated) { - return this.executeIsolated(isolatedClient => - isolatedClient.sendCommand(args, { - ...options, - isolated: false - }) - ); } else if (!this._socket.isReady && this._options?.disableOfflineQueue) { return Promise.reject(new ClientOfflineError()); } @@ -612,7 +522,7 @@ export default class RedisClient< } async SELECT(db: number): Promise { - await this._sendCommand(['SELECT', db.toString()]); + await this.sendCommand(['SELECT', db.toString()]); this._selectedDB = db; } @@ -630,7 +540,6 @@ export default class RedisClient< listener: PubSubListener, bufferMode?: T ): Promise { - console.log('SUBSCRIBE', channels, listener, bufferMode, this._options?.RESP); return this._pubSubCommand( this._queue.subscribe( PubSubType.CHANNELS, @@ -658,7 +567,7 @@ export default class RedisClient< ); } - unsubscribe = this.UNSUBSCRIBE; + unsubscribe = this.UNSUBSCRIBE PSUBSCRIBE( patterns: string | Array, @@ -752,17 +661,13 @@ export default class RedisClient< return this._socket.quit(async () => { const quitPromise = this._queue.addCommand(['QUIT']); this._tick(); - const [reply] = await Promise.all([ - quitPromise, - this._destroyIsolationPool() - ]); - return reply; + return quitPromise; }); } quit = this.QUIT; - _tick(force = false): void { + private _tick(force = false): void { if (this._socket.writableNeedDrain || (!force && !this._socket.isReady)) { return; } @@ -777,12 +682,6 @@ export default class RedisClient< } } - executeIsolated(fn: (client: RedisClientType) => T | Promise): Promise { - return this._isolationPool ? - this._isolationPool.use(fn) : - Promise.reject(new ClientClosedError()); - } - private _addMultiCommands( commands: Array, chainId?: symbol, @@ -827,7 +726,6 @@ export default class RedisClient< return results; } - // self.#options?.legacyMode ); } @@ -884,23 +782,16 @@ export default class RedisClient< } while (cursor !== 0); } - async disconnect(): Promise { + disconnect() { this._queue.flushAll(new DisconnectsClientError()); this._socket.disconnect(); - await this._destroyIsolationPool(); - } - - private async _destroyIsolationPool(): Promise { - await this._isolationPool!.drain(); - await this._isolationPool!.clear(); - this.self._isolationPool = undefined; } - ref(): void { + ref() { this._socket.ref(); } - unref(): void { + unref() { this._socket.unref(); } } diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts new file mode 100644 index 00000000000..c189c85342d --- /dev/null +++ b/packages/client/lib/client/legacy-mode.ts @@ -0,0 +1,107 @@ +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, Flags, Command, CommandArguments, ReplyUnion } from '../RESP/types'; +import { RedisClientType } from '.'; +import { getTransformReply } from '../commander'; +import { ErrorReply } from '../errors'; +import COMMANDS from '../commands'; + +type LegacyArgument = string | Buffer | number | Date; + +type LegacyArguments = Array; + +type LegacyCallback = (err: ErrorReply | null, reply?: ReplyUnion) => unknown + +type LegacyCommandArguments = LegacyArguments | [ + ...args: LegacyArguments, + callback: LegacyCallback +]; + +export type CommandSignature = (...args: LegacyCommandArguments) => void; + +type WithCommands = { + [P in keyof typeof COMMANDS]: CommandSignature; +}; + +export type RedisLegacyClientType = RedisLegacyClient & WithCommands; + +export class RedisLegacyClient { + private static _transformArguments(redisArgs: CommandArguments, args: LegacyCommandArguments) { + let callback: LegacyCallback | undefined; + if (typeof args[args.length - 1] === 'function') { + callback = args.pop() as LegacyCallback; + } + + RedisLegacyClient._pushArguments(redisArgs, args as LegacyArguments); + + return callback; + } + + private static _pushArguments(redisArgs: CommandArguments, args: LegacyArguments) { + for (let i = 0; i < args.length; ++i) { + const arg = args[i]; + if (Array.isArray(arg)) { + RedisLegacyClient._pushArguments(redisArgs, arg); + } else { + redisArgs.push( + typeof arg === 'number' || arg instanceof Date ? + arg.toString() : + arg + ); + } + } + } + + private static _getTransformReply(command: Command, resp: RespVersions) { + return command.TRANSFORM_LEGACY_REPLY ? + getTransformReply(command, resp) : + undefined; + } + + private static _createCommand(name: string, command: Command, resp: RespVersions) { + const transformReply = RedisLegacyClient._getTransformReply(command, resp); + return async function (this: RedisLegacyClient, ...args: LegacyCommandArguments) { + const redisArgs = [name], + callback = RedisLegacyClient._transformArguments(redisArgs, args), + promise = this._client.sendCommand(redisArgs); + + if (!callback) { + promise.catch(err => this._client.emit('error', err)); + return; + } + + promise + .then(reply => callback(null, transformReply ? transformReply(reply) : reply)) + .catch(err => callback(err)); + }; + } + + constructor( + private _client: RedisClientType + ) { + const RESP = _client.options?.RESP ?? 2; + for (const [name, command] of Object.entries(COMMANDS)) { + // TODO: as any? + (this as any)[name] = RedisLegacyClient._createCommand( + name, + command, + RESP + ); + } + + // TODO: Multi + } + + sendCommand(...args: LegacyArguments) { + const redisArgs: CommandArguments = [], + callback = RedisLegacyClient._transformArguments(redisArgs, args), + promise = this._client.sendCommand(redisArgs); + + if (!callback) { + promise.catch(err => this._client.emit('error', err)); + return; + } + + promise + .then(reply => callback(null, reply)) + .catch(err => callback(err)); + } +} diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts new file mode 100644 index 00000000000..36c4387a3ed --- /dev/null +++ b/packages/client/lib/client/pool.ts @@ -0,0 +1,84 @@ +import { Pool, Options as PoolOptions, createPool } from 'generic-pool'; +import { RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; +import RedisClient, { RedisClientType, RedisClientOptions } from '.'; +import { EventEmitter } from 'events'; + +type RedisClientPoolOptions< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> = RedisClientOptions & PoolOptions; + +export class RedisClientPool< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +> extends EventEmitter { + _pool: Pool>; + + static fromClient< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >( + client: RedisClientType, + poolOptions?: PoolOptions + ) { + return new RedisClientPool( + () => client.duplicate(), + poolOptions + ); + } + + static fromOptions< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions + >( + options: RedisClientPoolOptions, + poolOptions?: PoolOptions + ) { + return new RedisClientPool( + RedisClient.factory(options), + poolOptions + ); + } + + constructor( + clientFactory: () => RedisClientType, + options?: PoolOptions + ) { + super(); + + this._pool = createPool({ + create: async () => { + const client = clientFactory(); + + // TODO: more events? + client.on('error', (err: Error) => this.emit('error', err)); + + await client.connect(); + + return client; + }, + // TODO: destroy has to return a Promise?! + destroy: async client => client.disconnect() + }, options); + } + + execute(fn: () => T): Promise { + return this._pool.use(fn); + } + + close() { + // TODO + } + + disconnect() { + // TODO + } +} diff --git a/packages/client/lib/commands/READONLY.spec.ts b/packages/client/lib/commands/READONLY.spec.ts index aa4db47f81a..e635d04009e 100644 --- a/packages/client/lib/commands/READONLY.spec.ts +++ b/packages/client/lib/commands/READONLY.spec.ts @@ -2,10 +2,10 @@ import { strict as assert } from 'assert'; import { transformArguments } from './READONLY'; describe('READONLY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['READONLY'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['READONLY'] + ); + }); }); diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index 690f31c435b..da64a7969ef 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -1,4 +1,4 @@ -import { CommandArguments, RedisArgument, BlobStringReply, ArrayReply, Command } from '../RESP/types'; +import { RedisArgument, CommandArguments, BlobStringReply, ArrayReply, Command } from '../RESP/types'; export interface ScanCommonOptions { MATCH?: string; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index ec2c6329159..68f29c37516 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -133,6 +133,7 @@ import PING from './PING'; import PSETEX from './PSETEX'; import PTTL from './PTTL'; import RANDOMKEY from './RANDOMKEY'; +import READONLY from './READONLY'; import RENAME from './RENAME'; import RENAMENX from './RENAMENX'; import RPOP_COUNT from './RPOP_COUNT'; @@ -487,6 +488,8 @@ export default { pTTL: PTTL, RANDOMKEY, randomKey: RANDOMKEY, + READONLY, + readonly: READONLY, RENAME, rename: RENAME, RENAMENX, From d59254e497813d1ceebf92386c1b76a67b86cd65 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 9 May 2023 14:04:26 +0300 Subject: [PATCH 100/325] some commands --- docs/v4-to-v5.md | 6 +- packages/client/lib/commands/BITPOS.spec.ts | 2 +- packages/client/lib/commands/FLUSHALL.spec.ts | 52 ++++----- packages/client/lib/commands/FLUSHALL.ts | 2 + packages/client/lib/commands/FLUSHDB.spec.ts | 54 +++++----- packages/client/lib/commands/FLUSHDB.ts | 2 + packages/client/lib/commands/GEOSEARCH.ts | 4 - packages/client/lib/commands/HEXISTS.spec.ts | 2 +- packages/client/lib/commands/MOVE.spec.ts | 2 +- packages/client/lib/commands/XADD.ts | 59 +++++----- .../lib/commands/XADD_NOMKSTREAM.spec.ts | 16 +-- .../client/lib/commands/XADD_NOMKSTREAM.ts | 19 ++-- packages/client/lib/commands/ZINTER.ts | 42 +------- packages/client/lib/commands/ZUNION.spec.ts | 22 +++- packages/client/lib/commands/ZUNION.ts | 11 +- .../client/lib/commands/ZUNIONSTORE.spec.ts | 2 +- packages/client/lib/commands/ZUNIONSTORE.ts | 11 +- .../lib/commands/ZUNION_WITHSCORES.spec.ts | 101 ++++++++++-------- .../client/lib/commands/ZUNION_WITHSCORES.ts | 25 ++--- .../lib/commands/generic-transformers.ts | 54 ++++++++++ packages/client/lib/commands/index.ts | 34 +++--- 21 files changed, 291 insertions(+), 231 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index d13c4f1115c..d520962d5a7 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -85,7 +85,10 @@ Some command arguments/replies have changed to align more closely to data types - `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). - `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`? - `HSETNX`: `boolean` -> `number` [^boolean-to-number] -- `ZINTER`: instead of `client.ZINTER('11, { WEIGHTS: [1] })` use `client.ZINTER({ key: '1', weight: 1 }])` +- `ZINTER`: instead of `client.ZINTER('key', { WEIGHTS: [1] })` use `client.ZINTER({ key: 'key', weight: 1 }])` +- `ZINTER_WITHSCORES`: instead of `client.ZINTER_WITHSCORES('key', { WEIGHTS: [1] })` use `client.ZINTER_WITHSCORES({ key: 'key', weight: 1 }])` +- `ZUNION`: instead of `client.ZUNION('key', { WEIGHTS: [1] })` use `client.ZUNION({ key: 'key', weight: 1 }])` +- `ZUNION_WITHSCORES`: instead of `client.ZUNION_WITHSCORES('key', { WEIGHTS: [1] })` use `client.ZUNION_WITHSCORES({ key: 'key', weight: 1 }])` - `SETNX`: `boolean` -> `number` [^boolean-to-number] - `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] - `EXPIRE`: `boolean` -> `number` [^boolean-to-number] @@ -104,6 +107,7 @@ Some command arguments/replies have changed to align more closely to data types - `GEOSEARCH_WITH`/`GEORADIUS_WITH`: `GeoReplyWith` -> `GEO_REPLY_WITH` [^enum-to-constants] - `GEORADIUSSTORE` -> `GEORADIUS_STORE` - `GEORADIUSBYMEMBERSTORE` -> `GEORADIUSBYMEMBER_STORE` +- `XACK`: `boolean` -> `number` [^boolean-to-number] [^enum-to-constants]: TODO diff --git a/packages/client/lib/commands/BITPOS.spec.ts b/packages/client/lib/commands/BITPOS.spec.ts index 8891f43a150..34e975ca03b 100644 --- a/packages/client/lib/commands/BITPOS.spec.ts +++ b/packages/client/lib/commands/BITPOS.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITPOS from './BITPOS'; -describe.only('BITPOS', () => { +describe('BITPOS', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( diff --git a/packages/client/lib/commands/FLUSHALL.spec.ts b/packages/client/lib/commands/FLUSHALL.spec.ts index db5bb72e9cb..3cef3798a68 100644 --- a/packages/client/lib/commands/FLUSHALL.spec.ts +++ b/packages/client/lib/commands/FLUSHALL.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisFlushModes, transformArguments } from './FLUSHALL'; +import FLUSHALL, { REDIS_FLUSH_MODES } from './FLUSHALL'; describe('FLUSHALL', () => { - describe('transformArguments', () => { - it('default', () => { - assert.deepEqual( - transformArguments(), - ['FLUSHALL'] - ); - }); + describe('transformArguments', () => { + it('default', () => { + assert.deepEqual( + FLUSHALL.transformArguments(), + ['FLUSHALL'] + ); + }); - it('ASYNC', () => { - assert.deepEqual( - transformArguments(RedisFlushModes.ASYNC), - ['FLUSHALL', 'ASYNC'] - ); - }); + it('ASYNC', () => { + assert.deepEqual( + FLUSHALL.transformArguments(REDIS_FLUSH_MODES.ASYNC), + ['FLUSHALL', 'ASYNC'] + ); + }); - it('SYNC', () => { - assert.deepEqual( - transformArguments(RedisFlushModes.SYNC), - ['FLUSHALL', 'SYNC'] - ); - }); + it('SYNC', () => { + assert.deepEqual( + FLUSHALL.transformArguments(REDIS_FLUSH_MODES.SYNC), + ['FLUSHALL', 'SYNC'] + ); }); + }); - testUtils.testWithClient('client.flushAll', async client => { - assert.equal( - await client.flushAll(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.flushAll', async client => { + assert.equal( + await client.flushAll(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FLUSHALL.ts b/packages/client/lib/commands/FLUSHALL.ts index bc41e24e0d5..6c814b34a4b 100644 --- a/packages/client/lib/commands/FLUSHALL.ts +++ b/packages/client/lib/commands/FLUSHALL.ts @@ -8,6 +8,8 @@ export const REDIS_FLUSH_MODES = { export type RedisFlushModes = typeof REDIS_FLUSH_MODES[keyof typeof REDIS_FLUSH_MODES]; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, transformArguments(mode?: RedisFlushModes) { const args = ['FLUSHALL']; diff --git a/packages/client/lib/commands/FLUSHDB.spec.ts b/packages/client/lib/commands/FLUSHDB.spec.ts index bf460e9e7a8..93b328eda69 100644 --- a/packages/client/lib/commands/FLUSHDB.spec.ts +++ b/packages/client/lib/commands/FLUSHDB.spec.ts @@ -1,36 +1,36 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisFlushModes } from './FLUSHALL'; -import { transformArguments } from './FLUSHDB'; +import FLUSHDB from './FLUSHDB'; +import { REDIS_FLUSH_MODES } from './FLUSHALL'; describe('FLUSHDB', () => { - describe('transformArguments', () => { - it('default', () => { - assert.deepEqual( - transformArguments(), - ['FLUSHDB'] - ); - }); + describe('transformArguments', () => { + it('default', () => { + assert.deepEqual( + FLUSHDB.transformArguments(), + ['FLUSHDB'] + ); + }); - it('ASYNC', () => { - assert.deepEqual( - transformArguments(RedisFlushModes.ASYNC), - ['FLUSHDB', 'ASYNC'] - ); - }); + it('ASYNC', () => { + assert.deepEqual( + FLUSHDB.transformArguments(REDIS_FLUSH_MODES.ASYNC), + ['FLUSHDB', 'ASYNC'] + ); + }); - it('SYNC', () => { - assert.deepEqual( - transformArguments(RedisFlushModes.SYNC), - ['FLUSHDB', 'SYNC'] - ); - }); + it('SYNC', () => { + assert.deepEqual( + FLUSHDB.transformArguments(REDIS_FLUSH_MODES.SYNC), + ['FLUSHDB', 'SYNC'] + ); }); + }); - testUtils.testWithClient('client.flushDb', async client => { - assert.equal( - await client.flushDb(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.flushDb', async client => { + assert.equal( + await client.flushDb(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FLUSHDB.ts b/packages/client/lib/commands/FLUSHDB.ts index 3dade5c0c50..cb7be1156a2 100644 --- a/packages/client/lib/commands/FLUSHDB.ts +++ b/packages/client/lib/commands/FLUSHDB.ts @@ -2,6 +2,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; import { RedisFlushModes } from './FLUSHALL'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, transformArguments(mode?: RedisFlushModes) { const args = ['FLUSHDB']; diff --git a/packages/client/lib/commands/GEOSEARCH.ts b/packages/client/lib/commands/GEOSEARCH.ts index 4e81f361dd9..c4deaa37e6c 100644 --- a/packages/client/lib/commands/GEOSEARCH.ts +++ b/packages/client/lib/commands/GEOSEARCH.ts @@ -43,10 +43,6 @@ export function pushGeoSearchArguments( args.push('BYBOX', by.width.toString(), by.height.toString(), by.unit); } - if (options?.SORT) { - args.push(options.SORT); - } - pushGeoSearchOptions(args, options); return args; diff --git a/packages/client/lib/commands/HEXISTS.spec.ts b/packages/client/lib/commands/HEXISTS.spec.ts index fae7c11f2b0..0e0e82fa21b 100644 --- a/packages/client/lib/commands/HEXISTS.spec.ts +++ b/packages/client/lib/commands/HEXISTS.spec.ts @@ -13,7 +13,7 @@ describe('HEXISTS', () => { testUtils.testAll('hExists', async client => { assert.equal( await client.hExists('key', 'field'), - false + 0 ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts index 63e10c8e107..929fd2dfd43 100644 --- a/packages/client/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -13,7 +13,7 @@ describe('MOVE', () => { testUtils.testAll('move', async client => { assert.equal( await client.move('key', 1), - 1 + 0 ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/XADD.ts b/packages/client/lib/commands/XADD.ts index 9b6fe045a8f..b681069c729 100644 --- a/packages/client/lib/commands/XADD.ts +++ b/packages/client/lib/commands/XADD.ts @@ -1,4 +1,4 @@ -import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, BlobStringReply, Command, CommandArguments } from '../RESP/types'; export interface XAddOptions { TRIM?: { @@ -9,6 +9,37 @@ export interface XAddOptions { }; } +export function pushXAddArguments( + args: CommandArguments, + id: RedisArgument, + message: Record, + options?: XAddOptions +) { + if (options?.TRIM) { + if (options.TRIM.strategy) { + args.push(options.TRIM.strategy); + } + + if (options.TRIM.strategyModifier) { + args.push(options.TRIM.strategyModifier); + } + + args.push(options.TRIM.threshold.toString()); + + if (options.TRIM.limit) { + args.push('LIMIT', options.TRIM.limit.toString()); + } + } + + args.push(id); + + for (const [key, value] of Object.entries(message)) { + args.push(key, value); + } + + return args; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, @@ -18,31 +49,7 @@ export default { message: Record, options?: XAddOptions ) { - const args = ['XADD', key]; - - if (options?.TRIM) { - if (options.TRIM.strategy) { - args.push(options.TRIM.strategy); - } - - if (options.TRIM.strategyModifier) { - args.push(options.TRIM.strategyModifier); - } - - args.push(options.TRIM.threshold.toString()); - - if (options.TRIM.limit) { - args.push('LIMIT', options.TRIM.limit.toString()); - } - } - - args.push(id); - - for (const [key, value] of Object.entries(message)) { - args.push(key, value); - } - - return args; + return pushXAddArguments(['XADD', key], id, message, options); }, transformReply: undefined as unknown as () => BlobStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts index e28bd4e1053..862b51a4aa6 100644 --- a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts @@ -9,7 +9,7 @@ describe('XADD NOMKSTREAM', () => { XADD_NOMKSTREAM.transformArguments('key', '*', { field: 'value' }), - ['XADD', 'key', '*', 'field', 'value', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', '*', 'field', 'value'] ); }); @@ -19,7 +19,7 @@ describe('XADD NOMKSTREAM', () => { '1': 'I', '2': 'II' }), - ['XADD', 'key', '*', '1', 'I', '2', 'II', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', '*', '1', 'I', '2', 'II'] ); }); @@ -32,7 +32,7 @@ describe('XADD NOMKSTREAM', () => { threshold: 1000 } }), - ['XADD', 'key', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', '1000', '*', 'field', 'value'] ); }); @@ -46,7 +46,7 @@ describe('XADD NOMKSTREAM', () => { threshold: 1000 } }), - ['XADD', 'key', 'MAXLEN', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', 'MAXLEN', '1000', '*', 'field', 'value'] ); }); @@ -60,7 +60,7 @@ describe('XADD NOMKSTREAM', () => { threshold: 1000 } }), - ['XADD', 'key', '=', '1000', '*', 'field', 'value', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', '=', '1000', '*', 'field', 'value'] ); }); @@ -74,17 +74,17 @@ describe('XADD NOMKSTREAM', () => { limit: 1 } }), - ['XADD', 'key', '1000', 'LIMIT', '1', '*', 'field', 'value', 'NOMKSTREAM'] + ['XADD', 'key', 'NOMKSTREAM', '1000', 'LIMIT', '1', '*', 'field', 'value'] ); }); }); testUtils.testAll('xAddNoMkStream', async client => { assert.equal( - typeof await client.xAddNoMkStream('key', '*', { + await client.xAddNoMkStream('key', '*', { field: 'value' }), - 'string' + null ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.ts index 4c425f89826..65e7dd566e3 100644 --- a/packages/client/lib/commands/XADD_NOMKSTREAM.ts +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.ts @@ -1,13 +1,16 @@ -import { BlobStringReply, NullReply, Command } from '../RESP/types'; -import XADD from './XADD'; +import { RedisArgument, BlobStringReply, NullReply, Command } from '../RESP/types'; +import { XAddOptions, pushXAddArguments } from './XADD'; export default { - FIRST_KEY_INDEX: XADD.FIRST_KEY_INDEX, - IS_READ_ONLY: XADD.IS_READ_ONLY, - transformArguments(...args: Parameters) { - const redisArgs = XADD.transformArguments(...args); - redisArgs.push('NOMKSTREAM'); - return redisArgs; + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + id: RedisArgument, + message: Record, + options?: XAddOptions + ) { + return pushXAddArguments(['XADD', key, 'NOMKSTREAM'], id, message, options); }, transformReply: undefined as unknown as () => BlobStringReply | NullReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTER.ts b/packages/client/lib/commands/ZINTER.ts index a4c0be6debe..97f01f2040e 100644 --- a/packages/client/lib/commands/ZINTER.ts +++ b/packages/client/lib/commands/ZINTER.ts @@ -1,5 +1,5 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { transformDoubleArgument } from './generic-transformers'; +import { ZKeys, pushZKeysArguments } from './generic-transformers'; export type ZInterKeyAndWeight = { key: RedisArgument; @@ -14,38 +14,10 @@ export interface ZInterOptions { export function pushZInterArguments( args: Array, - keys: ZInterKeys | ZInterKeys, + keys: ZKeys, options?: ZInterOptions ) { - if (Array.isArray(keys)) { - args.push(keys.length.toString()); - - if (keys.length) { - if (isPlainKeys(keys)) { - args = args.concat(keys); - } else { - const start = args.length; - args[start + keys.length] = 'WEIGHTS'; - for (let i = 0; i < keys.length; i++) { - const index = start + i; - args[index] = keys[i].key; - args[index + 1 + keys.length] = transformDoubleArgument(keys[i].weight); - } - } - } - } else { - args.push('1'); - - if (isPlainKey(keys)) { - args.push(keys); - } else { - args.push( - keys.key, - 'WEIGHTS', - transformDoubleArgument(keys.weight) - ); - } - } + pushZKeysArguments(args, keys); if (options?.AGGREGATE) { args.push('AGGREGATE', options.AGGREGATE); @@ -54,14 +26,6 @@ export function pushZInterArguments( return args; } -function isPlainKey(key: RedisArgument | ZInterKeyAndWeight): key is RedisArgument { - return typeof key === 'string' || Buffer.isBuffer(key); -} - -function isPlainKeys(keys: Array | Array): keys is Array { - return isPlainKey(keys[0]); -} - export default { FIRST_KEY_INDEX: 2, IS_READ_ONLY: true, diff --git a/packages/client/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts index 8aca77531ef..54542aaa81d 100644 --- a/packages/client/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -13,22 +13,36 @@ describe('ZUNION', () => { ); }); - it('keys (array)', () => { + it('keys (Array)', () => { assert.deepEqual( ZUNION.transformArguments(['1', '2']), ['ZUNION', '2', '1', '2'] ); }); - it('with WEIGHTS', () => { + it('key & weight', () => { assert.deepEqual( - ZUNION.transformArguments('key', { - WEIGHTS: [1] + ZUNION.transformArguments({ + key: 'key', + weight: 1 }), ['ZUNION', '1', 'key', 'WEIGHTS', '1'] ); }); + it('keys & weights', () => { + assert.deepEqual( + ZUNION.transformArguments([{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ); + }); + it('with AGGREGATE', () => { assert.deepEqual( ZUNION.transformArguments('key', { diff --git a/packages/client/lib/commands/ZUNION.ts b/packages/client/lib/commands/ZUNION.ts index f9eb06fbdfa..09614b9dc01 100644 --- a/packages/client/lib/commands/ZUNION.ts +++ b/packages/client/lib/commands/ZUNION.ts @@ -1,8 +1,7 @@ import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; +import { ZKeys, pushZKeysArguments } from './generic-transformers'; export interface ZUnionOptions { - WEIGHTS?: Array; AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; } @@ -10,14 +9,10 @@ export default { FIRST_KEY_INDEX: 2, IS_READ_ONLY: true, transformArguments( - keys: RedisVariadicArgument, + keys: ZKeys, options?: ZUnionOptions ) { - const args = pushVariadicArgument(['ZUNION'], keys); - - if (options?.WEIGHTS) { - args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); - } + const args = pushZKeysArguments(['ZUNION'], keys); if (options?.AGGREGATE) { args.push('AGGREGATE', options.AGGREGATE); diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index ae561aff651..ca436dbd064 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -49,7 +49,7 @@ describe('ZUNIONSTORE', () => { testUtils.testAll('zUnionStore', async client => { assert.equal( - await client.zUnionStore('destination', 'key'), + await client.zUnionStore('{tag}destination', '{tag}key'), 0 ); }, { diff --git a/packages/client/lib/commands/ZUNIONSTORE.ts b/packages/client/lib/commands/ZUNIONSTORE.ts index ed70c75c3ce..a14d3ba31c9 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.ts @@ -1,8 +1,7 @@ import { RedisArgument, NumberReply, Command, } from '../RESP/types'; -import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; +import { ZKeys, pushZKeysArguments } from './generic-transformers'; export interface ZUnionOptions { - WEIGHTS?: Array; AGGREGATE?: 'SUM' | 'MIN' | 'MAX'; } @@ -11,14 +10,10 @@ export default { IS_READ_ONLY: false, transformArguments( destination: RedisArgument, - keys: RedisVariadicArgument, + keys: ZKeys, options?: ZUnionOptions ) { - const args = pushVariadicArgument(['ZUNIONSTORE', destination], keys); - - if (options?.WEIGHTS) { - args.push('WEIGHTS', ...options.WEIGHTS.map(weight => weight.toString())); - } + const args = pushZKeysArguments(['ZUNIONSTORE', destination], keys); if (options?.AGGREGATE) { args.push('AGGREGATE', options.AGGREGATE); diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index 6076801367c..41442bb646a 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -1,48 +1,65 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZUNION_WITHSCORES'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZUNION_WITHSCORES from './ZUNION_WITHSCORES'; -// describe('ZUNION WITHSCORES', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('ZUNION WITHSCORES', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// describe('transformArguments', () => { -// it('key (string)', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['ZUNION', '1', 'key', 'WITHSCORES'] -// ); -// }); + describe('transformArguments', () => { + it('key (string)', () => { + assert.deepEqual( + ZUNION_WITHSCORES.transformArguments('key'), + ['ZUNION', '1', 'key'] + ); + }); -// it('keys (array)', () => { -// assert.deepEqual( -// transformArguments(['1', '2']), -// ['ZUNION', '2', '1', '2', 'WITHSCORES'] -// ); -// }); + it('keys (Array)', () => { + assert.deepEqual( + ZUNION_WITHSCORES.transformArguments(['1', '2']), + ['ZUNION', '2', '1', '2'] + ); + }); -// it('with WEIGHTS', () => { -// assert.deepEqual( -// transformArguments('key', { -// WEIGHTS: [1] -// }), -// ['ZUNION', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] -// ); -// }); + it('key & weight', () => { + assert.deepEqual( + ZUNION_WITHSCORES.transformArguments({ + key: 'key', + weight: 1 + }), + ['ZUNION', '1', 'key', 'WEIGHTS', '1'] + ); + }); -// it('with AGGREGATE', () => { -// assert.deepEqual( -// transformArguments('key', { -// AGGREGATE: 'SUM' -// }), -// ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] -// ); -// }); -// }); + it('keys & weights', () => { + assert.deepEqual( + ZUNION_WITHSCORES.transformArguments([{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ); + }); -// testUtils.testWithClient('client.zUnionWithScores', async client => { -// assert.deepEqual( -// await client.zUnionWithScores('key'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + it('with AGGREGATE', () => { + assert.deepEqual( + ZUNION_WITHSCORES.transformArguments('key', { + AGGREGATE: 'SUM' + }), + ['ZUNION', '1', 'key', 'AGGREGATE', 'SUM', 'WITHSCORES'] + ); + }); + }); + + testUtils.testAll('zUnionWithScores', async client => { + assert.deepEqual( + await client.zUnionWithScores('key'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.ts index 54a43da7ecf..d0895a3de76 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.ts @@ -1,13 +1,14 @@ -// import { RedisCommandArguments } from '.'; -// import { transformArguments as transformZUnionArguments } from './ZUNION'; +import { Command } from '../RESP/types'; +import ZUNION from './ZUNION'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZUNION'; - -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformZUnionArguments(...args), -// 'WITHSCORES' -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: ZUNION.FIRST_KEY_INDEX, + IS_READ_ONLY: ZUNION.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZUNION.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 78bc9838429..027a1cee345 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -432,3 +432,57 @@ export function transformRangeReply([start, end]: RawRangeReply): RangeReply { end }; } + +export type ZKeyAndWeight = { + key: RedisArgument; + weight: number; +}; + +export type ZVariadicKeys = T | [T, ...Array]; + +export type ZKeys = ZVariadicKeys | ZVariadicKeys; + +export function pushZKeysArguments( + args: CommandArguments, + keys: ZKeys +) { + if (Array.isArray(keys)) { + args.push(keys.length.toString()); + + if (keys.length) { + if (isPlainKeys(keys)) { + args = args.concat(keys); + } else { + const start = args.length; + args[start + keys.length] = 'WEIGHTS'; + for (let i = 0; i < keys.length; i++) { + const index = start + i; + args[index] = keys[i].key; + args[index + 1 + keys.length] = transformDoubleArgument(keys[i].weight); + } + } + } + } else { + args.push('1'); + + if (isPlainKey(keys)) { + args.push(keys); + } else { + args.push( + keys.key, + 'WEIGHTS', + transformDoubleArgument(keys.weight) + ); + } + } + + return args; +} + +function isPlainKey(key: RedisArgument | ZKeyAndWeight): key is RedisArgument { + return typeof key === 'string' || Buffer.isBuffer(key); +} + +function isPlainKeys(keys: Array | Array): keys is Array { + return isPlainKey(keys[0]); +} diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 68f29c37516..a83177138ba 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -68,7 +68,12 @@ import GETDEL from './GETDEL'; import GETEX from './GETEX'; import GETRANGE from './GETRANGE'; import GETSET from './GETSET'; +import EXISTS from './EXISTS'; +import EXPIRE from './EXPIRE'; +import EXPIREAT from './EXPIREAT'; +import EXPIRETIME from './EXPIRETIME'; import FLUSHALL from './FLUSHALL'; +import FLUSHDB from './FLUSHDB'; import HDEL from './HDEL'; import HEXISTS from './HEXISTS'; import HGET from './HGET'; @@ -119,10 +124,6 @@ import OBJECT_FREQ from './OBJECT_FREQ'; import OBJECT_IDLETIME from './OBJECT_IDLETIME'; import OBJECT_REFCOUNT from './OBJECT_REFCOUNT'; import PERSIST from './PERSIST'; -import EXISTS from './EXISTS'; -import EXPIRE from './EXPIRE'; -import EXPIREAT from './EXPIREAT'; -import EXPIRETIME from './EXPIRETIME'; import PEXPIRE from './PEXPIRE'; import PEXPIREAT from './PEXPIREAT'; import PEXPIRETIME from './PEXPIRETIME'; @@ -212,6 +213,7 @@ import ZREMRANGEBYRANK from './ZREMRANGEBYRANK'; import ZREVRANK from './ZREVRANK'; import ZSCAN from './ZSCAN'; import ZSCORE from './ZSCORE'; +import ZUNION_WITHSCORES from './ZUNION_WITHSCORES'; import ZUNION from './ZUNION'; import ZUNIONSTORE from './ZUNIONSTORE'; import { Command } from '../RESP/types'; @@ -311,6 +313,18 @@ export default { del: DEL, DUMP, dump: DUMP, + EXISTS, + exists: EXISTS, + EXPIRE, + expire: EXPIRE, + EXPIREAT, + expireAt: EXPIREAT, + EXPIRETIME, + expireTime: EXPIRETIME, + FLUSHALL, + flushAll: FLUSHALL, + FLUSHDB, + flushDb: FLUSHDB, GEOADD, geoAdd: GEOADD, GEODIST, @@ -357,8 +371,6 @@ export default { getRange: GETRANGE, GETSET, getSet: GETSET, - FLUSHALL, - flushAll: FLUSHALL, HDEL, hDel: HDEL, HEXISTS, @@ -457,14 +469,6 @@ export default { objectRefCount: OBJECT_REFCOUNT, PERSIST, persist: PERSIST, - EXISTS, - exists: EXISTS, - EXPIRE, - expire: EXPIRE, - EXPIREAT, - expireAt: EXPIREAT, - EXPIRETIME, - expireTime: EXPIRETIME, PEXPIRE, pExpire: PEXPIRE, PEXPIREAT, @@ -646,6 +650,8 @@ export default { zScan: ZSCAN, ZSCORE, zScore: ZSCORE, + ZUNION_WITHSCORES, + zUnionWithScores: ZUNION_WITHSCORES, ZUNION, zUnion: ZUNION, ZUNIONSTORE, From b4196faa41a4aad1499ba276b7a066f8b1be4375 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 10 May 2023 12:08:02 +0300 Subject: [PATCH 101/325] wip --- packages/client/lib/commands/ZADD.spec.ts | 19 +--- packages/client/lib/commands/ZADD.ts | 30 +++--- .../client/lib/commands/ZADD_INCR.spec.ts | 93 +++++++++++++++++++ packages/client/lib/commands/ZADD_INCR.ts | 42 +++++++++ .../client/lib/commands/ZDIFF_WITHSCORES.ts | 23 ++--- packages/client/lib/commands/ZINTERSTORE.ts | 5 +- .../client/lib/commands/ZINTER_WITHSCORES.ts | 30 +----- .../commands/ZRANGEBYSCORE_WITHSCORES.spec.ts | 63 +++++++------ .../lib/commands/ZRANGEBYSCORE_WITHSCORES.ts | 30 +++--- .../client/lib/commands/ZUNIONSTORE.spec.ts | 30 +++--- .../lib/commands/ZUNION_WITHSCORES.spec.ts | 8 +- packages/client/lib/commands/index.ts | 6 ++ 12 files changed, 242 insertions(+), 137 deletions(-) create mode 100644 packages/client/lib/commands/ZADD_INCR.spec.ts create mode 100644 packages/client/lib/commands/ZADD_INCR.ts diff --git a/packages/client/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts index 722856caa81..9f684237e11 100644 --- a/packages/client/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -115,19 +115,7 @@ describe('ZADD', () => { ); }); - it('with INCR', () => { - assert.deepEqual( - ZADD.transformArguments('key', { - value: '1', - score: 1 - }, { - INCR: true - }), - ['ZADD', 'key', 'INCR', '1', '1'] - ); - }); - - it('with condition, comparison, CH, INCR', () => { + it('with condition, comparison, CH', () => { assert.deepEqual( ZADD.transformArguments('key', { value: '1', @@ -135,10 +123,9 @@ describe('ZADD', () => { }, { condition: 'XX', comparison: 'LT', - CH: true, - INCR: true + CH: true }), - ['ZADD', 'key', 'XX', 'LT', 'CH', 'INCR', '1', '1'] + ['ZADD', 'key', 'XX', 'LT', 'CH', '1', '1'] ); }); }); diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index 49a839fb6f3..ff729f4f9c5 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, NumberReply, DoubleReply, Command, CommandArguments } from '../RESP/types'; import { ZMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export interface ZAddOptions { @@ -21,7 +21,6 @@ export interface ZAddOptions { */ GT?: boolean; CH?: boolean; - INCR?: boolean; } export default { @@ -53,26 +52,29 @@ export default { args.push('CH'); } - if (options?.INCR) { - args.push('INCR'); - } - - if (Array.isArray(members)) { - for (const member of members) { - pushMember(args, member); - } - } else { - pushMember(args, members); - } + pushMembers(args, members); return args; }, transformReply: { 2: transformDoubleReply, - 3: undefined as unknown as () => NumberReply | DoubleReply + 3: undefined as unknown as () => NumberReply } } as const satisfies Command; +export function pushMembers( + args: CommandArguments, + members: ZMember | Array +) { + if (Array.isArray(members)) { + for (const member of members) { + pushMember(args, member); + } + } else { + pushMember(args, members); + } +} + function pushMember(args: Array, member: ZMember) { args.push( transformDoubleArgument(member.score), diff --git a/packages/client/lib/commands/ZADD_INCR.spec.ts b/packages/client/lib/commands/ZADD_INCR.spec.ts new file mode 100644 index 00000000000..b2fab832ee6 --- /dev/null +++ b/packages/client/lib/commands/ZADD_INCR.spec.ts @@ -0,0 +1,93 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZADD_INCR from './ZADD_INCR'; + +describe('ZADD INCR', () => { + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }), + ['ZADD', 'key', 'INCR', '1', '1'] + ); + }); + + it('multiple members', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', [{ + value: '1', + score: 1 + }, { + value: '2', + score: 2 + }]), + ['ZADD', 'key', 'INCR', '1', '1', '2', '2'] + ); + }); + + it('with condition', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'NX' + }), + ['ZADD', 'key', 'NX', 'INCR', '1', '1'] + ); + }); + + it('with comparison', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + comparison: 'LT' + }), + ['ZADD', 'key', 'LT', 'INCR', '1', '1'] + ); + }); + + it('with CH', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + CH: true + }), + ['ZADD', 'key', 'CH', 'INCR', '1', '1'] + ); + }); + + it('with condition, comparison, CH', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'XX', + comparison: 'LT', + CH: true + }), + ['ZADD', 'key', 'XX', 'LT', 'CH', 'INCR', '1', '1'] + ); + }); + }); + + testUtils.testAll('zAddIncr', async client => { + assert.equal( + await client.zAddIncr('key', { + value: '1', + score: 1 + }), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZADD_INCR.ts b/packages/client/lib/commands/ZADD_INCR.ts new file mode 100644 index 00000000000..a278b2ee89a --- /dev/null +++ b/packages/client/lib/commands/ZADD_INCR.ts @@ -0,0 +1,42 @@ +import { RedisArgument, DoubleReply, NullReply, Command } from '../RESP/types'; +import { pushMembers } from './ZADD'; +import { ZMember, transformDoubleArgument, transformNullableDoubleReply } from './generic-transformers'; + +export interface ZAddOptions { + condition?: 'NX' | 'XX'; + comparison?: 'LT' | 'GT'; + CH?: boolean; +} + +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + members: ZMember | Array, + options?: ZAddOptions + ) { + const args = ['ZADD', key]; + + if (options?.condition) { + args.push(options.condition); + } + + if (options?.comparison) { + args.push(options.comparison); + } + + if (options?.CH) { + args.push('CH'); + } + + args.push('INCR'); + + pushMembers(args, members); + + return args; + }, + transformReply: { + 2: transformNullableDoubleReply, + 3: undefined as unknown as () => DoubleReply | NullReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts index 0fa1a6d271a..f971e828574 100644 --- a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts @@ -1,19 +1,14 @@ -import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types'; +import { Command } from '../RESP/types'; import ZDIFF from './ZDIFF'; -import { transformSortedSetWithScoresReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export default { - FIRST_KEY_INDEX: 2, - IS_READ_ONLY: true, - transformArguments(keys: Parameters[0]) { - const args = ZDIFF.transformArguments(keys); - args.push('WITHSCORES'); - return args; + FIRST_KEY_INDEX: ZDIFF.FIRST_KEY_INDEX, + IS_READ_ONLY: ZDIFF.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZDIFF.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; }, - transformReply: { - 2: transformSortedSetWithScoresReply, - 3: (reply: ArrayReply<[BlobStringReply, NumberReply]>) => { - return reply.map(([value, score]) => ({ value, score })); - } - } + transformReply: transformSortedSetReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTERSTORE.ts b/packages/client/lib/commands/ZINTERSTORE.ts index 9188b0d90f1..941ddd68e57 100644 --- a/packages/client/lib/commands/ZINTERSTORE.ts +++ b/packages/client/lib/commands/ZINTERSTORE.ts @@ -1,12 +1,13 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushZInterArguments, ZInterKeyAndWeight, ZInterKeys, ZInterOptions } from './ZINTER'; +import { pushZInterArguments, ZInterOptions } from './ZINTER'; +import { ZKeys } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, transformArguments( destination: RedisArgument, - keys: ZInterKeys | ZInterKeys, + keys: ZKeys, options?: ZInterOptions ) { return pushZInterArguments(['ZINTERSTORE', destination], keys, options); diff --git a/packages/client/lib/commands/ZINTER_WITHSCORES.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.ts index 07616251452..b287649fbc0 100644 --- a/packages/client/lib/commands/ZINTER_WITHSCORES.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.ts @@ -1,22 +1,6 @@ -// import { RedisCommandArguments } from '.'; -// import { transformArguments as transformZInterArguments } from './ZINTER'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZINTER'; - -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformZInterArguments(...args), -// 'WITHSCORES' -// ]; -// } - - - -// // transformSortedSetWithScoresReply - -import { ArrayReply, BlobStringReply, Command, DoubleReply } from '../RESP/types'; +import { Command } from '../RESP/types'; import ZINTER from './ZINTER'; -import { transformSortedSetWithScoresReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export default { FIRST_KEY_INDEX: ZINTER.FIRST_KEY_INDEX, @@ -26,13 +10,5 @@ export default { redisArgs.push('WITHSCORES'); return redisArgs; }, - transformReply: { - 2: transformSortedSetWithScoresReply, - 3: (reply: ArrayReply<[BlobStringReply, DoubleReply]>) => { - return reply.map(([member, score]) => ({ - member, - score - })); - } - } + transformReply: transformSortedSetReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts index 2a90a6af3f7..2cca62bae26 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts @@ -1,33 +1,36 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZRANGEBYSCORE_WITHSCORES'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; -// describe('ZRANGEBYSCORE WITHSCORES', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1), -// ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] -// ); -// }); +describe('ZRANGEBYSCORE WITHSCORES', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGEBYSCORE_WITHSCORES.transformArguments('src', 0, 1), + ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] -// ); -// }); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGEBYSCORE_WITHSCORES.transformArguments('src', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] + ); + }); + }); -// testUtils.testWithClient('client.zRangeByScoreWithScores', async client => { -// assert.deepEqual( -// await client.zRangeByScoreWithScores('src', 0, 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRangeByScoreWithScores', async client => { + assert.deepEqual( + await client.zRangeByScoreWithScores('src', 0, 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts index 1cd2df10f0a..bfbe09c6e26 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts @@ -1,18 +1,14 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { ZRangeByScoreOptions, transformArguments as transformZRangeByScoreArguments } from './ZRANGEBYSCORE'; +import { Command } from '../RESP/types'; +import ZRANGEBYSCORE from './ZRANGEBYSCORE'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGEBYSCORE'; - -// export function transformArguments( -// key: RedisCommandArgument, -// min: string | number, -// max: string | number, -// options?: ZRangeByScoreOptions -// ): RedisCommandArguments { -// return [ -// ...transformZRangeByScoreArguments(key, min, max, options), -// 'WITHSCORES' -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: ZRANGEBYSCORE.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANGEBYSCORE.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZRANGEBYSCORE.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index ca436dbd064..9b6454f232b 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -6,43 +6,47 @@ describe('ZUNIONSTORE', () => { describe('transformArguments', () => { it('key (string)', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key'), + ZUNIONSTORE.transformArguments('destination', 'source'), ['ZUNIONSTORE', 'destination', '1', 'key'] ); }); - it('keys (array)', () => { + it('keys (Array)', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', ['1', '2']), ['ZUNIONSTORE', 'destination', '2', '1', '2'] ); }); - it('with WEIGHTS', () => { + it('key & weight', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key', { - WEIGHTS: [1] + ZUNIONSTORE.transformArguments('destination', { + key: 'key', + weight: 1 }), ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] ); }); - it('with AGGREGATE', () => { + it('keys & weights', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key', { - AGGREGATE: 'SUM' - }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] + ZUNIONSTORE.transformArguments('destination', [{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZUNIONSTORE', 'destination', '2', 'a', 'b', 'WEIGHTS', '1', '2'] ); }); - it('with WEIGHTS, AGGREGATE', () => { + it('with AGGREGATE', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', 'key', { - WEIGHTS: [1], AGGREGATE: 'SUM' }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] + ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] ); }); }); diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index 41442bb646a..75283c0bc3a 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -9,14 +9,14 @@ describe('ZUNION WITHSCORES', () => { it('key (string)', () => { assert.deepEqual( ZUNION_WITHSCORES.transformArguments('key'), - ['ZUNION', '1', 'key'] + ['ZUNION', '1', 'key', 'WITHSCORES'] ); }); it('keys (Array)', () => { assert.deepEqual( ZUNION_WITHSCORES.transformArguments(['1', '2']), - ['ZUNION', '2', '1', '2'] + ['ZUNION', '2', '1', '2', 'WITHSCORES'] ); }); @@ -26,7 +26,7 @@ describe('ZUNION WITHSCORES', () => { key: 'key', weight: 1 }), - ['ZUNION', '1', 'key', 'WEIGHTS', '1'] + ['ZUNION', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] ); }); @@ -39,7 +39,7 @@ describe('ZUNION WITHSCORES', () => { key: 'b', weight: 2 }]), - ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2', 'WITHSCORES'] ); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index a83177138ba..397ae7ff227 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -186,6 +186,7 @@ import XDEL from './XDEL'; import XSETID from './XSETID'; import XTRIM from './XTRIM'; import XLEN from './XLEN'; +import ZADD_INCR from './ZADD_INCR'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; import ZCOUNT from './ZCOUNT'; @@ -204,6 +205,7 @@ import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; import ZRANDMEMBER from './ZRANDMEMBER'; import ZRANGE from './ZRANGE'; import ZRANGEBYLEX from './ZRANGEBYLEX'; +import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; import ZRANK from './ZRANK'; @@ -596,6 +598,8 @@ export default { xTrim: XTRIM, XLEN, xLen: XLEN, + ZADD_INCR, + zAddIncr: ZADD_INCR, ZADD, zAdd: ZADD, ZCARD, @@ -632,6 +636,8 @@ export default { zRange: ZRANGE, ZRANGEBYLEX, zRangeByLex: ZRANGEBYLEX, + ZRANGEBYSCORE_WITHSCORES, + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, ZRANK, From 13f1fa9e58d0563a1085dacc6e9709741fdd7e8c Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 10 May 2023 14:55:03 +0300 Subject: [PATCH 102/325] WIP --- docs/v4-to-v5.md | 1 + packages/client/lib/commands/CONFIG_SET.ts | 2 +- packages/client/lib/commands/HSET.ts | 2 +- .../client/lib/commands/SCRIPT_DEBUG.spec.ts | 26 ++++++------ packages/client/lib/commands/SCRIPT_DEBUG.ts | 2 +- .../client/lib/commands/SCRIPT_EXISTS.spec.ts | 40 +++++++++---------- .../client/lib/commands/SCRIPT_FLUSH.spec.ts | 40 +++++++++---------- packages/client/lib/commands/SCRIPT_FLUSH.ts | 2 +- .../client/lib/commands/SCRIPT_KILL.spec.ts | 14 +++---- packages/client/lib/commands/SCRIPT_KILL.ts | 2 +- .../client/lib/commands/SCRIPT_LOAD.spec.ts | 32 +++++++-------- packages/client/lib/commands/XSETID.spec.ts | 10 +++-- packages/client/lib/commands/ZINTER.ts | 2 +- .../client/lib/commands/ZINTERSTORE.spec.ts | 12 +++--- .../client/lib/commands/ZUNIONSTORE.spec.ts | 10 ++--- .../lib/commands/generic-transformers.ts | 2 +- packages/client/lib/commands/index.ts | 15 +++++++ 17 files changed, 117 insertions(+), 97 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index d520962d5a7..49a86086fd6 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -108,6 +108,7 @@ Some command arguments/replies have changed to align more closely to data types - `GEORADIUSSTORE` -> `GEORADIUS_STORE` - `GEORADIUSBYMEMBERSTORE` -> `GEORADIUSBYMEMBER_STORE` - `XACK`: `boolean` -> `number` [^boolean-to-number] +- `XADD`: the `INCR` option has been removed, use `XADD_INCR` instead [^enum-to-constants]: TODO diff --git a/packages/client/lib/commands/CONFIG_SET.ts b/packages/client/lib/commands/CONFIG_SET.ts index 426a314fc17..58f16e96933 100644 --- a/packages/client/lib/commands/CONFIG_SET.ts +++ b/packages/client/lib/commands/CONFIG_SET.ts @@ -10,7 +10,7 @@ export default { ) { const args: Array = ['CONFIG', 'SET']; - if (typeof parameterOrConfig === 'string' || Buffer.isBuffer(parameterOrConfig)) { + if (typeof parameterOrConfig === 'string' || parameterOrConfig instanceof Buffer) { args.push(parameterOrConfig, value!); } else { for (const [key, value] of Object.entries(parameterOrConfig)) { diff --git a/packages/client/lib/commands/HSET.ts b/packages/client/lib/commands/HSET.ts index 7cb98c827bd..e14aa9d06f6 100644 --- a/packages/client/lib/commands/HSET.ts +++ b/packages/client/lib/commands/HSET.ts @@ -21,7 +21,7 @@ export default { transformArguments(...[key, value, fieldValue]: SingleFieldArguments | MultipleFieldsArguments) { const args: Array = ['HSET', key]; - if (typeof value === 'string' || typeof value === 'number' || Buffer.isBuffer(value)) { + if (typeof value === 'string' || typeof value === 'number' || value instanceof Buffer) { args.push( convertValue(value), convertValue(fieldValue!) diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts index 192f90f75a5..c90f0573f36 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SCRIPT_DEBUG'; +import SCRIPT_DEBUG from './SCRIPT_DEBUG'; describe('SCRIPT DEBUG', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('NO'), - ['SCRIPT', 'DEBUG', 'NO'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SCRIPT_DEBUG.transformArguments('NO'), + ['SCRIPT', 'DEBUG', 'NO'] + ); + }); - testUtils.testWithClient('client.scriptDebug', async client => { - assert.equal( - await client.scriptDebug('NO'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.scriptDebug', async client => { + assert.equal( + await client.scriptDebug('NO'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.ts b/packages/client/lib/commands/SCRIPT_DEBUG.ts index b4bc1cfa8e0..3c49ff709d5 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.ts @@ -6,5 +6,5 @@ export default { transformArguments(mode: 'YES' | 'SYNC' | 'NO') { return ['SCRIPT', 'DEBUG', mode]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts index e0fbbcc5537..0a8a7be991d 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SCRIPT_EXISTS'; +import SCRIPT_EXISTS from './SCRIPT_EXISTS'; describe('SCRIPT EXISTS', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('sha1'), - ['SCRIPT', 'EXISTS', 'sha1'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + SCRIPT_EXISTS.transformArguments('sha1'), + ['SCRIPT', 'EXISTS', 'sha1'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['SCRIPT', 'EXISTS', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + SCRIPT_EXISTS.transformArguments(['1', '2']), + ['SCRIPT', 'EXISTS', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.scriptExists', async client => { - assert.deepEqual( - await client.scriptExists('sha1'), - [false] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.scriptExists', async client => { + assert.deepEqual( + await client.scriptExists('sha1'), + [0] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts index ae156e937d1..1407c8c3666 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SCRIPT_FLUSH'; +import SCRIPT_FLUSH from './SCRIPT_FLUSH'; describe('SCRIPT FLUSH', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['SCRIPT', 'FLUSH'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SCRIPT_FLUSH.transformArguments(), + ['SCRIPT', 'FLUSH'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments('SYNC'), - ['SCRIPT', 'FLUSH', 'SYNC'] - ); - }); + it('with mode', () => { + assert.deepEqual( + SCRIPT_FLUSH.transformArguments('SYNC'), + ['SCRIPT', 'FLUSH', 'SYNC'] + ); }); + }); - testUtils.testWithClient('client.scriptFlush', async client => { - assert.equal( - await client.scriptFlush(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.scriptFlush', async client => { + assert.equal( + await client.scriptFlush(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.ts b/packages/client/lib/commands/SCRIPT_FLUSH.ts index 6a224cdaa85..f5426395628 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.ts @@ -12,5 +12,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_KILL.spec.ts b/packages/client/lib/commands/SCRIPT_KILL.spec.ts index e57265aa61a..d9313de18b1 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.spec.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './SCRIPT_KILL'; +import SCRIPT_KILL from './SCRIPT_KILL'; describe('SCRIPT KILL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['SCRIPT', 'KILL'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SCRIPT_KILL.transformArguments(), + ['SCRIPT', 'KILL'] + ); + }); }); diff --git a/packages/client/lib/commands/SCRIPT_KILL.ts b/packages/client/lib/commands/SCRIPT_KILL.ts index 973bf51660d..ac025b788bb 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.ts @@ -6,5 +6,5 @@ export default { transformArguments() { return ['SCRIPT', 'KILL']; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_LOAD.spec.ts b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts index 062f3c201e1..5aaba040855 100644 --- a/packages/client/lib/commands/SCRIPT_LOAD.spec.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts @@ -1,23 +1,23 @@ import { strict as assert } from 'assert'; -import { scriptSha1 } from '../lua-script'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SCRIPT_LOAD'; +import SCRIPT_LOAD from './SCRIPT_LOAD'; +import { scriptSha1 } from '../lua-script'; describe('SCRIPT LOAD', () => { - const SCRIPT = 'return 1;', - SCRIPT_SHA1 = scriptSha1(SCRIPT); + const SCRIPT = 'return 1;', + SCRIPT_SHA1 = scriptSha1(SCRIPT); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(SCRIPT), - ['SCRIPT', 'LOAD', SCRIPT] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SCRIPT_LOAD.transformArguments(SCRIPT), + ['SCRIPT', 'LOAD', SCRIPT] + ); + }); - testUtils.testWithClient('client.scriptLoad', async client => { - assert.equal( - await client.scriptLoad(SCRIPT), - SCRIPT_SHA1 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.scriptLoad', async client => { + assert.equal( + await client.scriptLoad(SCRIPT), + SCRIPT_SHA1 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/XSETID.spec.ts b/packages/client/lib/commands/XSETID.spec.ts index 8e951335a88..993f4638a80 100644 --- a/packages/client/lib/commands/XSETID.spec.ts +++ b/packages/client/lib/commands/XSETID.spec.ts @@ -31,9 +31,13 @@ describe('XSETID', () => { }); testUtils.testAll('xSetId', async client => { - assert.deepEqual( - await client.xSetId('key', '0-0'), - [] + const id = await client.xAdd('key', '*', { + field: 'value' + }); + + assert.equal( + await client.xSetId('key', id), + 'OK' ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/ZINTER.ts b/packages/client/lib/commands/ZINTER.ts index 97f01f2040e..392c3a96c65 100644 --- a/packages/client/lib/commands/ZINTER.ts +++ b/packages/client/lib/commands/ZINTER.ts @@ -17,7 +17,7 @@ export function pushZInterArguments( keys: ZKeys, options?: ZInterOptions ) { - pushZKeysArguments(args, keys); + args = pushZKeysArguments(args, keys); if (options?.AGGREGATE) { args.push('AGGREGATE', options.AGGREGATE); diff --git a/packages/client/lib/commands/ZINTERSTORE.spec.ts b/packages/client/lib/commands/ZINTERSTORE.spec.ts index 6c7a534e3db..01591147c44 100644 --- a/packages/client/lib/commands/ZINTERSTORE.spec.ts +++ b/packages/client/lib/commands/ZINTERSTORE.spec.ts @@ -6,8 +6,8 @@ describe('ZINTERSTORE', () => { describe('transformArguments', () => { it('key (string)', () => { assert.deepEqual( - ZINTERSTORE.transformArguments('destination', 'key'), - ['ZINTERSTORE', 'destination', '1', 'key'] + ZINTERSTORE.transformArguments('destination', 'source'), + ['ZINTERSTORE', 'destination', '1', 'source'] ); }); @@ -21,10 +21,10 @@ describe('ZINTERSTORE', () => { it('key & weight', () => { assert.deepEqual( ZINTERSTORE.transformArguments('destination', { - key: 'key', + key: 'source', weight: 1 }), - ['ZINTERSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] + ['ZINTERSTORE', 'destination', '1', 'source', 'WEIGHTS', '1'] ); }); @@ -43,10 +43,10 @@ describe('ZINTERSTORE', () => { it('with AGGREGATE', () => { assert.deepEqual( - ZINTERSTORE.transformArguments('destination', 'key', { + ZINTERSTORE.transformArguments('destination', 'source', { AGGREGATE: 'SUM' }), - ['ZINTERSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] + ['ZINTERSTORE', 'destination', '1', 'source', 'AGGREGATE', 'SUM'] ); }); }); diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index 9b6454f232b..979cd384e1b 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -7,7 +7,7 @@ describe('ZUNIONSTORE', () => { it('key (string)', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', 'source'), - ['ZUNIONSTORE', 'destination', '1', 'key'] + ['ZUNIONSTORE', 'destination', '1', 'source'] ); }); @@ -21,10 +21,10 @@ describe('ZUNIONSTORE', () => { it('key & weight', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', { - key: 'key', + key: 'source', weight: 1 }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] + ['ZUNIONSTORE', 'destination', '1', 'source', 'WEIGHTS', '1'] ); }); @@ -43,10 +43,10 @@ describe('ZUNIONSTORE', () => { it('with AGGREGATE', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key', { + ZUNIONSTORE.transformArguments('destination', 'source', { AGGREGATE: 'SUM' }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] + ['ZUNIONSTORE', 'destination', '1', 'source', 'AGGREGATE', 'SUM'] ); }); }); diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 027a1cee345..ee72bb00041 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -480,7 +480,7 @@ export function pushZKeysArguments( } function isPlainKey(key: RedisArgument | ZKeyAndWeight): key is RedisArgument { - return typeof key === 'string' || Buffer.isBuffer(key); + return typeof key === 'string' || key instanceof Buffer; } function isPlainKeys(keys: Array | Array): keys is Array { diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 397ae7ff227..c96883ae490 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -145,6 +145,11 @@ import RPUSHX from './RPUSHX'; import SADD from './SADD'; import SCAN from './SCAN'; import SCARD from './SCARD'; +import SCRIPT_DEBUG from './SCRIPT_DEBUG'; +import SCRIPT_EXISTS from './SCRIPT_EXISTS'; +import SCRIPT_FLUSH from './SCRIPT_FLUSH'; +import SCRIPT_KILL from './SCRIPT_KILL'; +import SCRIPT_LOAD from './SCRIPT_LOAD'; import SDIFF from './SDIFF'; import SDIFFSTORE from './SDIFFSTORE'; import SET from './SET'; @@ -516,6 +521,16 @@ export default { scan: SCAN, SCARD, sCard: SCARD, + SCRIPT_DEBUG, + scriptDebug: SCRIPT_DEBUG, + SCRIPT_EXISTS, + scriptExists: SCRIPT_EXISTS, + SCRIPT_FLUSH, + scriptFlush: SCRIPT_FLUSH, + SCRIPT_KILL, + scriptKill: SCRIPT_KILL, + SCRIPT_LOAD, + scriptLoad: SCRIPT_LOAD, SDIFF, sDiff: SDIFF, SDIFFSTORE, From 442a554fce091bb6040fed05fe63b25d4ccc1680 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 10 May 2023 16:07:29 +0300 Subject: [PATCH 103/325] WIP --- packages/client/lib/commands/ECHO.spec.ts | 26 ++-- packages/client/lib/commands/EVAL.spec.ts | 42 +++--- packages/client/lib/commands/EVAL.ts | 34 ++++- packages/client/lib/commands/EVALSHA.spec.ts | 20 +-- packages/client/lib/commands/EVALSHA.ts | 14 +- .../client/lib/commands/EVALSHA_RO.spec.ts | 22 ++-- packages/client/lib/commands/EVALSHA_RO.ts | 16 +-- packages/client/lib/commands/EVAL_RO.spec.ts | 44 +++---- packages/client/lib/commands/EVAL_RO.ts | 16 +-- packages/client/lib/commands/FCALL.ts | 12 ++ packages/client/lib/commands/HELLO.spec.ts | 123 +++++++++--------- packages/client/lib/commands/HELLO.ts | 33 +++-- packages/client/lib/commands/LASTSAVE.spec.ts | 20 +-- packages/client/lib/commands/LASTSAVE.ts | 15 ++- packages/client/lib/commands/LCS_LEN.spec.ts | 2 +- packages/client/lib/commands/MOVE.spec.ts | 7 +- packages/client/lib/commands/PUBLISH.spec.ts | 26 ++-- packages/client/lib/commands/index.ts | 21 +++ 18 files changed, 272 insertions(+), 221 deletions(-) diff --git a/packages/client/lib/commands/ECHO.spec.ts b/packages/client/lib/commands/ECHO.spec.ts index 27f6b2a17d3..04ce759b1f8 100644 --- a/packages/client/lib/commands/ECHO.spec.ts +++ b/packages/client/lib/commands/ECHO.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ECHO'; +import ECHO from './ECHO'; describe('ECHO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('message'), - ['ECHO', 'message'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ECHO.transformArguments('message'), + ['ECHO', 'message'] + ); + }); - testUtils.testWithClient('client.echo', async client => { - assert.equal( - await client.echo('message'), - 'message' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.echo', async client => { + assert.equal( + await client.echo('message'), + 'message' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/EVAL.spec.ts b/packages/client/lib/commands/EVAL.spec.ts index 7aa029362fd..e131cd79abf 100644 --- a/packages/client/lib/commands/EVAL.spec.ts +++ b/packages/client/lib/commands/EVAL.spec.ts @@ -1,29 +1,25 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EVAL'; +import EVAL from './EVAL'; describe('EVAL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('return KEYS[1] + ARGV[1]', { - keys: ['key'], - arguments: ['argument'] - }), - ['EVAL', 'return KEYS[1] + ARGV[1]', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EVAL.transformArguments('return KEYS[1] + ARGV[1]', { + keys: ['key'], + arguments: ['argument'] + }), + ['EVAL', 'return KEYS[1] + ARGV[1]', '1', 'key', 'argument'] + ); + }); - testUtils.testWithClient('client.eval', async client => { - assert.equal( - await client.eval('return 1'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.eval', async cluster => { - assert.equal( - await cluster.eval('return 1'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('eval', async client => { + assert.equal( + await client.eval('return 1'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/EVAL.ts b/packages/client/lib/commands/EVAL.ts index a82f8bf0aad..21684e7a313 100644 --- a/packages/client/lib/commands/EVAL.ts +++ b/packages/client/lib/commands/EVAL.ts @@ -1,7 +1,33 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; +import { RedisArgument, ReplyUnion, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = evalFirstKeyIndex; +export interface EvalOptions { + keys?: Array; + arguments?: Array; +} + +export function transformEvalArguments( + command: RedisArgument, + script: RedisArgument, + options?: EvalOptions +) { + const args = [command, script]; + + if (options?.keys) { + args.push(options.keys.length.toString(), ...options.keys); + } else { + args.push('0'); + } -export function transformArguments(script: string, options?: EvalOptions): Array { - return pushEvalArguments(['EVAL', script], options); + if (options?.arguments) { + args.push(...options.arguments); + } + + return args; } + +export default { + FIRST_KEY_INDEX: (_, options?: EvalOptions) => options?.keys?.[0], + IS_READ_ONLY: false, + transformArguments: transformEvalArguments.bind(undefined, 'EVAL'), + transformReply: undefined as unknown as () => ReplyUnion +} as const satisfies Command; diff --git a/packages/client/lib/commands/EVALSHA.spec.ts b/packages/client/lib/commands/EVALSHA.spec.ts index 08b330ac4f5..ce08ec89c87 100644 --- a/packages/client/lib/commands/EVALSHA.spec.ts +++ b/packages/client/lib/commands/EVALSHA.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './EVALSHA'; +import EVALSHA from './EVALSHA'; describe('EVALSHA', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('sha1', { - keys: ['key'], - arguments: ['argument'] - }), - ['EVALSHA', 'sha1', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EVALSHA.transformArguments('sha1', { + keys: ['key'], + arguments: ['argument'] + }), + ['EVALSHA', 'sha1', '1', 'key', 'argument'] + ); + }); }); diff --git a/packages/client/lib/commands/EVALSHA.ts b/packages/client/lib/commands/EVALSHA.ts index 24f7060a052..dc4127f90da 100644 --- a/packages/client/lib/commands/EVALSHA.ts +++ b/packages/client/lib/commands/EVALSHA.ts @@ -1,7 +1,9 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import EVAL, { transformEvalArguments } from './EVAL'; -export const FIRST_KEY_INDEX = evalFirstKeyIndex; - -export function transformArguments(sha1: string, options?: EvalOptions): Array { - return pushEvalArguments(['EVALSHA', sha1], options); -} +export default { + FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, + IS_READ_ONLY: false, + transformArguments: transformEvalArguments.bind(undefined, 'EVALSHA'), + transformReply: EVAL.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EVALSHA_RO.spec.ts b/packages/client/lib/commands/EVALSHA_RO.spec.ts index 939a4a209cb..0afd5d18037 100644 --- a/packages/client/lib/commands/EVALSHA_RO.spec.ts +++ b/packages/client/lib/commands/EVALSHA_RO.spec.ts @@ -1,17 +1,17 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './EVALSHA_RO'; +import EVALSHA_RO from './EVALSHA_RO'; describe('EVALSHA_RO', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('sha1', { - keys: ['key'], - arguments: ['argument'] - }), - ['EVALSHA_RO', 'sha1', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EVALSHA_RO.transformArguments('sha1', { + keys: ['key'], + arguments: ['argument'] + }), + ['EVALSHA_RO', 'sha1', '1', 'key', 'argument'] + ); + }); }); diff --git a/packages/client/lib/commands/EVALSHA_RO.ts b/packages/client/lib/commands/EVALSHA_RO.ts index c3fcc3dc9cf..fe9042bd5fd 100644 --- a/packages/client/lib/commands/EVALSHA_RO.ts +++ b/packages/client/lib/commands/EVALSHA_RO.ts @@ -1,9 +1,9 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import EVAL, { transformEvalArguments } from './EVAL'; -export const FIRST_KEY_INDEX = evalFirstKeyIndex; - -export const IS_READ_ONLY = true; - -export function transformArguments(sha1: string, options?: EvalOptions): Array { - return pushEvalArguments(['EVALSHA_RO', sha1], options); -} +export default { + FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformEvalArguments.bind(undefined, 'EVALSHA_RO'), + transformReply: EVAL.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/EVAL_RO.spec.ts b/packages/client/lib/commands/EVAL_RO.spec.ts index f71d0b2b24a..06ae6c64096 100644 --- a/packages/client/lib/commands/EVAL_RO.spec.ts +++ b/packages/client/lib/commands/EVAL_RO.spec.ts @@ -1,31 +1,27 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EVAL_RO'; +import EVAL_RO from './EVAL_RO'; describe('EVAL_RO', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('return KEYS[1] + ARGV[1]', { - keys: ['key'], - arguments: ['argument'] - }), - ['EVAL_RO', 'return KEYS[1] + ARGV[1]', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EVAL_RO.transformArguments('return KEYS[1] + ARGV[1]', { + keys: ['key'], + arguments: ['argument'] + }), + ['EVAL_RO', 'return KEYS[1] + ARGV[1]', '1', 'key', 'argument'] + ); + }); - testUtils.testWithClient('client.evalRo', async client => { - assert.equal( - await client.evalRo('return 1'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.evalRo', async cluster => { - assert.equal( - await cluster.evalRo('return 1'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('evalRo', async cluster => { + assert.equal( + await cluster.evalRo('return 1'), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/EVAL_RO.ts b/packages/client/lib/commands/EVAL_RO.ts index 590c3af04f3..2608e28f789 100644 --- a/packages/client/lib/commands/EVAL_RO.ts +++ b/packages/client/lib/commands/EVAL_RO.ts @@ -1,9 +1,9 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import EVAL, { transformEvalArguments } from './EVAL'; -export const FIRST_KEY_INDEX = evalFirstKeyIndex; - -export const IS_READ_ONLY = true; - -export function transformArguments(script: string, options?: EvalOptions): Array { - return pushEvalArguments(['EVAL_RO', script], options); -} +export default { + FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformEvalArguments.bind(undefined, 'EVAL_RO'), + transformReply: EVAL.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FCALL.ts b/packages/client/lib/commands/FCALL.ts index a4cadedb6f9..a2411f62dc2 100644 --- a/packages/client/lib/commands/FCALL.ts +++ b/packages/client/lib/commands/FCALL.ts @@ -5,3 +5,15 @@ export const FIRST_KEY_INDEX = evalFirstKeyIndex; export function transformArguments(fn: string, options?: EvalOptions): Array { return pushEvalArguments(['FCALL', fn], options); } + +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments() { + return ['FCALL']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; + diff --git a/packages/client/lib/commands/HELLO.spec.ts b/packages/client/lib/commands/HELLO.spec.ts index 12d6d98c7c9..0a60c7ae69f 100644 --- a/packages/client/lib/commands/HELLO.spec.ts +++ b/packages/client/lib/commands/HELLO.spec.ts @@ -1,76 +1,71 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './HELLO'; +import HELLO from './HELLO'; describe('HELLO', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['HELLO'] - ); - }); - - it('with protover', () => { - assert.deepEqual( - transformArguments({ - protover: 3 - }), - ['HELLO', '3'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + HELLO.transformArguments(), + ['HELLO'] + ); + }); - it('with protover, auth', () => { - assert.deepEqual( - transformArguments({ - protover: 3, - auth: { - username: 'username', - password: 'password' - } - }), - ['HELLO', '3', 'AUTH', 'username', 'password'] - ); - }); + it('with protover', () => { + assert.deepEqual( + HELLO.transformArguments(3), + ['HELLO', '3'] + ); + }); - it('with protover, clientName', () => { - assert.deepEqual( - transformArguments({ - protover: 3, - clientName: 'clientName' - }), - ['HELLO', '3', 'SETNAME', 'clientName'] - ); - }); + it('with protover, AUTH', () => { + assert.deepEqual( + HELLO.transformArguments(3, { + AUTH: { + username: 'username', + password: 'password' + } + }), + ['HELLO', '3', 'AUTH', 'username', 'password'] + ); + }); - it('with protover, auth, clientName', () => { - assert.deepEqual( - transformArguments({ - protover: 3, - auth: { - username: 'username', - password: 'password' - }, - clientName: 'clientName' - }), - ['HELLO', '3', 'AUTH', 'username', 'password', 'SETNAME', 'clientName'] - ); - }); + it('with protover, SETNAME', () => { + assert.deepEqual( + HELLO.transformArguments(3, { + SETNAME: 'name' + }), + ['HELLO', '3', 'SETNAME', 'name'] + ); }); - testUtils.testWithClient('client.hello', async client => { - const reply = await client.hello(); - assert.equal(reply.server, 'redis'); - assert.equal(typeof reply.version, 'string'); - assert.equal(reply.proto, 2); - assert.equal(typeof reply.id, 'number'); - assert.equal(reply.mode, 'standalone'); - assert.equal(reply.role, 'master'); - assert.deepEqual(reply.modules, []); - }, { - ...GLOBAL.SERVERS.OPEN, - minimumDockerVersion: [6, 2] + it('with protover, AUTH, SETNAME', () => { + assert.deepEqual( + HELLO.transformArguments(3, { + AUTH: { + username: 'username', + password: 'password' + }, + SETNAME: 'name' + }), + ['HELLO', '3', 'AUTH', 'username', 'password', 'SETNAME', 'name'] + ); }); + }); + + testUtils.testWithClient('client.hello', async client => { + const reply = await client.hello(); + assert.equal(reply.server, 'redis'); + assert.equal(typeof reply.version, 'string'); + assert.equal(reply.proto, 2); + assert.equal(typeof reply.id, 'number'); + assert.equal(reply.mode, 'standalone'); + assert.equal(reply.role, 'master'); + assert.deepEqual(reply.modules, []); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] + }); }); diff --git a/packages/client/lib/commands/HELLO.ts b/packages/client/lib/commands/HELLO.ts index d4784b67c40..717ee05130d 100644 --- a/packages/client/lib/commands/HELLO.ts +++ b/packages/client/lib/commands/HELLO.ts @@ -1,6 +1,7 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command, NumberReply, Resp2Reply, RespVersions, TuplesToMapReply } from '../RESP/types'; export interface HelloOptions { + protover?: RespVersions; AUTH?: { username: RedisArgument; password: RedisArgument; @@ -19,22 +20,26 @@ export type HelloReply = TuplesToMapReply<[ ]>; export default { - transformArguments(protoover: RespVersions, options?: HelloOptions) { - const args: Array = ['HELLO', protoover.toString()]; + transformArguments(protover?: RespVersions, options?: HelloOptions) { + const args: Array = ['HELLO']; - if (options?.AUTH) { - args.push( - 'AUTH', - options.AUTH.username, - options.AUTH.password - ); - } + if (protover) { + args.push(protover.toString()); - if (options?.SETNAME) { - args.push( - 'SETNAME', - options.SETNAME - ); + if (options?.AUTH) { + args.push( + 'AUTH', + options.AUTH.username, + options.AUTH.password + ); + } + + if (options?.SETNAME) { + args.push( + 'SETNAME', + options.SETNAME + ); + } } return args; diff --git a/packages/client/lib/commands/LASTSAVE.spec.ts b/packages/client/lib/commands/LASTSAVE.spec.ts index a6b4863f39e..db282374a97 100644 --- a/packages/client/lib/commands/LASTSAVE.spec.ts +++ b/packages/client/lib/commands/LASTSAVE.spec.ts @@ -1,16 +1,16 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LASTSAVE'; +import LASTSAVE from './LASTSAVE'; describe('LASTSAVE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['LASTSAVE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LASTSAVE.transformArguments(), + ['LASTSAVE'] + ); + }); - testUtils.testWithClient('client.lastSave', async client => { - assert.ok((await client.lastSave()) instanceof Date); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.lastSave', async client => { + assert.ok(typeof await client.lastSave() === 'number'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LASTSAVE.ts b/packages/client/lib/commands/LASTSAVE.ts index 76944d3548b..a65161f78b9 100644 --- a/packages/client/lib/commands/LASTSAVE.ts +++ b/packages/client/lib/commands/LASTSAVE.ts @@ -1,9 +1,10 @@ -export const IS_READ_ONLY = true; +import { NumberReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['LASTSAVE']; -} - -export function transformReply(reply: number): Date { - return new Date(reply); -} + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_LEN.spec.ts b/packages/client/lib/commands/LCS_LEN.spec.ts index c3cffb0937c..0ad10b3ed82 100644 --- a/packages/client/lib/commands/LCS_LEN.spec.ts +++ b/packages/client/lib/commands/LCS_LEN.spec.ts @@ -14,7 +14,7 @@ describe('LCS_LEN', () => { testUtils.testAll('lcsLen', async client => { assert.equal( - await client.lcsLen('1', '2'), + await client.lcsLen('{tag}1', '{tag}2'), 0 ); }, { diff --git a/packages/client/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts index 929fd2dfd43..e0ca4ec797e 100644 --- a/packages/client/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -10,13 +10,10 @@ describe('MOVE', () => { ); }); - testUtils.testAll('move', async client => { + testUtils.testWithClient('client.move', async client => { assert.equal( await client.move('key', 1), 0 ); - }, { - client: GLOBAL.SERVERS.OPEN, - cluster: GLOBAL.CLUSTERS.OPEN - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBLISH.spec.ts b/packages/client/lib/commands/PUBLISH.spec.ts index b2084e668ba..e9657812915 100644 --- a/packages/client/lib/commands/PUBLISH.spec.ts +++ b/packages/client/lib/commands/PUBLISH.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBLISH'; +import PUBLISH from './PUBLISH'; describe('PUBLISH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('channel', 'message'), - ['PUBLISH', 'channel', 'message'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PUBLISH.transformArguments('channel', 'message'), + ['PUBLISH', 'channel', 'message'] + ); + }); - testUtils.testWithClient('client.publish', async client => { - assert.equal( - await client.publish('channel', 'message'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.publish', async client => { + assert.equal( + await client.publish('channel', 'message'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c96883ae490..8f66b1cab0f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -45,6 +45,11 @@ import DECR from './DECR'; import DECRBY from './DECRBY'; import DEL from './DEL'; import DUMP from './DUMP'; +import ECHO from './ECHO'; +import EVAL_RO from './EVAL_RO'; +import EVAL from './EVAL'; +import EVALSHA_RO from './EVALSHA_RO'; +import EVALSHA from './EVALSHA'; import GEOADD from './GEOADD'; import GEODIST from './GEODIST'; import GEOHASH from './GEOHASH'; @@ -75,6 +80,7 @@ import EXPIRETIME from './EXPIRETIME'; import FLUSHALL from './FLUSHALL'; import FLUSHDB from './FLUSHDB'; import HDEL from './HDEL'; +import HELLO from './HELLO'; import HEXISTS from './HEXISTS'; import HGET from './HGET'; import HGETALL from './HGETALL'; @@ -96,6 +102,7 @@ import INCRBY from './INCRBY'; import INCRBYFLOAT from './INCRBYFLOAT'; import INFO from './INFO'; import KEYS from './KEYS'; +import LASTSAVE from './LASTSAVE'; // import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; // import LCS_IDX from './LCS_IDX'; import LCS_LEN from './LCS_LEN'; @@ -320,6 +327,16 @@ export default { del: DEL, DUMP, dump: DUMP, + ECHO, + echo: ECHO, + EVAL_RO, + evalRo: EVAL_RO, + EVAL, + eval: EVAL, + EVALSHA_RO, + evalShaRo: EVALSHA_RO, + EVALSHA, + evalSha: EVALSHA, EXISTS, exists: EXISTS, EXPIRE, @@ -380,6 +397,8 @@ export default { getSet: GETSET, HDEL, hDel: HDEL, + HELLO, + hello: HELLO, HEXISTS, hExists: HEXISTS, HGET, @@ -422,6 +441,8 @@ export default { info: INFO, KEYS, keys: KEYS, + LASTSAVE, + lastSave: LASTSAVE, // LCS_IDX_WITHMATCHLEN, // LCS_IDX, LCS_LEN, From 37be30a8fe0992ba3726902033d9addeab8e11c0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 14 May 2023 14:42:48 +0300 Subject: [PATCH 104/325] some more commands --- packages/client/lib/commands/LCS_IDX.spec.ts | 61 ++++---- packages/client/lib/commands/LCS_IDX.ts | 98 ++++++------ .../lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts | 63 ++++---- .../lib/commands/LCS_IDX_WITHMATCHLEN.ts | 77 ++++----- packages/client/lib/commands/LOLWUT.spec.ts | 52 +++---- .../client/lib/commands/MEMORY_DOCTOR.spec.ts | 26 ++-- packages/client/lib/commands/MEMORY_DOCTOR.ts | 13 +- .../lib/commands/MEMORY_MALLOC-STATS.spec.ts | 26 ++-- .../lib/commands/MEMORY_MALLOC-STATS.ts | 12 +- .../client/lib/commands/MEMORY_PURGE.spec.ts | 26 ++-- packages/client/lib/commands/MEMORY_PURGE.ts | 12 +- .../client/lib/commands/MEMORY_STATS.spec.ts | 147 +++++------------- packages/client/lib/commands/MEMORY_STATS.ts | 138 ++++++---------- .../client/lib/commands/MEMORY_USAGE.spec.ts | 44 +++--- packages/client/lib/commands/MEMORY_USAGE.ts | 23 +-- .../client/lib/commands/MODULE_LIST.spec.ts | 14 +- packages/client/lib/commands/MODULE_LIST.ts | 4 +- .../client/lib/commands/MODULE_LOAD.spec.ts | 28 ++-- packages/client/lib/commands/MODULE_LOAD.ts | 2 +- .../client/lib/commands/MODULE_UNLOAD.spec.ts | 14 +- packages/client/lib/commands/MODULE_UNLOAD.ts | 2 +- .../lib/commands/PUBSUB_CHANNELS.spec.ts | 40 ++--- .../client/lib/commands/PUBSUB_NUMPAT.spec.ts | 26 ++-- .../client/lib/commands/PUBSUB_NUMSUB.spec.ts | 52 +++---- .../lib/commands/PUBSUB_SHARDCHANNELS.spec.ts | 44 +++--- .../lib/commands/PUBSUB_SHARDCHANNELS.ts | 2 +- packages/client/lib/commands/READONLY.spec.ts | 4 +- .../client/lib/commands/READWRITE.spec.ts | 14 +- .../client/lib/commands/REPLICAOF.spec.ts | 14 +- .../lib/commands/RESTORE-ASKING.spec.ts | 14 +- packages/client/lib/commands/SAVE.spec.ts | 14 +- packages/client/lib/commands/index.ts | 51 +++++- 32 files changed, 545 insertions(+), 612 deletions(-) diff --git a/packages/client/lib/commands/LCS_IDX.spec.ts b/packages/client/lib/commands/LCS_IDX.spec.ts index fc3ee54f7c0..72d0f985b43 100644 --- a/packages/client/lib/commands/LCS_IDX.spec.ts +++ b/packages/client/lib/commands/LCS_IDX.spec.ts @@ -1,41 +1,34 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LCS_IDX'; +import LCS_IDX from './LCS_IDX'; -describe('LCS_IDX', () => { - testUtils.isVersionGreaterThanHook([7]); +describe('LCS IDX', () => { + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('1', '2'), - ['LCS', '1', '2', 'IDX'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LCS_IDX.transformArguments('1', '2'), + ['LCS', '1', '2', 'IDX'] + ); + }); - testUtils.testWithClient('client.lcsIdx', async client => { - const [, reply] = await Promise.all([ - client.mSet({ - '1': 'abc', - '2': 'bc' - }), - client.lcsIdx('1', '2') - ]); + testUtils.testWithClient('client.lcsIdx', async client => { + const [, reply] = await Promise.all([ + client.mSet({ + '1': 'abc', + '2': 'bc' + }), + client.lcsIdx('1', '2') + ]); - assert.deepEqual( - reply, - { - matches: [{ - key1: { - start: 1, - end: 2 - }, - key2: { - start: 0, - end: 1 - } - }], - length: 2 - } - ); - }, GLOBAL.SERVERS.OPEN); + console.log(reply); + + assert.deepEqual( + reply, + { + matches: [[[1, 2], [0, 1]]], + len: 2 + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LCS_IDX.ts b/packages/client/lib/commands/LCS_IDX.ts index b9961830578..41a0b61e8a8 100644 --- a/packages/client/lib/commands/LCS_IDX.ts +++ b/packages/client/lib/commands/LCS_IDX.ts @@ -1,48 +1,50 @@ -// import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; -// import LCS from './LCS'; - -// export interface LcsIdxOptions { -// MINMATCHLEN?: number; -// } - -// export type LcsIdxRange = TuplesReply<[ -// start: NumberReply, -// end: NumberReply -// ]>; - -// export type LcsIdxMatches = ArrayReply< -// TuplesReply<[ -// key1: LcsIdxRange, -// key2: LcsIdxRange -// ]> -// >; - -// export type LcsIdxReply = TuplesToMapReply<[ -// [BlobStringReply<'matches'>, LcsIdxMatches], -// [BlobStringReply<'len'>, NumberReply] -// ]>; - -// export default { -// FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, -// IS_READ_ONLY: LCS.IS_READ_ONLY, -// transformArguments( -// key1: RedisArgument, -// key2: RedisArgument, -// options?: LcsIdxOptions -// ) { -// const args = LCS.transformArguments(key1, key2); - -// if (options?.MINMATCHLEN) { -// args.push('MINMATCHLEN', options.MINMATCHLEN.toString()); -// } - -// return args; -// }, -// transformReply: { -// 2: (reply: Resp2Reply) => ({ -// matches: reply[1], -// len: reply[2] -// }), -// 3: undefined as unknown as () => LcsIdxReply -// } -// } as const satisfies Command; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +import LCS from './LCS'; + +export interface LcsIdxOptions { + MINMATCHLEN?: number; +} + +export type LcsIdxRange = TuplesReply<[ + start: NumberReply, + end: NumberReply +]>; + +export type LcsIdxMatches = ArrayReply< + TuplesReply<[ + key1: LcsIdxRange, + key2: LcsIdxRange + ]> +>; + +export type LcsIdxReply = TuplesToMapReply<[ + [BlobStringReply<'matches'>, LcsIdxMatches], + [BlobStringReply<'len'>, NumberReply] +]>; + +export default { + FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, + IS_READ_ONLY: LCS.IS_READ_ONLY, + transformArguments( + key1: RedisArgument, + key2: RedisArgument, + options?: LcsIdxOptions + ) { + const args = LCS.transformArguments(key1, key2); + + args.push('IDX'); + + if (options?.MINMATCHLEN) { + args.push('MINMATCHLEN', options.MINMATCHLEN.toString()); + } + + return args; + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + matches: reply[1], + len: reply[3] + }), + 3: undefined as unknown as () => LcsIdxReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts index 8be9b993135..80505ce38b1 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts @@ -1,42 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LCS_IDX_WITHMATCHLEN'; +import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; -describe('LCS_IDX_WITHMATCHLEN', () => { - testUtils.isVersionGreaterThanHook([7]); +describe('LCS IDX WITHMATCHLEN', () => { + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('1', '2'), - ['LCS', '1', '2', 'IDX', 'WITHMATCHLEN'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LCS_IDX_WITHMATCHLEN.transformArguments('1', '2'), + ['LCS', '1', '2', 'IDX', 'WITHMATCHLEN'] + ); + }); - testUtils.testWithClient('client.lcsIdxWithMatchLen', async client => { - const [, reply] = await Promise.all([ - client.mSet({ - '1': 'abc', - '2': 'bc' - }), - client.lcsIdxWithMatchLen('1', '2') - ]); + testUtils.testWithClient('client.lcsIdxWithMatchLen', async client => { + const [, reply] = await Promise.all([ + client.mSet({ + '1': 'abc', + '2': 'bc' + }), + client.lcsIdxWithMatchLen('1', '2') + ]); - assert.deepEqual( - reply, - { - matches: [{ - key1: { - start: 1, - end: 2 - }, - key2: { - start: 0, - end: 1 - }, - length: 2 - }], - length: 2 - } - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + reply, + { + matches: [ + [[[1, 2], [0, 1]]], + 2 + ], + len: 2 + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts index 2b6a87672a9..abd3bb361f5 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts @@ -1,47 +1,36 @@ -// import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; -// import LCS from './LCS'; -// import { LcsIdxRange } from './LCS_IDX'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +import LCS_IDX, { LcsIdxOptions, LcsIdxRange } from './LCS_IDX'; -// interface LcsIdxOptions { -// MINMATCHLEN?: number; -// } +export type LcsIdxWithMatchLenMatches = ArrayReply< + TuplesReply<[ + key1: LcsIdxRange, + key2: LcsIdxRange, + len: NumberReply + ]> +>; -// export type LcsIdxWithMatchLenMatches = ArrayReply< -// TuplesReply<[ -// key1: LcsIdxRange, -// key2: LcsIdxRange, -// len: NumberReply -// ]> -// >; +export type LcsIdxWithMatchLenReply = TuplesToMapReply<[ + [BlobStringReply<'matches'>, LcsIdxWithMatchLenMatches], + [BlobStringReply<'len'>, NumberReply] +]>; -// export type LcsIdxReply = TuplesToMapReply<[ -// [BlobStringReply<'matches'>, LcsIdxWithMatchLenMatches], -// [BlobStringReply<'len'>, NumberReply] -// ]>; - -// export default { -// FIRST_KEY_INDEX: LCS.FIRST_KEY_INDEX, -// IS_READ_ONLY: LCS.IS_READ_ONLY, -// transformArguments( -// key1: RedisArgument, -// key2: RedisArgument, -// options?: LcsIdxOptions -// ) { -// const args = LCS.transformArguments(key1, key2); - -// if (options?.MINMATCHLEN) { -// args.push('MINMATCHLEN', options.MINMATCHLEN.toString()); -// } - -// args.push('WITHMATCHLEN'); - -// return args; -// }, -// transformReply: { -// 2: (reply: Resp2Reply) => ({ -// matches: reply[1], -// len: reply[2] -// }), -// 3: undefined as unknown as () => LcsIdxReply -// } -// } as const satisfies Command; +export default { + FIRST_KEY_INDEX: LCS_IDX.FIRST_KEY_INDEX, + IS_READ_ONLY: LCS_IDX.IS_READ_ONLY, + transformArguments( + key1: RedisArgument, + key2: RedisArgument, + options?: LcsIdxOptions + ) { + const args = LCS_IDX.transformArguments(key1, key2); + args.push('WITHMATCHLEN'); + return args; + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + matches: reply[1], + len: reply[3] + }), + 3: undefined as unknown as () => LcsIdxWithMatchLenReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/LOLWUT.spec.ts b/packages/client/lib/commands/LOLWUT.spec.ts index db335893302..89b294bdad4 100644 --- a/packages/client/lib/commands/LOLWUT.spec.ts +++ b/packages/client/lib/commands/LOLWUT.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LOLWUT'; +import LOLWUT from './LOLWUT'; describe('LOLWUT', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['LOLWUT'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + LOLWUT.transformArguments(), + ['LOLWUT'] + ); + }); - it('with version', () => { - assert.deepEqual( - transformArguments(5), - ['LOLWUT', 'VERSION', '5'] - ); - }); + it('with version', () => { + assert.deepEqual( + LOLWUT.transformArguments(5), + ['LOLWUT', 'VERSION', '5'] + ); + }); - it('with version and optional arguments', () => { - assert.deepEqual( - transformArguments(5, 1, 2, 3), - ['LOLWUT', 'VERSION', '5', '1', '2', '3'] - ); - }); + it('with version and optional arguments', () => { + assert.deepEqual( + LOLWUT.transformArguments(5, 1, 2, 3), + ['LOLWUT', 'VERSION', '5', '1', '2', '3'] + ); }); + }); - testUtils.testWithClient('client.LOLWUT', async client => { - assert.equal( - typeof (await client.LOLWUT()), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.LOLWUT', async client => { + assert.equal( + typeof (await client.LOLWUT()), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts index ad97047606c..0936bd98983 100644 --- a/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts +++ b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MEMORY_DOCTOR'; +import MEMORY_DOCTOR from './MEMORY_DOCTOR'; describe('MEMORY DOCTOR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['MEMORY', 'DOCTOR'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MEMORY_DOCTOR.transformArguments(), + ['MEMORY', 'DOCTOR'] + ); + }); - testUtils.testWithClient('client.memoryDoctor', async client => { - assert.equal( - typeof (await client.memoryDoctor()), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.memoryDoctor', async client => { + assert.equal( + typeof (await client.memoryDoctor()), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_DOCTOR.ts b/packages/client/lib/commands/MEMORY_DOCTOR.ts index 95a37246ffa..6f8eb29ef2b 100644 --- a/packages/client/lib/commands/MEMORY_DOCTOR.ts +++ b/packages/client/lib/commands/MEMORY_DOCTOR.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['MEMORY', 'DOCTOR']; -} +import { BlobStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['MEMORY', 'DOCTOR']; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts index ce866f1e116..7cf5e5dc8b1 100644 --- a/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MEMORY_MALLOC-STATS'; +import MEMORY_MALLOC_STATS from './MEMORY_MALLOC-STATS'; describe('MEMORY MALLOC-STATS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['MEMORY', 'MALLOC-STATS'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MEMORY_MALLOC_STATS.transformArguments(), + ['MEMORY', 'MALLOC-STATS'] + ); + }); - testUtils.testWithClient('client.memoryMallocStats', async client => { - assert.equal( - typeof (await client.memoryDoctor()), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.memoryMallocStats', async client => { + assert.equal( + typeof (await client.memoryMallocStats()), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_MALLOC-STATS.ts b/packages/client/lib/commands/MEMORY_MALLOC-STATS.ts index 3977e3a1de4..31b01a49b5c 100644 --- a/packages/client/lib/commands/MEMORY_MALLOC-STATS.ts +++ b/packages/client/lib/commands/MEMORY_MALLOC-STATS.ts @@ -1,5 +1,11 @@ -export function transformArguments(): Array { +import { BlobStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['MEMORY', 'MALLOC-STATS']; -} + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; -export declare function transformReply(): string; diff --git a/packages/client/lib/commands/MEMORY_PURGE.spec.ts b/packages/client/lib/commands/MEMORY_PURGE.spec.ts index 5d34331feb6..f54769bcc2a 100644 --- a/packages/client/lib/commands/MEMORY_PURGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_PURGE.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MEMORY_PURGE'; +import MEMORY_PURGE from './MEMORY_PURGE'; describe('MEMORY PURGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['MEMORY', 'PURGE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MEMORY_PURGE.transformArguments(), + ['MEMORY', 'PURGE'] + ); + }); - testUtils.testWithClient('client.memoryPurge', async client => { - assert.equal( - await client.memoryPurge(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.memoryPurge', async client => { + assert.equal( + await client.memoryPurge(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_PURGE.ts b/packages/client/lib/commands/MEMORY_PURGE.ts index cfa38179273..b4c48d40102 100644 --- a/packages/client/lib/commands/MEMORY_PURGE.ts +++ b/packages/client/lib/commands/MEMORY_PURGE.ts @@ -1,5 +1,11 @@ -export function transformArguments(): Array { +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments() { return ['MEMORY', 'PURGE']; -} + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -export declare function transformReply(): string; diff --git a/packages/client/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts index 12aa21181e6..6c53b61b036 100644 --- a/packages/client/lib/commands/MEMORY_STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_STATS.spec.ts @@ -1,108 +1,43 @@ -import { strict as assert } from 'assert'; -import { transformArguments, transformReply } from './MEMORY_STATS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import MEMORY_STATS from './MEMORY_STATS'; -describe('MEMORY STATS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['MEMORY', 'STATS'] - ); - }); +// describe('MEMORY STATS', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// MEMORY_STATS.transformArguments(), +// ['MEMORY', 'STATS'] +// ); +// }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - 'peak.allocated', - 952728, - 'total.allocated', - 892904, - 'startup.allocated', - 809952, - 'replication.backlog', - 0, - 'clients.slaves', - 0, - 'clients.normal', - 41000, - 'aof.buffer', - 0, - 'lua.caches', - 0, - 'db.0', - [ - 'overhead.hashtable.main', - 72, - 'overhead.hashtable.expires', - 0 - ], - 'overhead.total', - 850952, - 'keys.count', - 0, - 'keys.bytes-per-key', - 0, - 'dataset.bytes', - 41952, - 'dataset.percentage', - '50.573825836181641', - 'peak.percentage', - '93.720771789550781', - 'allocator.allocated', - 937632, - 'allocator.active', - 1191936, - 'allocator.resident', - 4005888, - 'allocator-fragmentation.ratio', - '1.2712193727493286', - 'allocator-fragmentation.bytes', - 254304, - 'allocator-rss.ratio', - '3.3608248233795166', - 'allocator-rss.bytes', - 2813952, - 'rss-overhead.ratio', - '2.4488751888275146', - 'rss-overhead.bytes', - 5804032, - 'fragmentation', - '11.515504837036133', - 'fragmentation.bytes', - 8958032 - ]), - { - peakAllocated: 952728, - totalAllocated: 892904, - startupAllocated: 809952, - replicationBacklog: 0, - clientsReplicas: 0, - clientsNormal: 41000, - aofBuffer: 0, - luaCaches: 0, - overheadTotal: 850952, - keysCount: 0, - keysBytesPerKey: 0, - datasetBytes: 41952, - datasetPercentage: 50.573825836181641, - peakPercentage: 93.720771789550781, - allocatorAllocated: 937632, - allocatorActive: 1191936, - allocatorResident: 4005888, - allocatorFragmentationRatio: 1.2712193727493286, - allocatorFragmentationBytes: 254304, - allocatorRssRatio: 3.3608248233795166, - allocatorRssBytes: 2813952, - rssOverheadRatio: 2.4488751888275146, - rssOverheadBytes: 5804032, - fragmentation: 11.515504837036133, - fragmentationBytes: 8958032, - db: { - 0: { - overheadHashtableMain: 72, - overheadHashtableExpires: 0 - } - } - } - ); - }); -}); +// testUtils.testWithClient('client.memoryStats', async client => { +// const memoryStats = await client.memoryStats(); +// assert.equal(typeof memoryStats['peak.allocated'], 'number'); +// assert.equal(typeof memoryStats['total.allocated'], 'number'); +// assert.equal(typeof memoryStats['startup.allocated'], 'number'); +// assert.equal(typeof memoryStats['replication.backlog'], 'number'); +// assert.equal(typeof memoryStats['clients.slaves'], 'number'); +// assert.equal(typeof memoryStats['clients.normal'], 'number'); +// assert.equal(typeof memoryStats['cluster.links'], 'number'); +// assert.equal(typeof memoryStats['aof.buffer'], 'number'); +// assert.equal(typeof memoryStats['lua.caches'], 'number'); +// assert.equal(typeof memoryStats['functions.caches'], 'number'); +// assert.equal(typeof memoryStats['overhead.total'], 'number'); +// assert.equal(typeof memoryStats['keys.count'], 'number'); +// assert.equal(typeof memoryStats['keys.bytes-per-key'], 'number'); +// assert.equal(typeof memoryStats['dataset.bytes'], 'number'); +// assert.equal(typeof memoryStats['dataset.percentage'], 'string'); +// assert.equal(typeof memoryStats['peak.percentage'], 'string'); +// assert.equal(typeof memoryStats['allocator.allocated'], 'number'); +// assert.equal(typeof memoryStats['allocator.active'], 'number'); +// assert.equal(typeof memoryStats['allocator.resident'], 'number'); +// assert.equal(typeof memoryStats['allocator-fragmentation.ratio'], 'string'); +// assert.equal(typeof memoryStats['allocator-fragmentation.bytes'], 'number'); +// assert.equal(typeof memoryStats['allocator-rss.ratio'], 'string'); +// assert.equal(typeof memoryStats['allocator-rss.bytes'], 'number'); +// assert.equal(typeof memoryStats['rss-overhead.ratio'], 'string'); +// assert.equal(typeof memoryStats['rss-overhead.bytes'], 'number'); +// assert.equal(typeof memoryStats['fragmentation'], 'string'); +// assert.equal(typeof memoryStats['fragmentation.bytes'], 'number'); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 8ae83d2239a..4cc2ca2e4d6 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -1,93 +1,53 @@ -export function transformArguments(): Array { - return ['MEMORY', 'STATS']; -} +// import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Command, Resp2Reply } from '../RESP/types'; -interface MemoryStatsReply { - peakAllocated: number; - totalAllocated: number; - startupAllocated: number; - replicationBacklog: number; - clientsReplicas: number; - clientsNormal: number; - aofBuffer: number; - luaCaches: number; - overheadTotal: number; - keysCount: number; - keysBytesPerKey: number; - datasetBytes: number; - datasetPercentage: number; - peakPercentage: number; - allocatorAllocated?: number, - allocatorActive?: number; - allocatorResident?: number; - allocatorFragmentationRatio?: number; - allocatorFragmentationBytes?: number; - allocatorRssRatio?: number; - allocatorRssBytes?: number; - rssOverheadRatio?: number; - rssOverheadBytes?: number; - fragmentation?: number; - fragmentationBytes: number; - db: { - [key: number]: { - overheadHashtableMain: number; - overheadHashtableExpires: number; - }; - }; -} +// export type MemoryStatsReply = TuplesToMapReply<[ +// [BlobStringReply<'peak.allocated'>, NumberReply], +// [BlobStringReply<'total.allocated'>, NumberReply], +// [BlobStringReply<'startup.allocated'>, NumberReply], +// [BlobStringReply<'replication.backlog'>, NumberReply], +// [BlobStringReply<'clients.slaves'>, NumberReply], +// [BlobStringReply<'clients.normal'>, NumberReply], +// [BlobStringReply<'cluster.links'>, NumberReply], +// [BlobStringReply<'aof.buffer'>, NumberReply], +// [BlobStringReply<'lua.caches'>, NumberReply], +// [BlobStringReply<'functions.caches'>, NumberReply], +// [BlobStringReply<'overhead.total'>, NumberReply], +// [BlobStringReply<'keys.count'>, NumberReply], +// [BlobStringReply<'keys.bytes-per-key'>, NumberReply], +// [BlobStringReply<'dataset.bytes'>, NumberReply], +// [BlobStringReply<'dataset.percentage'>, DoubleReply], +// [BlobStringReply<'peak.percentage'>, DoubleReply], +// [BlobStringReply<'allocator.allocated'>, NumberReply], +// [BlobStringReply<'allocator.active'>, NumberReply], +// [BlobStringReply<'allocator.resident'>, NumberReply], +// [BlobStringReply<'allocator-fragmentation.ratio'>, DoubleReply], +// [BlobStringReply<'allocator-fragmentation.bytes'>, NumberReply], +// [BlobStringReply<'allocator-rss.ratio'>, DoubleReply], +// [BlobStringReply<'allocator-rss.bytes'>, NumberReply], +// [BlobStringReply<'rss-overhead.ratio'>, DoubleReply], +// [BlobStringReply<'rss-overhead.bytes'>, NumberReply], +// [BlobStringReply<'fragmentation'>, DoubleReply], +// [BlobStringReply<'fragmentation.bytes'>, NumberReply] +// ]>; -const FIELDS_MAPPING = { - 'peak.allocated': 'peakAllocated', - 'total.allocated': 'totalAllocated', - 'startup.allocated': 'startupAllocated', - 'replication.backlog': 'replicationBacklog', - 'clients.slaves': 'clientsReplicas', - 'clients.normal': 'clientsNormal', - 'aof.buffer': 'aofBuffer', - 'lua.caches': 'luaCaches', - 'overhead.total': 'overheadTotal', - 'keys.count': 'keysCount', - 'keys.bytes-per-key': 'keysBytesPerKey', - 'dataset.bytes': 'datasetBytes', - 'dataset.percentage': 'datasetPercentage', - 'peak.percentage': 'peakPercentage', - 'allocator.allocated': 'allocatorAllocated', - 'allocator.active': 'allocatorActive', - 'allocator.resident': 'allocatorResident', - 'allocator-fragmentation.ratio': 'allocatorFragmentationRatio', - 'allocator-fragmentation.bytes': 'allocatorFragmentationBytes', - 'allocator-rss.ratio': 'allocatorRssRatio', - 'allocator-rss.bytes': 'allocatorRssBytes', - 'rss-overhead.ratio': 'rssOverheadRatio', - 'rss-overhead.bytes': 'rssOverheadBytes', - 'fragmentation': 'fragmentation', - 'fragmentation.bytes': 'fragmentationBytes' - }, - DB_FIELDS_MAPPING = { - 'overhead.hashtable.main': 'overheadHashtableMain', - 'overhead.hashtable.expires': 'overheadHashtableExpires' - }; +// export default { +// FIRST_KEY_INDEX: undefined, +// IS_READ_ONLY: true, +// transformArguments() { +// return ['MEMORY', 'STATS']; +// }, +// transformReply: { +// 2: (rawReply: Array) => { +// const reply: Partial> = {}; -export function transformReply(rawReply: Array>): MemoryStatsReply { - const reply: any = { - db: {} - }; +// let i = 0; +// while (i < rawReply.length) { +// const key = rawReply[i++] as keyof MemoryStatsReply['DEFAULT']; +// reply[key] = rawReply[i++] as any; +// } - for (let i = 0; i < rawReply.length; i += 2) { - const key = rawReply[i] as string; - if (key.startsWith('db.')) { - const dbTuples = rawReply[i + 1] as Array, - db: any = {}; - for (let j = 0; j < dbTuples.length; j += 2) { - db[DB_FIELDS_MAPPING[dbTuples[j] as keyof typeof DB_FIELDS_MAPPING]] = dbTuples[j + 1]; - } - - reply.db[key.substring(3)] = db; - continue; - } - - reply[FIELDS_MAPPING[key as keyof typeof FIELDS_MAPPING]] = Number(rawReply[i + 1]); - } - - return reply as MemoryStatsReply; -} +// return reply as MemoryStatsReply['DEFAULT']; +// }, +// 3: undefined as unknown as () => MemoryStatsReply +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/MEMORY_USAGE.spec.ts b/packages/client/lib/commands/MEMORY_USAGE.spec.ts index fe5ff404d93..e4bdb05c59a 100644 --- a/packages/client/lib/commands/MEMORY_USAGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_USAGE.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MEMORY_USAGE'; +import MEMORY_USAGE from './MEMORY_USAGE'; describe('MEMORY USAGE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key'), - ['MEMORY', 'USAGE', 'key'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + MEMORY_USAGE.transformArguments('key'), + ['MEMORY', 'USAGE', 'key'] + ); + }); - it('with SAMPLES', () => { - assert.deepEqual( - transformArguments('key', { - SAMPLES: 1 - }), - ['MEMORY', 'USAGE', 'key', 'SAMPLES', '1'] - ); - }); + it('with SAMPLES', () => { + assert.deepEqual( + MEMORY_USAGE.transformArguments('key', { + SAMPLES: 1 + }), + ['MEMORY', 'USAGE', 'key', 'SAMPLES', '1'] + ); }); + }); - testUtils.testWithClient('client.memoryUsage', async client => { - assert.equal( - await client.memoryUsage('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.memoryUsage', async client => { + assert.equal( + await client.memoryUsage('key'), + null + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_USAGE.ts b/packages/client/lib/commands/MEMORY_USAGE.ts index 959cdb0a0c4..78b079c2c13 100644 --- a/packages/client/lib/commands/MEMORY_USAGE.ts +++ b/packages/client/lib/commands/MEMORY_USAGE.ts @@ -1,19 +1,20 @@ -export const FIRST_KEY_INDEX = 1; +import { NumberReply, NullReply, Command, RedisArgument } from '../RESP/types'; -export const IS_READ_ONLY = true; - -interface MemoryUsageOptions { - SAMPLES?: number; +export interface MemoryUsageOptions { + SAMPLES?: number; } -export function transformArguments(key: string, options?: MemoryUsageOptions): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, options?: MemoryUsageOptions) { const args = ['MEMORY', 'USAGE', key]; if (options?.SAMPLES) { - args.push('SAMPLES', options.SAMPLES.toString()); + args.push('SAMPLES', options.SAMPLES.toString()); } - + return args; -} - -export declare function transformReply(): number | null; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_LIST.spec.ts b/packages/client/lib/commands/MODULE_LIST.spec.ts index eeeb774ebff..da5544cb098 100644 --- a/packages/client/lib/commands/MODULE_LIST.spec.ts +++ b/packages/client/lib/commands/MODULE_LIST.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './MODULE_LIST'; +import MODULE_LIST from './MODULE_LIST'; describe('MODULE LIST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['MODULE', 'LIST'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MODULE_LIST.transformArguments(), + ['MODULE', 'LIST'] + ); + }); }); diff --git a/packages/client/lib/commands/MODULE_LIST.ts b/packages/client/lib/commands/MODULE_LIST.ts index 5ab297faecc..9c61dcf07af 100644 --- a/packages/client/lib/commands/MODULE_LIST.ts +++ b/packages/client/lib/commands/MODULE_LIST.ts @@ -2,7 +2,7 @@ import { ArrayReply, BlobStringReply, NumberReply, Command, Resp2Reply, TuplesTo export type ModuleListReply = ArrayReply, BlobStringReply], - [BlobStringReply<'version'>, NumberReply], + [BlobStringReply<'ver'>, NumberReply], ]>>; export default { @@ -15,7 +15,7 @@ export default { 2: (reply: Resp2Reply) => { return reply.map(module => ({ name: module[1], - version: module[3] + ver: module[3] })); }, 3: undefined as unknown as () => ModuleListReply diff --git a/packages/client/lib/commands/MODULE_LOAD.spec.ts b/packages/client/lib/commands/MODULE_LOAD.spec.ts index 5a99a232ca4..254e9755a11 100644 --- a/packages/client/lib/commands/MODULE_LOAD.spec.ts +++ b/packages/client/lib/commands/MODULE_LOAD.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './MODULE_LOAD'; +import MODULE_LOAD from './MODULE_LOAD'; describe('MODULE LOAD', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('path'), - ['MODULE', 'LOAD', 'path'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + MODULE_LOAD.transformArguments('path'), + ['MODULE', 'LOAD', 'path'] + ); + }); - it('with module args', () => { - assert.deepEqual( - transformArguments('path', ['1', '2']), - ['MODULE', 'LOAD', 'path', '1', '2'] - ); - }); + it('with module args', () => { + assert.deepEqual( + MODULE_LOAD.transformArguments('path', ['1', '2']), + ['MODULE', 'LOAD', 'path', '1', '2'] + ); }); + }); }); diff --git a/packages/client/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts index 3fab206eeff..293a18a03c6 100644 --- a/packages/client/lib/commands/MODULE_LOAD.ts +++ b/packages/client/lib/commands/MODULE_LOAD.ts @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/MODULE_UNLOAD.spec.ts b/packages/client/lib/commands/MODULE_UNLOAD.spec.ts index d8af96c54f1..3de117bc5ca 100644 --- a/packages/client/lib/commands/MODULE_UNLOAD.spec.ts +++ b/packages/client/lib/commands/MODULE_UNLOAD.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './MODULE_UNLOAD'; +import MODULE_UNLOAD from './MODULE_UNLOAD'; describe('MODULE UNLOAD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('name'), - ['MODULE', 'UNLOAD', 'name'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MODULE_UNLOAD.transformArguments('name'), + ['MODULE', 'UNLOAD', 'name'] + ); + }); }); diff --git a/packages/client/lib/commands/MODULE_UNLOAD.ts b/packages/client/lib/commands/MODULE_UNLOAD.ts index 8d1e64800a9..3a2bc05c0e7 100644 --- a/packages/client/lib/commands/MODULE_UNLOAD.ts +++ b/packages/client/lib/commands/MODULE_UNLOAD.ts @@ -6,5 +6,5 @@ export default { transformArguments(name: RedisArgument) { return ['MODULE', 'UNLOAD', name]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts index c427eab4850..635a88eb107 100644 --- a/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts +++ b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBSUB_CHANNELS'; +import PUBSUB_CHANNELS from './PUBSUB_CHANNELS'; describe('PUBSUB CHANNELS', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['PUBSUB', 'CHANNELS'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + PUBSUB_CHANNELS.transformArguments(), + ['PUBSUB', 'CHANNELS'] + ); + }); - it('with pattern', () => { - assert.deepEqual( - transformArguments('patter*'), - ['PUBSUB', 'CHANNELS', 'patter*'] - ); - }); + it('with pattern', () => { + assert.deepEqual( + PUBSUB_CHANNELS.transformArguments('patter*'), + ['PUBSUB', 'CHANNELS', 'patter*'] + ); }); + }); - testUtils.testWithClient('client.pubSubChannels', async client => { - assert.deepEqual( - await client.pubSubChannels(), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.pubSubChannels', async client => { + assert.deepEqual( + await client.pubSubChannels(), + [] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts index d738b916c60..fce46b23287 100644 --- a/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBSUB_NUMPAT'; +import PUBSUB_NUMPAT from './PUBSUB_NUMPAT'; describe('PUBSUB NUMPAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['PUBSUB', 'NUMPAT'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PUBSUB_NUMPAT.transformArguments(), + ['PUBSUB', 'NUMPAT'] + ); + }); - testUtils.testWithClient('client.pubSubNumPat', async client => { - assert.equal( - await client.pubSubNumPat(), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.pubSubNumPat', async client => { + assert.equal( + await client.pubSubNumPat(), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts index e35558ef865..bf9741229c1 100644 --- a/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBSUB_NUMSUB'; +import PUBSUB_NUMSUB from './PUBSUB_NUMSUB'; describe('PUBSUB NUMSUB', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['PUBSUB', 'NUMSUB'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + PUBSUB_NUMSUB.transformArguments(), + ['PUBSUB', 'NUMSUB'] + ); + }); - it('string', () => { - assert.deepEqual( - transformArguments('channel'), - ['PUBSUB', 'NUMSUB', 'channel'] - ); - }); + it('string', () => { + assert.deepEqual( + PUBSUB_NUMSUB.transformArguments('channel'), + ['PUBSUB', 'NUMSUB', 'channel'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['PUBSUB', 'NUMSUB', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + PUBSUB_NUMSUB.transformArguments(['1', '2']), + ['PUBSUB', 'NUMSUB', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.pubSubNumSub', async client => { - assert.deepEqual( - await client.pubSubNumSub(), - Object.create(null) - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.pubSubNumSub', async client => { + assert.deepEqual( + await client.pubSubNumSub(), + Object.create(null) + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts index 1e5f2292b39..7b6bcaf5a03 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBSUB_SHARDCHANNELS'; +import PUBSUB_SHARDCHANNELS from './PUBSUB_SHARDCHANNELS'; describe('PUBSUB SHARDCHANNELS', () => { - testUtils.isVersionGreaterThanHook([7]); - - describe('transformArguments', () => { - it('without pattern', () => { - assert.deepEqual( - transformArguments(), - ['PUBSUB', 'SHARDCHANNELS'] - ); - }); + testUtils.isVersionGreaterThanHook([7]); - it('with pattern', () => { - assert.deepEqual( - transformArguments('patter*'), - ['PUBSUB', 'SHARDCHANNELS', 'patter*'] - ); - }); + describe('transformArguments', () => { + it('without pattern', () => { + assert.deepEqual( + PUBSUB_SHARDCHANNELS.transformArguments(), + ['PUBSUB', 'SHARDCHANNELS'] + ); }); - testUtils.testWithClient('client.pubSubShardChannels', async client => { - assert.deepEqual( - await client.pubSubShardChannels(), - [] - ); - }, GLOBAL.SERVERS.OPEN); + it('with pattern', () => { + assert.deepEqual( + PUBSUB_SHARDCHANNELS.transformArguments('patter*'), + ['PUBSUB', 'SHARDCHANNELS', 'patter*'] + ); + }); + }); + + testUtils.testWithClient('client.pubSubShardChannels', async client => { + assert.deepEqual( + await client.pubSubShardChannels(), + [] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts index 1403d67fa22..74d78c02614 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.ts @@ -4,7 +4,7 @@ export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(pattern?: RedisArgument) { - const args: Array = ['PUBSUB', 'bb']; + const args: Array = ['PUBSUB', 'SHARDCHANNELS']; if (pattern) { args.push(pattern); diff --git a/packages/client/lib/commands/READONLY.spec.ts b/packages/client/lib/commands/READONLY.spec.ts index e635d04009e..2aa0d274ceb 100644 --- a/packages/client/lib/commands/READONLY.spec.ts +++ b/packages/client/lib/commands/READONLY.spec.ts @@ -1,10 +1,10 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './READONLY'; +import READONLY from './READONLY'; describe('READONLY', () => { it('transformArguments', () => { assert.deepEqual( - transformArguments(), + READONLY.transformArguments(), ['READONLY'] ); }); diff --git a/packages/client/lib/commands/READWRITE.spec.ts b/packages/client/lib/commands/READWRITE.spec.ts index 6ce4a3ee56a..9f9e7982a6b 100644 --- a/packages/client/lib/commands/READWRITE.spec.ts +++ b/packages/client/lib/commands/READWRITE.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './READWRITE'; +import READWRITE from './READWRITE'; describe('READWRITE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['READWRITE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + READWRITE.transformArguments(), + ['READWRITE'] + ); + }); }); diff --git a/packages/client/lib/commands/REPLICAOF.spec.ts b/packages/client/lib/commands/REPLICAOF.spec.ts index ab1906944cf..a88f929e833 100644 --- a/packages/client/lib/commands/REPLICAOF.spec.ts +++ b/packages/client/lib/commands/REPLICAOF.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './REPLICAOF'; +import REPLICAOF from './REPLICAOF'; describe('REPLICAOF', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('host', 1), - ['REPLICAOF', 'host', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + REPLICAOF.transformArguments('host', 1), + ['REPLICAOF', 'host', '1'] + ); + }); }); diff --git a/packages/client/lib/commands/RESTORE-ASKING.spec.ts b/packages/client/lib/commands/RESTORE-ASKING.spec.ts index de9fce5c628..c87fd706450 100644 --- a/packages/client/lib/commands/RESTORE-ASKING.spec.ts +++ b/packages/client/lib/commands/RESTORE-ASKING.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './RESTORE-ASKING'; +import RESTORE_ASKING from './RESTORE-ASKING'; describe('RESTORE-ASKING', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['RESTORE-ASKING'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RESTORE_ASKING.transformArguments(), + ['RESTORE-ASKING'] + ); + }); }); diff --git a/packages/client/lib/commands/SAVE.spec.ts b/packages/client/lib/commands/SAVE.spec.ts index 1e1987b5ab8..66a9e210902 100644 --- a/packages/client/lib/commands/SAVE.spec.ts +++ b/packages/client/lib/commands/SAVE.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './SAVE'; +import SAVE from './SAVE'; describe('SAVE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['SAVE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SAVE.transformArguments(), + ['SAVE'] + ); + }); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 8f66b1cab0f..4e41be07c1b 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -103,8 +103,8 @@ import INCRBYFLOAT from './INCRBYFLOAT'; import INFO from './INFO'; import KEYS from './KEYS'; import LASTSAVE from './LASTSAVE'; -// import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; -// import LCS_IDX from './LCS_IDX'; +import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; +import LCS_IDX from './LCS_IDX'; import LCS_LEN from './LCS_LEN'; import LCS from './LCS'; import LINDEX from './LINDEX'; @@ -112,6 +112,7 @@ import LINSERT from './LINSERT'; import LLEN from './LLEN'; import LMOVE from './LMOVE'; import LMPOP from './LMPOP'; +import LOLWUT from './LOLWUT'; import LPOP_COUNT from './LPOP_COUNT'; import LPOP from './LPOP'; import LPOS_COUNT from './LPOS_COUNT'; @@ -122,7 +123,15 @@ import LRANGE from './LRANGE'; import LREM from './LREM'; import LSET from './LSET'; import LTRIM from './LTRIM'; +import MEMORY_DOCTOR from './MEMORY_DOCTOR'; +import MEMORY_MALLOC_STATS from './MEMORY_MALLOC-STATS'; +import MEMORY_PURGE from './MEMORY_PURGE'; +// import MEMORY_STATS from './MEMORY_STATS'; +import MEMORY_USAGE from './MEMORY_USAGE'; import MGET from './MGET'; +import MODULE_LIST from './MODULE_LIST'; +import MODULE_LOAD from './MODULE_LOAD'; +import MODULE_UNLOAD from './MODULE_UNLOAD'; import MOVE from './MOVE'; import MSET from './MSET'; import MSETNX from './MSETNX'; @@ -140,6 +149,11 @@ import PFMERGE from './PFMERGE'; import PING from './PING'; import PSETEX from './PSETEX'; import PTTL from './PTTL'; +import PUBLISH from './PUBLISH'; +import PUBSUB_CHANNELS from './PUBSUB_CHANNELS'; +import PUBSUB_NUMPAT from './PUBSUB_NUMPAT'; +import PUBSUB_NUMSUB from './PUBSUB_NUMSUB'; +import PUBSUB_SHARDCHANNELS from './PUBSUB_SHARDCHANNELS'; import RANDOMKEY from './RANDOMKEY'; import READONLY from './READONLY'; import RENAME from './RENAME'; @@ -443,8 +457,10 @@ export default { keys: KEYS, LASTSAVE, lastSave: LASTSAVE, - // LCS_IDX_WITHMATCHLEN, - // LCS_IDX, + LCS_IDX_WITHMATCHLEN, + lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN, + LCS_IDX, + lcsIdx: LCS_IDX, LCS_LEN, lcsLen: LCS_LEN, LCS, @@ -459,6 +475,7 @@ export default { lMove: LMOVE, LMPOP, lmPop: LMPOP, + LOLWUT, LPOP_COUNT, lPopCount: LPOP_COUNT, LPOP, @@ -479,8 +496,24 @@ export default { lSet: LSET, LTRIM, lTrim: LTRIM, + MEMORY_DOCTOR, + memoryDoctor: MEMORY_DOCTOR, + 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS, + memoryMallocStats: MEMORY_MALLOC_STATS, + MEMORY_PURGE, + memoryPurge: MEMORY_PURGE, + // MEMORY_STATS, + // memoryStats: MEMORY_STATS, + MEMORY_USAGE, + memoryUsage: MEMORY_USAGE, MGET, mGet: MGET, + MODULE_LIST, + moduleList: MODULE_LIST, + MODULE_LOAD, + moduleLoad: MODULE_LOAD, + MODULE_UNLOAD, + moduleUnload: MODULE_UNLOAD, MOVE, move: MOVE, MSET, @@ -518,6 +551,16 @@ export default { pSetEx: PSETEX, PTTL, pTTL: PTTL, + PUBLISH, + publish: PUBLISH, + PUBSUB_CHANNELS, + pubSubChannels: PUBSUB_CHANNELS, + PUBSUB_NUMPAT, + pubSubNumPat: PUBSUB_NUMPAT, + PUBSUB_NUMSUB, + pubSubNumSub: PUBSUB_NUMSUB, + PUBSUB_SHARDCHANNELS, + pubSubShardChannels: PUBSUB_SHARDCHANNELS, RANDOMKEY, randomKey: RANDOMKEY, READONLY, From dd5dd67bc113b863d30a276049c7b579b81b183e Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 14 May 2023 14:44:34 +0300 Subject: [PATCH 105/325] fix LCS IDX --- packages/client/lib/commands/LCS_IDX.spec.ts | 6 +++--- packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/client/lib/commands/LCS_IDX.spec.ts b/packages/client/lib/commands/LCS_IDX.spec.ts index 72d0f985b43..c948fa3eb6c 100644 --- a/packages/client/lib/commands/LCS_IDX.spec.ts +++ b/packages/client/lib/commands/LCS_IDX.spec.ts @@ -21,12 +21,12 @@ describe('LCS IDX', () => { client.lcsIdx('1', '2') ]); - console.log(reply); - assert.deepEqual( reply, { - matches: [[[1, 2], [0, 1]]], + matches: [ + [[1, 2], [0, 1]] + ], len: 2 } ); diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts index 80505ce38b1..96296be8b76 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts @@ -21,12 +21,15 @@ describe('LCS IDX WITHMATCHLEN', () => { client.lcsIdxWithMatchLen('1', '2') ]); + console.log(reply); + assert.deepEqual( reply, { matches: [ - [[[1, 2], [0, 1]]], - 2 + [ + [[1, 2], [0, 1], 2] + ], ], len: 2 } From cf5510f55b49caa32a824252be1e526e88877cd4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 14 May 2023 14:51:45 +0300 Subject: [PATCH 106/325] fix LCS IDX WITHMATCHLEN --- packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts index 96296be8b76..784ece8a616 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts @@ -21,15 +21,11 @@ describe('LCS IDX WITHMATCHLEN', () => { client.lcsIdxWithMatchLen('1', '2') ]); - console.log(reply); - assert.deepEqual( reply, { matches: [ - [ - [[1, 2], [0, 1], 2] - ], + [[1, 2], [0, 1], 2] ], len: 2 } From f8fa8878c3be821a749a3031b56a30247c89e50a Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 14 May 2023 14:54:09 +0300 Subject: [PATCH 107/325] fix some more --- docs/v4-to-v5.md | 6 +++++ packages/client/lib/commands/COPY.spec.ts | 2 +- packages/client/lib/commands/DBSIZE.spec.ts | 26 +++++++++---------- packages/client/lib/commands/EXPIRE.spec.ts | 2 +- packages/client/lib/commands/EXPIREAT.spec.ts | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 49a86086fd6..4519ebcb0ff 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -109,7 +109,13 @@ Some command arguments/replies have changed to align more closely to data types - `GEORADIUSBYMEMBERSTORE` -> `GEORADIUSBYMEMBER_STORE` - `XACK`: `boolean` -> `number` [^boolean-to-number] - `XADD`: the `INCR` option has been removed, use `XADD_INCR` instead +- `LASTSAVE`: `Date` -> `number` (unix timestamp) +- `HELLO`: `protover` moved from the options object to it's own argument, `auth` -> `AUTH`, `clientName` -> `SETNAME` +- `MODULE LIST`: `version` -> `ver` [^map-keys] +- `MEMORY STATS`: [^map-keys] [^enum-to-constants]: TODO [^boolean-to-number]: TODO + +[^map-keys]: [TODO](https://github.com/redis/node-redis/discussions/2506) \ No newline at end of file diff --git a/packages/client/lib/commands/COPY.spec.ts b/packages/client/lib/commands/COPY.spec.ts index 412d49db3a0..44649d3c783 100644 --- a/packages/client/lib/commands/COPY.spec.ts +++ b/packages/client/lib/commands/COPY.spec.ts @@ -45,7 +45,7 @@ describe('COPY', () => { testUtils.testAll('copy', async client => { assert.equal( await client.copy('{tag}source', '{tag}destination'), - false + 0 ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/DBSIZE.spec.ts b/packages/client/lib/commands/DBSIZE.spec.ts index a014a46e6e2..cb2d72aae79 100644 --- a/packages/client/lib/commands/DBSIZE.spec.ts +++ b/packages/client/lib/commands/DBSIZE.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DBSIZE'; +import DBSIZE from './DBSIZE'; describe('DBSIZE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['DBSIZE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DBSIZE.transformArguments(), + ['DBSIZE'] + ); + }); - testUtils.testWithClient('client.dbSize', async client => { - assert.equal( - await client.dbSize(), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.dbSize', async client => { + assert.equal( + await client.dbSize(), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/EXPIRE.spec.ts b/packages/client/lib/commands/EXPIRE.spec.ts index ff0ac667767..add2040eb31 100644 --- a/packages/client/lib/commands/EXPIRE.spec.ts +++ b/packages/client/lib/commands/EXPIRE.spec.ts @@ -22,7 +22,7 @@ describe('EXPIRE', () => { testUtils.testAll('expire', async client => { assert.equal( await client.expire('key', 0), - false + 0 ); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/EXPIREAT.spec.ts b/packages/client/lib/commands/EXPIREAT.spec.ts index 45677f8835d..730d925d998 100644 --- a/packages/client/lib/commands/EXPIREAT.spec.ts +++ b/packages/client/lib/commands/EXPIREAT.spec.ts @@ -30,7 +30,7 @@ describe('EXPIREAT', () => { testUtils.testAll('expireAt', async client => { assert.equal( await client.expireAt('key', 1), - false + 0 ); }, { client: GLOBAL.SERVERS.OPEN, From e3326134bac823f7f899fd8a1a8a3cb710a04ee6 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 15 May 2023 15:41:40 +0300 Subject: [PATCH 108/325] deprecate `QUIT` and `disconnect`, implement `close` and `destroy` --- docs/v4-to-v5.md | 6 +- packages/client/lib/client/commands-queue.ts | 7 +++ packages/client/lib/client/index.ts | 64 ++++++++++++++++---- packages/client/lib/client/socket.ts | 36 ++++++----- 4 files changed, 82 insertions(+), 31 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 4519ebcb0ff..c81e2b29e3d 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -41,9 +41,7 @@ To override just a specific option, use the following functions: The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection. -Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`. - -TODO difference between `close` and `disconnect`... +`client.QUIT/quit()` is replaced by `client.close()`. and, to avoid confusion, `client.disconnect()` has been renamed to `client.destroy()`. ## Scan Iterators @@ -62,7 +60,7 @@ const client = createClient(), // use `client` for the new API await client.set('key', 'value'); -// use `legacyClient` for the "legacy" callback API +// use `legacyClient` for the "legacy" API legacyClient.set('key', 'value', (err, reply) => { // ... }); diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 69ba57425a6..f8e351f6e2e 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -316,4 +316,11 @@ export default class RedisCommandsQueue { ); } } + + isEmpty() { + return ( + this._waitingToBeSent.length === 0 && + this._waitingForReply.length === 0 + ); + } } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index df736f3f600..6de3d53e522 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -657,16 +657,6 @@ export default class RedisClient< ); } - QUIT(): Promise { - return this._socket.quit(async () => { - const quitPromise = this._queue.addCommand(['QUIT']); - this._tick(); - return quitPromise; - }); - } - - quit = this.QUIT; - private _tick(force = false): void { if (this._socket.writableNeedDrain || (!force && !this._socket.isReady)) { return; @@ -674,12 +664,12 @@ export default class RedisClient< this._socket.cork(); - while (!this._socket.writableNeedDrain) { + do { const args = this._queue.getCommandToSend(); if (args === undefined) break; this._socket.writeCommand(args); - } + } while (!this._socket.writableNeedDrain); } private _addMultiCommands( @@ -782,9 +772,57 @@ export default class RedisClient< } while (cursor !== 0); } + /** + * @deprecated use .close instead + */ + QUIT(): Promise { + return this._socket.quit(async () => { + const quitPromise = this._queue.addCommand(['QUIT']); + this._tick(); + return quitPromise; + }); + } + + quit = this.QUIT; + + /** + * @deprecated use .destroy instead + */ disconnect() { + return Promise.resolve(this.destroy()); + } + + private _resolveClose?: () => unknown; + + /** + * Close the client. Wait for pending replies. + */ + close() { + return new Promise(resolve => { + this._socket.close(); + + if (this._queue.isEmpty()) { + this._socket.destroySocket(); + return resolve(); + } + + const maybeClose = () => { + if (!this._queue.isEmpty()) return; + + this._socket.off('data', maybeClose); + this._socket.destroySocket(); + resolve(); + }; + this._socket.on('data', maybeClose); + }); + } + + /** + * Destroy the client. Rejects all commands immediately. + */ + destroy() { this._queue.flushAll(new DisconnectsClientError()); - this._socket.disconnect(); + this._socket.destroy(); } ref() { diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index d0c1cfae896..a2683cc85e3 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -19,7 +19,7 @@ export interface RedisSocketCommonOptions { */ keepAlive?: number | false; /** - * When the socket closes unexpectedly (without calling `.quit()`/`.disconnect()`), the client uses `reconnectStrategy` to decide what to do. The following values are supported: + * When the socket closes unexpectedly (without calling `.close()`/`.destroy()`), the client uses `reconnectStrategy` to decide what to do. The following values are supported: * 1. `false` -> do not reconnect, close the client and flush the command queue. * 2. `number` -> wait for `X` milliseconds before reconnecting. * 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. @@ -250,35 +250,43 @@ export default class RedisSocket extends EventEmitter { } } - disconnect(): void { + async quit(fn: () => Promise): Promise { if (!this.#isOpen) { throw new ClientClosedError(); } this.#isOpen = false; - this.#disconnect(); + const reply = await fn(); + this.destroySocket(); + return reply; } - #disconnect(): void { - this.#isReady = false; - - if (this.#socket) { - this.#socket.destroy(); - this.#socket = undefined; + close() { + if (!this.#isOpen) { + throw new ClientClosedError(); } - this.emit('end'); + this.#isOpen = false; } - async quit(fn: () => Promise): Promise { + destroy() { if (!this.#isOpen) { throw new ClientClosedError(); } this.#isOpen = false; - const reply = await fn(); - this.#disconnect(); - return reply; + this.destroySocket(); + } + + destroySocket() { + this.#isReady = false; + + if (this.#socket) { + this.#socket.destroy(); + this.#socket = undefined; + } + + this.emit('end'); } #isCorked = false; From e27693f13f76b318a587d0193674cf3342e69269 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 15 May 2023 16:56:48 +0300 Subject: [PATCH 109/325] cluster close & destroy --- packages/client/lib/cluster/cluster-slots.ts | 56 ++++++++++++++------ packages/client/lib/cluster/index.ts | 22 ++++++-- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index e94ad52002d..0b445042b5a 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -259,7 +259,7 @@ export default class RedisClusterSlots< // switch to `CLUSTER SHARDS` when Redis 7.0 will be the minimum supported version return await client.clusterSlots(); } finally { - await client.disconnect(); + client.destroy(); } } @@ -377,41 +377,67 @@ export default class RedisClusterSlots< return this._discoverWithRootNodes(); } + /** + * @deprecated Use `close` instead. + */ quit(): Promise { return this._destroy(client => client.quit()); } + /** + * @deprecated Use `destroy` instead. + */ disconnect(): Promise { return this._destroy(client => client.disconnect()); } - private async _destroy(fn: (client: RedisClientType) => Promise): Promise { + close() { + return this._destroy(client => client.close()); + } + + destroy() { this._isOpen = false; - const promises = []; + for (const client of this._clients()) { + this._execOnNodeClient(client, client => client.destroy()); + } + + if (this.pubSubNode) { + this._execOnNodeClient(this.pubSubNode.client, client => client.destroy()); + this.pubSubNode = undefined; + } + + this._resetSlots(); + this.nodeByAddress.clear(); + } + + private *_clients() { for (const { master, replicas } of this.shards) { if (master.client) { - promises.push( - this._execOnNodeClient(master.client, fn) - ); + yield master.client; } if (master.pubSubClient) { - promises.push( - this._execOnNodeClient(master.pubSubClient, fn) - ); + yield master.pubSubClient; } if (replicas) { for (const { client } of replicas) { if (client) { - promises.push( - this._execOnNodeClient(client, fn) - ); + yield client; } } } } + } + + private async _destroy(fn: (client: RedisClientType) => Promise): Promise { + this._isOpen = false; + + const promises = []; + for (const client of this._clients()) { + promises.push(this._execOnNodeClient(client, fn)); + } if (this.pubSubNode) { promises.push(this._execOnNodeClient(this.pubSubNode.client, fn)); @@ -424,10 +450,10 @@ export default class RedisClusterSlots< await Promise.allSettled(promises); } - private _execOnNodeClient( + private _execOnNodeClient( client: ClientOrPromise, - fn: (client: RedisClientType) => Promise - ) { + fn: (client: RedisClientType) => T + ): T | Promise { return types.isPromise(client) ? client.then(fn) : fn(client); diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 96560fdaf05..abec4cb7f3b 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -503,14 +503,28 @@ export default class RedisCluster< sUnsubscribe = this.SUNSUBSCRIBE; - // quit(): Promise { - // return this.#slots.quit(); - // } + /** + * @deprecated Use `close` instead. + */ + quit() { + return this._slots.quit(); + } - disconnect(): Promise { + /** + * @deprecated Use `destroy` instead. + */ + disconnect() { return this._slots.disconnect(); } + close() { + return this._slots.close(); + } + + destroy() { + return this._slots.destroy(); + } + nodeClient(node: ShardNode) { return this._slots.nodeClient(node); } From 322f6446de668f558736dd6afb659977b7920803 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 21 May 2023 13:45:18 +0300 Subject: [PATCH 110/325] ref #2498 - replace yallist with custom made linked list --- packages/client/lib/client/commands-queue.ts | 34 +++---- packages/client/lib/client/queue.spec.ts | 77 ++++++++++++++ packages/client/lib/client/queue.ts | 101 +++++++++++++++++++ 3 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 packages/client/lib/client/queue.spec.ts create mode 100644 packages/client/lib/client/queue.ts diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index f8e351f6e2e..5ec181d78b6 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,4 +1,4 @@ -import * as LinkedList from 'yallist'; +import Queue, { QueueNode } from './queue'; import encodeCommand from '../RESP/encoder'; import { Decoder, PUSH_FLAGS, RESP_TYPES } from '../RESP/decoder'; import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; @@ -37,8 +37,8 @@ const RESP2_PUSH_FLAGS = { export default class RedisCommandsQueue { private readonly _maxLength: number | null | undefined; - private readonly _waitingToBeSent = new LinkedList(); - private readonly _waitingForReply = new LinkedList(); + private readonly _waitingToBeSent = new Queue(); + private readonly _waitingForReply = new Queue(); private readonly _onShardedChannelMoved: OnShardedChannelMoved; private readonly _pubSub = new PubSub(); @@ -154,30 +154,30 @@ export default class RedisCommandsQueue { } return new Promise((resolve, reject) => { - const node = new LinkedList.Node({ + let node: QueueNode; + const value: CommandWaitingToBeSent = { args, chainId: options?.chainId, flags: options?.flags, resolve, - reject - }); + reject, + removeAbortListener: undefined + }; - if (options?.signal) { + const signal = options?.signal; + if (signal) { const listener = () => { - this._waitingToBeSent.removeNode(node); - node.value.reject(new AbortError()); + this._waitingToBeSent.remove(node); + value.reject(new AbortError()); }; - node.value.removeAbortListener = () => options.signal?.removeEventListener('abort', listener); - - options.signal.addEventListener('abort', listener, { once: true }); + value.removeAbortListener = () => signal.removeEventListener('abort', listener); + signal.addEventListener('abort', listener, { once: true }); } - if (options?.asap) { - this._waitingToBeSent.unshiftNode(node); - } else { - this._waitingToBeSent.pushNode(node); - } + node = options?.asap ? + this._waitingToBeSent.unshift(value) : + this._waitingToBeSent.push(value); }); } diff --git a/packages/client/lib/client/queue.spec.ts b/packages/client/lib/client/queue.spec.ts new file mode 100644 index 00000000000..139dc8f8905 --- /dev/null +++ b/packages/client/lib/client/queue.spec.ts @@ -0,0 +1,77 @@ +import Queue from './queue'; +import { equal, deepEqual } from 'assert/strict'; + +describe.only('Queue', () => { + const queue = new Queue(); + + it('should start empty', () => { + equal(queue.length, 0); + deepEqual(Array.from(queue), []); + }); + + it('shift empty', () => { + equal(queue.shift(), null); + equal(queue.length, 0); + deepEqual(Array.from(queue), []); + }); + + it('push 1', () => { + queue.push(1); + equal(queue.length, 1); + deepEqual(Array.from(queue), [1]); + }); + + it('push 2', () => { + queue.push(2); + equal(queue.length, 2); + deepEqual(Array.from(queue), [1, 2]); + }); + + it('unshift 0', () => { + queue.unshift(0); + equal(queue.length, 3); + deepEqual(Array.from(queue), [0, 1, 2]); + }); + + it('remove middle node', () => { + queue.remove(queue.head.next!); + equal(queue.length, 2); + deepEqual(Array.from(queue), [0, 2]); + }); + + it('remove head', () => { + queue.remove(queue.head); + equal(queue.length, 1); + deepEqual(Array.from(queue), [2]); + }); + + it('remove tail', () => { + queue.remove(queue.tail); + equal(queue.length, 0); + deepEqual(Array.from(queue), []); + }); + + it('unshift empty queue', () => { + queue.unshift(0); + equal(queue.length, 1); + deepEqual(Array.from(queue), [0]); + }); + + it('push 1', () => { + queue.push(1); + equal(queue.length, 2); + deepEqual(Array.from(queue), [0, 1]); + }); + + it('shift', () => { + equal(queue.shift(), 0); + equal(queue.length, 1); + deepEqual(Array.from(queue), [1]); + }); + + it('shift last element', () => { + equal(queue.shift(), 1); + equal(queue.length, 0); + deepEqual(Array.from(queue), []); + }); +}); diff --git a/packages/client/lib/client/queue.ts b/packages/client/lib/client/queue.ts new file mode 100644 index 00000000000..20a1fe5c9a0 --- /dev/null +++ b/packages/client/lib/client/queue.ts @@ -0,0 +1,101 @@ +export interface QueueNode { + value: T; + previous: QueueNode | null; + next: QueueNode | null; +} + +export default class Queue { + #length = 0; + + get length() { + return this.#length; + } + + #head: QueueNode | null = null; + + get head() { + return this.#head; + } + + #tail: QueueNode | null = null; + + get tail() { + return this.#tail; + } + + push(value: T) { + ++this.#length; + + if (!this.#tail) { + return this.#tail = this.#head = { + previous: this.#head, + next: null, + value + }; + } + + return this.#tail = this.#tail.next = { + previous: this.#tail, + next: null, + value + }; + } + + unshift(value: T) { + ++this.#length; + + if (!this.#head) { + return this.#head = this.#tail = { + previous: null, + next: null, + value + }; + } + + return this.#head = this.#head.previous = { + previous: null, + next: this.#head, + value + }; + } + + shift() { + if (!this.#head) return null; + + --this.#length; + const node = this.#head; + if (node.next) { + node.next.previous = node.previous; + this.#head = node.next; + node.next = null; + } else { + this.#head = this.#tail = null; + } + return node.value; + } + + remove(node: QueueNode) { + --this.#length; + + if (this.#tail === node) { + this.#tail = node.previous; + } + + if (this.#head === node) { + this.#head = node.next; + } else { + node.previous!.next = node.next; + node.previous = null; + } + + node.next = null; + } + + *[Symbol.iterator]() { + let node = this.#head; + while (node !== null) { + yield node.value; + node = node.next; + } + } +} From 15908097c6fdbb1aab82d636909e195615473a1f Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 21 May 2023 13:46:43 +0300 Subject: [PATCH 111/325] replace # with private to improve performance --- packages/client/lib/client/queue.ts | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/client/lib/client/queue.ts b/packages/client/lib/client/queue.ts index 20a1fe5c9a0..5a213ce2bd7 100644 --- a/packages/client/lib/client/queue.ts +++ b/packages/client/lib/client/queue.ts @@ -5,84 +5,84 @@ export interface QueueNode { } export default class Queue { - #length = 0; + private _length = 0; get length() { - return this.#length; + return this._length; } - #head: QueueNode | null = null; + private _head: QueueNode | null = null; get head() { - return this.#head; + return this._head; } - #tail: QueueNode | null = null; + _tail: QueueNode | null = null; get tail() { - return this.#tail; + return this._tail; } push(value: T) { - ++this.#length; + ++this._length; - if (!this.#tail) { - return this.#tail = this.#head = { - previous: this.#head, + if (!this._tail) { + return this._tail = this._head = { + previous: this._head, next: null, value }; } - return this.#tail = this.#tail.next = { - previous: this.#tail, + return this._tail = this._tail.next = { + previous: this._tail, next: null, value }; } unshift(value: T) { - ++this.#length; + ++this._length; - if (!this.#head) { - return this.#head = this.#tail = { + if (!this._head) { + return this._head = this._tail = { previous: null, next: null, value }; } - return this.#head = this.#head.previous = { + return this._head = this._head.previous = { previous: null, - next: this.#head, + next: this._head, value }; } shift() { - if (!this.#head) return null; + if (!this._head) return null; - --this.#length; - const node = this.#head; + --this._length; + const node = this._head; if (node.next) { node.next.previous = node.previous; - this.#head = node.next; + this._head = node.next; node.next = null; } else { - this.#head = this.#tail = null; + this._head = this._tail = null; } return node.value; } remove(node: QueueNode) { - --this.#length; + --this._length; - if (this.#tail === node) { - this.#tail = node.previous; + if (this._tail === node) { + this._tail = node.previous; } - if (this.#head === node) { - this.#head = node.next; + if (this._head === node) { + this._head = node.next; } else { node.previous!.next = node.next; node.previous = null; @@ -92,7 +92,7 @@ export default class Queue { } *[Symbol.iterator]() { - let node = this.#head; + let node = this._head; while (node !== null) { yield node.value; node = node.next; From 0e89c667c97b2dddabf14839316189127accc759 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 21 May 2023 15:47:47 +0300 Subject: [PATCH 112/325] remove .only, fix some errors --- packages/client/lib/client/queue.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/queue.spec.ts b/packages/client/lib/client/queue.spec.ts index 139dc8f8905..39691c83d9f 100644 --- a/packages/client/lib/client/queue.spec.ts +++ b/packages/client/lib/client/queue.spec.ts @@ -1,7 +1,7 @@ import Queue from './queue'; import { equal, deepEqual } from 'assert/strict'; -describe.only('Queue', () => { +describe('Queue', () => { const queue = new Queue(); it('should start empty', () => { From dc094eaa9a6b66df66423796e42b68edb4b05336 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 24 May 2023 13:59:53 +0300 Subject: [PATCH 113/325] WIP --- packages/client/lib/RESP/decoder.ts | 1 + packages/client/lib/RESP/encoder.ts | 2 +- packages/client/lib/client/commands-queue.ts | 67 +++++--- packages/client/lib/client/index.ts | 36 ++-- .../client/lib/client/linked-list.spec.ts | 138 +++++++++++++++ packages/client/lib/client/linked-list.ts | 162 ++++++++++++++++++ packages/client/lib/client/pub-sub.ts | 2 +- packages/client/lib/client/queue.spec.ts | 77 --------- packages/client/lib/client/queue.ts | 101 ----------- packages/client/lib/client/socket.ts | 156 ++++++++--------- packages/client/lib/commands/CLUSTER_MYID.ts | 2 +- 11 files changed, 441 insertions(+), 303 deletions(-) create mode 100644 packages/client/lib/client/linked-list.spec.ts create mode 100644 packages/client/lib/client/linked-list.ts delete mode 100644 packages/client/lib/client/queue.spec.ts delete mode 100644 packages/client/lib/client/queue.ts diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 2a0a30b474b..98cd7bcdc81 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -555,6 +555,7 @@ export class Decoder { this, length - slice.length, chunks, + skip, flag ); } diff --git a/packages/client/lib/RESP/encoder.ts b/packages/client/lib/RESP/encoder.ts index b1db1c70237..af857711dc3 100644 --- a/packages/client/lib/RESP/encoder.ts +++ b/packages/client/lib/RESP/encoder.ts @@ -1,4 +1,4 @@ -import { RedisArgument } from "./types"; +import { RedisArgument } from './types'; const CRLF = '\r\n'; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 5ec181d78b6..55efe68080a 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,4 +1,4 @@ -import Queue, { QueueNode } from './queue'; +import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list'; import encodeCommand from '../RESP/encoder'; import { Decoder, PUSH_FLAGS, RESP_TYPES } from '../RESP/decoder'; import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; @@ -7,16 +7,19 @@ import { AbortError, ErrorReply } from '../errors'; import { EventEmitter } from 'stream'; export interface QueueCommandOptions { - asap?: boolean; chainId?: symbol; - signal?: AbortSignal; + asap?: boolean; + abortSignal?: AbortSignal; flags?: Flags; } export interface CommandWaitingToBeSent extends CommandWaitingForReply { args: CommandArguments; chainId?: symbol; - removeAbortListener?(): void; + abort?: { + signal: AbortSignal; + listener: () => unknown; + }; } interface CommandWaitingForReply { @@ -37,8 +40,8 @@ const RESP2_PUSH_FLAGS = { export default class RedisCommandsQueue { private readonly _maxLength: number | null | undefined; - private readonly _waitingToBeSent = new Queue(); - private readonly _waitingForReply = new Queue(); + private readonly _waitingToBeSent = new DoublyLinkedList(); + private readonly _waitingForReply = new SinglyLinkedList(); private readonly _onShardedChannelMoved: OnShardedChannelMoved; private readonly _pubSub = new PubSub(); @@ -149,30 +152,31 @@ export default class RedisCommandsQueue { addCommand(args: CommandArguments, options?: QueueCommandOptions): Promise { if (this._maxLength && this._waitingToBeSent.length + this._waitingForReply.length >= this._maxLength) { return Promise.reject(new Error('The queue is full')); - } else if (options?.signal?.aborted) { + } else if (options?.abortSignal?.aborted) { return Promise.reject(new AbortError()); } return new Promise((resolve, reject) => { - let node: QueueNode; + let node: DoublyLinkedNode; const value: CommandWaitingToBeSent = { args, chainId: options?.chainId, flags: options?.flags, resolve, reject, - removeAbortListener: undefined + abort: undefined }; - const signal = options?.signal; + const signal = options?.abortSignal; if (signal) { - const listener = () => { - this._waitingToBeSent.remove(node); - value.reject(new AbortError()); + value.abort = { + signal, + listener: () => { + this._waitingToBeSent.remove(node); + value.reject(new AbortError()); + } }; - - value.removeAbortListener = () => signal.removeEventListener('abort', listener); - signal.addEventListener('abort', listener, { once: true }); + signal.addEventListener('abort', value.abort.listener, { once: true }); } node = options?.asap ? @@ -264,13 +268,15 @@ export default class RedisCommandsQueue { return; } - // TODO - // reuse `toSend` - (toSend.args as any) = undefined; - if (toSend.removeAbortListener) { - toSend.removeAbortListener(); - (toSend.removeAbortListener as any) = undefined; + if (toSend.abort) { + RedisCommandsQueue._removeAbortListener(toSend); + toSend.abort = undefined; } + + // TODO reuse `toSend` or create new object? + (toSend as any).args = undefined; + (toSend as any).chainId = undefined; + this._waitingForReply.push(toSend); this._chainInExecution = toSend.chainId; return encoded; @@ -282,9 +288,16 @@ export default class RedisCommandsQueue { } } - static #flushWaitingToBeSent(command: CommandWaitingToBeSent, err: Error) { - command.removeAbortListener?.(); - command.reject(err); + private static _removeAbortListener(command: CommandWaitingToBeSent) { + command.abort!.signal.removeEventListener('abort', command.abort!.listener); + } + + private static _flushWaitingToBeSent(toBeSent: CommandWaitingToBeSent, err: Error) { + if (toBeSent.abort) { + RedisCommandsQueue._removeAbortListener(toBeSent); + } + + toBeSent.reject(err); } flushWaitingForReply(err: Error): void { @@ -296,7 +309,7 @@ export default class RedisCommandsQueue { if (!this._chainInExecution) return; while (this._waitingToBeSent.head?.value.chainId === this._chainInExecution) { - RedisCommandsQueue.#flushWaitingToBeSent( + RedisCommandsQueue._flushWaitingToBeSent( this._waitingToBeSent.shift()!, err ); @@ -310,7 +323,7 @@ export default class RedisCommandsQueue { this._pubSub.reset(); this.#flushWaitingForReply(err); while (this._waitingToBeSent.head) { - RedisCommandsQueue.#flushWaitingToBeSent( + RedisCommandsQueue._flushWaitingToBeSent( this._waitingToBeSent.shift()!, err ); diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 6de3d53e522..c098eb7208f 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -137,22 +137,22 @@ export default class RedisClient< > extends EventEmitter { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return async function (this: ProxyClient) { - const args = command.transformArguments.apply(undefined, arguments as any), - reply = await this.sendCommand(args, this.commandOptions); + return async function (this: ProxyClient, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this.sendCommand(redisArgs, this.commandOptions); return transformReply ? - transformReply(reply, args.preserve) : + transformReply(reply, redisArgs.preserve) : reply; }; } private static _createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return async function (this: NamespaceProxyClient) { - const args = command.transformArguments.apply(undefined, arguments as any), - reply = await this.self.sendCommand(args, this.self.commandOptions); + return async function (this: NamespaceProxyClient, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this.self.sendCommand(redisArgs, this.self.commandOptions); return transformReply ? - transformReply(reply, args.preserve) : + transformReply(reply, redisArgs.preserve) : reply; }; } @@ -160,8 +160,8 @@ export default class RedisClient< private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); - return async function (this: NamespaceProxyClient) { - const fnArgs = fn.transformArguments.apply(undefined, arguments as any), + return async function (this: NamespaceProxyClient, ...args: Array) { + const fnArgs = fn.transformArguments(...args), reply = await this.self.sendCommand( prefix.concat(fnArgs), this.self.commandOptions @@ -175,15 +175,15 @@ export default class RedisClient< private static _createScriptCommand(script: RedisScript, resp: RespVersions) { const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); - return async function (this: ProxyClient) { - const scriptArgs = script.transformArguments.apply(undefined, arguments as any), - args = prefix.concat(scriptArgs), - reply = await this.sendCommand(args, this.commandOptions).catch((err: unknown) => { + return async function (this: ProxyClient, ...args: Array) { + const scriptArgs = script.transformArguments(...args), + redisArgs = prefix.concat(scriptArgs), + reply = await this.sendCommand(redisArgs, this.commandOptions).catch((err: unknown) => { if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; args[0] = 'EVAL'; args[1] = script.SCRIPT; - return this.sendCommand(args, this.commandOptions); + return this.sendCommand(redisArgs, this.commandOptions); }); return transformReply ? transformReply(reply, scriptArgs.preserve) : @@ -470,6 +470,10 @@ export default class RedisClient< return this._commandOptionsProxy('flags', flags); } + withAbortSignal(abortSignal: AbortSignal) { + return this._commandOptionsProxy('abortSignal', abortSignal); + } + /** * Override the `asap` command option to `true` */ @@ -792,8 +796,6 @@ export default class RedisClient< return Promise.resolve(this.destroy()); } - private _resolveClose?: () => unknown; - /** * Close the client. Wait for pending replies. */ diff --git a/packages/client/lib/client/linked-list.spec.ts b/packages/client/lib/client/linked-list.spec.ts new file mode 100644 index 00000000000..c5ab379b82d --- /dev/null +++ b/packages/client/lib/client/linked-list.spec.ts @@ -0,0 +1,138 @@ +import { SinglyLinkedList, DoublyLinkedList } from './linked-list'; +import { equal, deepEqual } from 'assert/strict'; + +describe.only('DoublyLinkedList', () => { + const list = new DoublyLinkedList(); + + it('should start empty', () => { + equal(list.length, 0); + equal(list.head, undefined); + equal(list.tail, undefined); + deepEqual(Array.from(list), []); + }); + + it('shift empty', () => { + equal(list.shift(), undefined); + equal(list.length, 0); + deepEqual(Array.from(list), []); + }); + + it('push 1', () => { + list.push(1); + equal(list.length, 1); + deepEqual(Array.from(list), [1]); + }); + + it('push 2', () => { + list.push(2); + equal(list.length, 2); + deepEqual(Array.from(list), [1, 2]); + }); + + it('unshift 0', () => { + list.unshift(0); + equal(list.length, 3); + deepEqual(Array.from(list), [0, 1, 2]); + }); + + it('remove middle node', () => { + list.remove(list.head!.next!); + equal(list.length, 2); + deepEqual(Array.from(list), [0, 2]); + }); + + it('remove head', () => { + list.remove(list.head!); + equal(list.length, 1); + deepEqual(Array.from(list), [2]); + }); + + it('remove tail', () => { + list.remove(list.tail!); + equal(list.length, 0); + deepEqual(Array.from(list), []); + }); + + it('unshift empty queue', () => { + list.unshift(0); + equal(list.length, 1); + deepEqual(Array.from(list), [0]); + }); + + it('push 1', () => { + list.push(1); + equal(list.length, 2); + deepEqual(Array.from(list), [0, 1]); + }); + + it('shift', () => { + equal(list.shift(), 0); + equal(list.length, 1); + deepEqual(Array.from(list), [1]); + }); + + it('shift last element', () => { + equal(list.shift(), 1); + equal(list.length, 0); + deepEqual(Array.from(list), []); + }); +}); + +describe.only('SinglyLinkedList', () => { + const list = new SinglyLinkedList(); + + it('should start empty', () => { + equal(list.length, 0); + equal(list.head, undefined); + equal(list.tail, undefined); + deepEqual(Array.from(list), []); + }); + + it('shift empty', () => { + equal(list.shift(), undefined); + equal(list.length, 0); + deepEqual(Array.from(list), []); + }); + + it('push 1', () => { + list.push(1); + equal(list.length, 1); + deepEqual(Array.from(list), [1]); + }); + + it('push 2', () => { + list.push(2); + equal(list.length, 2); + deepEqual(Array.from(list), [1, 2]); + }); + + it('push 3', () => { + list.push(3); + equal(list.length, 3); + deepEqual(Array.from(list), [1, 2, 3]); + }); + + it('shift 1', () => { + equal(list.shift(), 1); + equal(list.length, 2); + deepEqual(Array.from(list), [2, 3]); + }); + + it('shift 2', () => { + equal(list.shift(), 2); + equal(list.length, 1); + deepEqual(Array.from(list), [3]); + }); + + it('shift 3', () => { + equal(list.shift(), 3); + equal(list.length, 0); + deepEqual(Array.from(list), []); + }); + + it('should be empty', () => { + equal(list.length, 0); + equal(list.head, undefined); + equal(list.tail, undefined); + }); +}); diff --git a/packages/client/lib/client/linked-list.ts b/packages/client/lib/client/linked-list.ts new file mode 100644 index 00000000000..ec59e672242 --- /dev/null +++ b/packages/client/lib/client/linked-list.ts @@ -0,0 +1,162 @@ +export interface DoublyLinkedNode { + value: T; + previous: DoublyLinkedNode | undefined; + next: DoublyLinkedNode | undefined; +} + +export class DoublyLinkedList { + private _length = 0; + + get length() { + return this._length; + } + + private _head?: DoublyLinkedNode; + + get head() { + return this._head; + } + + private _tail?: DoublyLinkedNode; + + get tail() { + return this._tail; + } + + push(value: T) { + ++this._length; + + if (this._tail === undefined) { + return this._tail = this._head = { + previous: this._head, + next: undefined, + value + }; + } + + return this._tail = this._tail.next = { + previous: this._tail, + next: undefined, + value + }; + } + + unshift(value: T) { + ++this._length; + + if (this._head === undefined) { + return this._head = this._tail = { + previous: undefined, + next: undefined, + value + }; + } + + return this._head = this._head.previous = { + previous: undefined, + next: this._head, + value + }; + } + + shift() { + if (this._head === undefined) return undefined; + + --this._length; + const node = this._head; + if (node.next) { + node.next.previous = node.previous; + this._head = node.next; + node.next = undefined; + } else { + this._head = this._tail = undefined; + } + return node.value; + } + + remove(node: DoublyLinkedNode) { + --this._length; + + if (this._tail === node) { + this._tail = node.previous; + } + + if (this._head === node) { + this._head = node.next; + } else { + node.previous!.next = node.next; + node.previous = undefined; + } + + node.next = undefined; + } + + *[Symbol.iterator]() { + let node = this._head; + while (node !== undefined) { + yield node.value; + node = node.next; + } + } +} + +export interface SinglyLinkedNode { + value: T; + next: SinglyLinkedNode | undefined; +} + +export class SinglyLinkedList { + private _length = 0; + + get length() { + return this._length; + } + + private _head?: SinglyLinkedNode; + + get head() { + return this._head; + } + + private _tail?: SinglyLinkedNode; + + get tail() { + return this._tail; + } + + push(value: T) { + ++this._length; + + const node = { + value, + next: undefined + }; + + if (this._head === undefined) { + this._head = this._tail = node; + } else { + this._tail!.next = this._tail = node; + } + } + + shift() { + if (this._head === undefined) return undefined; + + const node = this._head; + if (--this._length === 0) { + this._head = this._tail = undefined; + } else { + this._head = node.next; + } + + return node.value; + } + + *[Symbol.iterator]() { + let node = this._head; + while (node !== undefined) { + yield node.value; + node = node.next; + } + } +} diff --git a/packages/client/lib/client/pub-sub.ts b/packages/client/lib/client/pub-sub.ts index afa7972e831..91c771a57e7 100644 --- a/packages/client/lib/client/pub-sub.ts +++ b/packages/client/lib/client/pub-sub.ts @@ -1,4 +1,4 @@ -import { RedisArgument } from "../RESP/types"; +import { RedisArgument } from '../RESP/types'; export enum PubSubType { CHANNELS = 'CHANNELS', diff --git a/packages/client/lib/client/queue.spec.ts b/packages/client/lib/client/queue.spec.ts deleted file mode 100644 index 39691c83d9f..00000000000 --- a/packages/client/lib/client/queue.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import Queue from './queue'; -import { equal, deepEqual } from 'assert/strict'; - -describe('Queue', () => { - const queue = new Queue(); - - it('should start empty', () => { - equal(queue.length, 0); - deepEqual(Array.from(queue), []); - }); - - it('shift empty', () => { - equal(queue.shift(), null); - equal(queue.length, 0); - deepEqual(Array.from(queue), []); - }); - - it('push 1', () => { - queue.push(1); - equal(queue.length, 1); - deepEqual(Array.from(queue), [1]); - }); - - it('push 2', () => { - queue.push(2); - equal(queue.length, 2); - deepEqual(Array.from(queue), [1, 2]); - }); - - it('unshift 0', () => { - queue.unshift(0); - equal(queue.length, 3); - deepEqual(Array.from(queue), [0, 1, 2]); - }); - - it('remove middle node', () => { - queue.remove(queue.head.next!); - equal(queue.length, 2); - deepEqual(Array.from(queue), [0, 2]); - }); - - it('remove head', () => { - queue.remove(queue.head); - equal(queue.length, 1); - deepEqual(Array.from(queue), [2]); - }); - - it('remove tail', () => { - queue.remove(queue.tail); - equal(queue.length, 0); - deepEqual(Array.from(queue), []); - }); - - it('unshift empty queue', () => { - queue.unshift(0); - equal(queue.length, 1); - deepEqual(Array.from(queue), [0]); - }); - - it('push 1', () => { - queue.push(1); - equal(queue.length, 2); - deepEqual(Array.from(queue), [0, 1]); - }); - - it('shift', () => { - equal(queue.shift(), 0); - equal(queue.length, 1); - deepEqual(Array.from(queue), [1]); - }); - - it('shift last element', () => { - equal(queue.shift(), 1); - equal(queue.length, 0); - deepEqual(Array.from(queue), []); - }); -}); diff --git a/packages/client/lib/client/queue.ts b/packages/client/lib/client/queue.ts deleted file mode 100644 index 5a213ce2bd7..00000000000 --- a/packages/client/lib/client/queue.ts +++ /dev/null @@ -1,101 +0,0 @@ -export interface QueueNode { - value: T; - previous: QueueNode | null; - next: QueueNode | null; -} - -export default class Queue { - private _length = 0; - - get length() { - return this._length; - } - - private _head: QueueNode | null = null; - - get head() { - return this._head; - } - - _tail: QueueNode | null = null; - - get tail() { - return this._tail; - } - - push(value: T) { - ++this._length; - - if (!this._tail) { - return this._tail = this._head = { - previous: this._head, - next: null, - value - }; - } - - return this._tail = this._tail.next = { - previous: this._tail, - next: null, - value - }; - } - - unshift(value: T) { - ++this._length; - - if (!this._head) { - return this._head = this._tail = { - previous: null, - next: null, - value - }; - } - - return this._head = this._head.previous = { - previous: null, - next: this._head, - value - }; - } - - shift() { - if (!this._head) return null; - - --this._length; - const node = this._head; - if (node.next) { - node.next.previous = node.previous; - this._head = node.next; - node.next = null; - } else { - this._head = this._tail = null; - } - return node.value; - } - - remove(node: QueueNode) { - --this._length; - - if (this._tail === node) { - this._tail = node.previous; - } - - if (this._head === node) { - this._head = node.next; - } else { - node.previous!.next = node.next; - node.previous = null; - } - - node.next = null; - } - - *[Symbol.iterator]() { - let node = this._head; - while (node !== null) { - yield node.value; - node = node.next; - } - } -} diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index a2683cc85e3..a7f3d77dd61 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -64,49 +64,49 @@ export default class RedisSocket extends EventEmitter { return (options as RedisTlsSocketOptions).tls === true; } - readonly #initiator: RedisSocketInitiator; + private readonly _initiator: RedisSocketInitiator; - readonly #options: RedisSocketOptions; + private readonly _options: RedisSocketOptions; - #socket?: net.Socket | tls.TLSSocket; + private _socket?: net.Socket | tls.TLSSocket; - #isOpen = false; + private _isOpen = false; get isOpen(): boolean { - return this.#isOpen; + return this._isOpen; } - #isReady = false; + private _isReady = false; get isReady(): boolean { - return this.#isReady; + return this._isReady; } // `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used // https://nodejs.org/api/stream.html#stream_writable_writableneeddrain - #writableNeedDrain = false; + private _writableNeedDrain = false; get writableNeedDrain(): boolean { - return this.#writableNeedDrain; + return this._writableNeedDrain; } - #isSocketUnrefed = false; + private _isSocketUnrefed = false; constructor(initiator: RedisSocketInitiator, options?: RedisSocketOptions) { super(); - this.#initiator = initiator; - this.#options = RedisSocket.#initiateOptions(options); + this._initiator = initiator; + this._options = RedisSocket.#initiateOptions(options); } - #reconnectStrategy(retries: number, cause: Error) { - if (this.#options.reconnectStrategy === false) { + private _reconnectStrategy(retries: number, cause: Error) { + if (this._options.reconnectStrategy === false) { return false; - } else if (typeof this.#options.reconnectStrategy === 'number') { - return this.#options.reconnectStrategy; - } else if (this.#options.reconnectStrategy) { + } else if (typeof this._options.reconnectStrategy === 'number') { + return this._options.reconnectStrategy; + } else if (this._options.reconnectStrategy) { try { - const retryIn = this.#options.reconnectStrategy(retries, cause); + const retryIn = this._options.reconnectStrategy(retries, cause); if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); } @@ -120,14 +120,14 @@ export default class RedisSocket extends EventEmitter { return Math.min(retries * 50, 500); } - #shouldReconnect(retries: number, cause: Error) { - const retryIn = this.#reconnectStrategy(retries, cause); + private _shouldReconnect(retries: number, cause: Error) { + const retryIn = this._reconnectStrategy(retries, cause); if (retryIn === false) { - this.#isOpen = false; + this._isOpen = false; this.emit('error', cause); return cause; } else if (retryIn instanceof Error) { - this.#isOpen = false; + this._isOpen = false; this.emit('error', cause); return new ReconnectStrategyError(retryIn, cause); } @@ -136,33 +136,33 @@ export default class RedisSocket extends EventEmitter { } async connect(): Promise { - if (this.#isOpen) { + if (this._isOpen) { throw new Error('Socket already opened'); } - this.#isOpen = true; - return this.#connect(); + this._isOpen = true; + return this._connect(); } - async #connect(): Promise { + private async _connect(): Promise { let retries = 0; do { try { - this.#socket = await this.#createSocket(); - this.#writableNeedDrain = false; + this._socket = await this._createSocket(); + this._writableNeedDrain = false; this.emit('connect'); try { - await this.#initiator(); + await this._initiator(); } catch (err) { - this.#socket.destroy(); - this.#socket = undefined; + this._socket.destroy(); + this._socket = undefined; throw err; } - this.#isReady = true; + this._isReady = true; this.emit('ready'); } catch (err) { - const retryIn = this.#shouldReconnect(retries++, err as Error); + const retryIn = this._shouldReconnect(retries++, err as Error); if (typeof retryIn !== 'number') { throw retryIn; } @@ -171,40 +171,40 @@ export default class RedisSocket extends EventEmitter { await promiseTimeout(retryIn); this.emit('reconnecting'); } - } while (this.#isOpen && !this.#isReady); + } while (this._isOpen && !this._isReady); } - #createSocket(): Promise { + private _createSocket(): Promise { return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? - this.#createTlsSocket() : - this.#createNetSocket(); + const { connectEvent, socket } = RedisSocket.#isTlsSocket(this._options) ? + this._createTlsSocket() : + this._createNetSocket(); - if (this.#options.connectTimeout) { - socket.setTimeout(this.#options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); + if (this._options.connectTimeout) { + socket.setTimeout(this._options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); } - if (this.#isSocketUnrefed) { + if (this._isSocketUnrefed) { socket.unref(); } socket - .setNoDelay(this.#options.noDelay) + .setNoDelay(this._options.noDelay) .once('error', reject) .once(connectEvent, () => { socket .setTimeout(0) // https://github.com/nodejs/node/issues/31663 - .setKeepAlive(this.#options.keepAlive !== false, this.#options.keepAlive || 0) + .setKeepAlive(this._options.keepAlive !== false, this._options.keepAlive || 0) .off('error', reject) - .once('error', (err: Error) => this.#onSocketError(err)) + .once('error', (err: Error) => this._onSocketError(err)) .once('close', hadError => { - if (!hadError && this.#isOpen && this.#socket === socket) { - this.#onSocketError(new SocketClosedUnexpectedlyError()); + if (!hadError && this._isOpen && this._socket === socket) { + this._onSocketError(new SocketClosedUnexpectedlyError()); } }) .on('drain', () => { - this.#writableNeedDrain = false; + this._writableNeedDrain = false; this.emit('drain'); }) .on('data', data => this.emit('data', data)); @@ -214,104 +214,104 @@ export default class RedisSocket extends EventEmitter { }); } - #createNetSocket(): CreateSocketReturn { + private _createNetSocket(): CreateSocketReturn { return { connectEvent: 'connect', - socket: net.connect(this.#options as net.NetConnectOpts) // TODO + socket: net.connect(this._options as net.NetConnectOpts) // TODO }; } - #createTlsSocket(): CreateSocketReturn { + private _createTlsSocket(): CreateSocketReturn { return { connectEvent: 'secureConnect', - socket: tls.connect(this.#options as tls.ConnectionOptions) // TODO + socket: tls.connect(this._options as tls.ConnectionOptions) // TODO }; } - #onSocketError(err: Error): void { - this.#isReady = false; + private _onSocketError(err: Error): void { + this._isReady = false; this.emit('error', err); - if (!this.#isOpen || typeof this.#shouldReconnect(0, err) !== 'number') return; + if (!this._isOpen || typeof this._shouldReconnect(0, err) !== 'number') return; this.emit('reconnecting'); - this.#connect().catch(() => { + this._connect().catch(() => { // the error was already emitted, silently ignore it }); } writeCommand(args: Array): void { - if (!this.#socket) { + if (!this._socket) { throw new ClientClosedError(); } for (const toWrite of args) { - this.#writableNeedDrain = !this.#socket.write(toWrite); + this._writableNeedDrain = !this._socket.write(toWrite); } } async quit(fn: () => Promise): Promise { - if (!this.#isOpen) { + if (!this._isOpen) { throw new ClientClosedError(); } - this.#isOpen = false; + this._isOpen = false; const reply = await fn(); this.destroySocket(); return reply; } close() { - if (!this.#isOpen) { + if (!this._isOpen) { throw new ClientClosedError(); } - this.#isOpen = false; + this._isOpen = false; } destroy() { - if (!this.#isOpen) { + if (!this._isOpen) { throw new ClientClosedError(); } - this.#isOpen = false; + this._isOpen = false; this.destroySocket(); } destroySocket() { - this.#isReady = false; + this._isReady = false; - if (this.#socket) { - this.#socket.destroy(); - this.#socket = undefined; + if (this._socket) { + this._socket.destroy(); + this._socket = undefined; } this.emit('end'); } - #isCorked = false; + private _isCorked = false; cork(): void { - if (!this.#socket || this.#isCorked) { + if (!this._socket || this._isCorked) { return; } - this.#socket.cork(); - this.#isCorked = true; + this._socket.cork(); + this._isCorked = true; - queueMicrotask(() => { - this.#socket?.uncork(); - this.#isCorked = false; + setImmediate(() => { + this._socket?.uncork(); + this._isCorked = false; }); } ref(): void { - this.#isSocketUnrefed = false; - this.#socket?.ref(); + this._isSocketUnrefed = false; + this._socket?.ref(); } unref(): void { - this.#isSocketUnrefed = true; - this.#socket?.unref(); + this._isSocketUnrefed = true; + this._socket?.unref(); } } diff --git a/packages/client/lib/commands/CLUSTER_MYID.ts b/packages/client/lib/commands/CLUSTER_MYID.ts index a7a4184f9c4..6c682ddccf8 100644 --- a/packages/client/lib/commands/CLUSTER_MYID.ts +++ b/packages/client/lib/commands/CLUSTER_MYID.ts @@ -1,4 +1,4 @@ -import { BlobStringReply, Command } from "../RESP/types"; +import { BlobStringReply, Command } from '../RESP/types'; export default { transformArguments() { From 2fa33dbbac77d43a837a38cbeac1c2ea0034ee76 Mon Sep 17 00:00:00 2001 From: Leibale Date: Sun, 28 May 2023 16:50:48 +0300 Subject: [PATCH 114/325] legacy mode multi --- packages/client/lib/client/index.ts | 65 +++++++++++---- packages/client/lib/client/legacy-mode.ts | 83 +++++++++++++++++-- .../client/lib/client/linked-list.spec.ts | 4 +- packages/client/lib/client/multi-command.ts | 74 +++-------------- packages/client/lib/multi-command.ts | 16 +--- 5 files changed, 136 insertions(+), 106 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index c098eb7208f..debfcec163f 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -689,38 +689,71 @@ export default class RedisClient< ); } - MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, FLAGS> { - return new (this as any).Multi( - async ( + /** + * @internal + */ + async executePipeline(commands: Array) { + if (!this._socket.isOpen) { + return Promise.reject(new ClientClosedError()); + } + + const promise = Promise.all( + commands.map(({ args }) => this._queue.addCommand(args, { + flags: (this as ProxyClient).commandOptions?.flags + })) + ); + this._tick(); + return promise; + } + + /** + * @internal + */ + async executeMulti( commands: Array, - selectedDB?: number, - chainId?: symbol - ) => { + selectedDB?: number + ) { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); } const flags = (this as ProxyClient).commandOptions?.flags, - promise = chainId ? - // if `chainId` has a value, it's a `MULTI` (and not "pipeline") - need to add the `MULTI` and `EXEC` commands - Promise.all([ + chainId = Symbol('MULTI Chain'), + promises = [ this._queue.addCommand(['MULTI'], { chainId }), - this._addMultiCommands(commands, chainId), - this._queue.addCommand(['EXEC'], { chainId, flags }) - ]) : - this._addMultiCommands(commands, undefined, flags); + ]; + + for (const { args } of commands) { + promises.push( + this._queue.addCommand(args, { + chainId, + flags + }) + ); + } + + promises.push( + this._queue.addCommand(['EXEC'], { chainId }) + ); this._tick(); - const results = await promise; + const results = await Promise.all(promises), + execResult = results[results.length - 1]; + + if (execResult === null) { + throw new WatchError(); + } if (selectedDB !== undefined) { this._selectedDB = selectedDB; } - return results; + return execResult as Array; } - ); + + MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, FLAGS> { + return new (this as any).Multi(this); } multi = this.MULTI; diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index c189c85342d..87de34bd7e1 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -3,6 +3,7 @@ import { RedisClientType } from '.'; import { getTransformReply } from '../commander'; import { ErrorReply } from '../errors'; import COMMANDS from '../commands'; +import RedisMultiCommand from '../multi-command'; type LegacyArgument = string | Buffer | number | Date; @@ -15,10 +16,8 @@ type LegacyCommandArguments = LegacyArguments | [ callback: LegacyCallback ]; -export type CommandSignature = (...args: LegacyCommandArguments) => void; - type WithCommands = { - [P in keyof typeof COMMANDS]: CommandSignature; + [P in keyof typeof COMMANDS]: (...args: LegacyCommandArguments) => void; }; export type RedisLegacyClientType = RedisLegacyClient & WithCommands; @@ -30,16 +29,16 @@ export class RedisLegacyClient { callback = args.pop() as LegacyCallback; } - RedisLegacyClient._pushArguments(redisArgs, args as LegacyArguments); + RedisLegacyClient.pushArguments(redisArgs, args as LegacyArguments); return callback; } - private static _pushArguments(redisArgs: CommandArguments, args: LegacyArguments) { + static pushArguments(redisArgs: CommandArguments, args: LegacyArguments) { for (let i = 0; i < args.length; ++i) { const arg = args[i]; if (Array.isArray(arg)) { - RedisLegacyClient._pushArguments(redisArgs, arg); + RedisLegacyClient.pushArguments(redisArgs, arg); } else { redisArgs.push( typeof arg === 'number' || arg instanceof Date ? @@ -50,14 +49,14 @@ export class RedisLegacyClient { } } - private static _getTransformReply(command: Command, resp: RespVersions) { + static getTransformReply(command: Command, resp: RespVersions) { return command.TRANSFORM_LEGACY_REPLY ? getTransformReply(command, resp) : undefined; } private static _createCommand(name: string, command: Command, resp: RespVersions) { - const transformReply = RedisLegacyClient._getTransformReply(command, resp); + const transformReply = RedisLegacyClient.getTransformReply(command, resp); return async function (this: RedisLegacyClient, ...args: LegacyCommandArguments) { const redisArgs = [name], callback = RedisLegacyClient._transformArguments(redisArgs, args), @@ -74,6 +73,8 @@ export class RedisLegacyClient { }; } + private _Multi: ReturnType; + constructor( private _client: RedisClientType ) { @@ -87,7 +88,7 @@ export class RedisLegacyClient { ); } - // TODO: Multi + this._Multi = LegacyMultiCommand.factory(RESP); } sendCommand(...args: LegacyArguments) { @@ -104,4 +105,68 @@ export class RedisLegacyClient { .then(reply => callback(null, reply)) .catch(err => callback(err)); } + + multi() { + return this._Multi(this._client); + } +} + +type MultiWithCommands = { + [P in keyof typeof COMMANDS]: (...args: LegacyCommandArguments) => RedisLegacyMultiType; +}; + +export type RedisLegacyMultiType = Omit & MultiWithCommands; + +class LegacyMultiCommand extends RedisMultiCommand { + private static _createCommand(name: string, command: Command, resp: RespVersions) { + const transformReply = RedisLegacyClient.getTransformReply(command, resp); + return function (this: LegacyMultiCommand, ...args: LegacyArguments) { + const redisArgs = [name]; + RedisLegacyClient.pushArguments(redisArgs, args); + return this.addCommand(redisArgs, transformReply); + }; + } + + static factory(resp: RespVersions) { + const Multi = class extends LegacyMultiCommand {}; + + for (const [name, command] of Object.entries(COMMANDS)) { + // TODO: as any? + (Multi as any).prototype[name] = LegacyMultiCommand._createCommand( + name, + command, + resp + ); + } + + return (client: RedisClientType) => { + return new Multi(client) as unknown as RedisLegacyMultiType; + }; + } + + private _client: RedisClientType; + + constructor(client: RedisClientType) { + super(); + this._client = client; + } + + sendCommand(...args: LegacyArguments) { + const redisArgs: CommandArguments = []; + RedisLegacyClient.pushArguments(redisArgs, args); + return this.addCommand(redisArgs); + } + + exec(cb?: (err: ErrorReply | null, replies?: Array) => unknown) { + const promise = this._client.executeMulti(this.queue); + + if (!cb) { + promise.catch(err => this._client.emit('error', err)); + return; + } + + promise + .then(results => cb(null, this.transformReplies(results))) + .catch(err => cb?.(err)); + } } diff --git a/packages/client/lib/client/linked-list.spec.ts b/packages/client/lib/client/linked-list.spec.ts index c5ab379b82d..9547fb81c7c 100644 --- a/packages/client/lib/client/linked-list.spec.ts +++ b/packages/client/lib/client/linked-list.spec.ts @@ -1,7 +1,7 @@ import { SinglyLinkedList, DoublyLinkedList } from './linked-list'; import { equal, deepEqual } from 'assert/strict'; -describe.only('DoublyLinkedList', () => { +describe('DoublyLinkedList', () => { const list = new DoublyLinkedList(); it('should start empty', () => { @@ -78,7 +78,7 @@ describe.only('DoublyLinkedList', () => { }); }); -describe.only('SinglyLinkedList', () => { +describe('SinglyLinkedList', () => { const list = new SinglyLinkedList(); it('should start empty', () => { diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 3503a34af2b..90a5c7ccf9c 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -2,6 +2,7 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; +import { RedisClientType } from '.'; type CommandSignature< REPLIES extends Array, @@ -90,7 +91,7 @@ type MULTI_REPLY = { type MultiReply = MULTI_REPLY[keyof MULTI_REPLY]; -type ReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; +type ReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; export type RedisClientMultiExecutor = ( queue: Array, @@ -161,62 +162,14 @@ export default class RedisClientMultiCommand extends RedisMultiCom }); } - // readonly #multi = new RedisMultiCommand(); - readonly #executor: RedisClientMultiExecutor; - // readonly v4: Record = {}; + readonly #client: RedisClientType; #selectedDB?: number; - constructor(executor: RedisClientMultiExecutor, legacyMode = false) { + constructor(client: RedisClientType) { super(); - this.#executor = executor; - // if (legacyMode) { - // this.#legacyMode(); - // } + this.#client = client; } - // #legacyMode(): void { - // this.v4.addCommand = this.addCommand.bind(this); - // (this as any).addCommand = (...args: Array): this => { - // this.#multi.addCommand(transformLegacyCommandArguments(args)); - // return this; - // }; - // this.v4.exec = this.exec.bind(this); - // (this as any).exec = (callback?: (err: Error | null, replies?: Array) => unknown): void => { - // this.v4.exec() - // .then((reply: Array) => { - // if (!callback) return; - - // callback(null, reply); - // }) - // .catch((err: Error) => { - // if (!callback) { - // // this.emit('error', err); - // return; - // } - - // callback(err); - // }); - // }; - - // for (const [name, command] of Object.entries(COMMANDS as RedisCommands)) { - // this.#defineLegacyCommand(name, command); - // (this as any)[name.toLowerCase()] ??= (this as any)[name]; - // } - // } - - // #defineLegacyCommand(this: any, name: string, command?: RedisCommand): void { - // this.v4[name] = this[name].bind(this.v4); - // this[name] = command && command.TRANSFORM_LEGACY_REPLY && command.transformReply ? - // (...args: Array) => { - // this.#multi.addCommand( - // [name, ...transformLegacyCommandArguments(args)], - // command.transformReply - // ); - // return this; - // } : - // (...args: Array) => this.addCommand(name, ...args); - // } - SELECT(db: number, transformReply?: TransformReply): this { this.#selectedDB = db; return this.addCommand(['SELECT', db.toString()], transformReply); @@ -224,15 +177,11 @@ export default class RedisClientMultiCommand extends RedisMultiCom select = this.SELECT; - async exec(execAsPipeline = false) { + async exec(execAsPipeline = false): Promise> { if (execAsPipeline) return this.execAsPipeline(); - return this.handleExecReplies( - await this.#executor( - this.queue, - this.#selectedDB, - RedisMultiCommand.generateChainId() - ) + return this.transformReplies( + await this.#client.executeMulti(this.queue, this.#selectedDB) ) as ReplyType; } @@ -242,14 +191,11 @@ export default class RedisClientMultiCommand extends RedisMultiCom return this.exec(execAsPipeline); } - async execAsPipeline() { + async execAsPipeline(): Promise> { if (this.queue.length === 0) return [] as ReplyType; return this.transformReplies( - await this.#executor( - this.queue, - this.#selectedDB - ) + await this.#client.executePipeline(this.queue) ) as ReplyType; } diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 2c3f7f7ee7b..65570ff33aa 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -1,5 +1,4 @@ -import { Command, CommandArguments, RedisScript, TransformReply } from './RESP/types'; -import { WatchError } from './errors'; +import { CommandArguments, RedisScript, TransformReply } from './RESP/types'; export interface RedisMultiQueuedCommand { args: CommandArguments; @@ -7,10 +6,6 @@ export interface RedisMultiQueuedCommand { } export default class RedisMultiCommand { - static generateChainId(): symbol { - return Symbol('RedisMultiCommand Chain Id'); - } - readonly queue: Array = []; readonly scriptsInUse = new Set(); @@ -42,15 +37,6 @@ export default class RedisMultiCommand { return this.addCommand(redisArgs, transformReply); } - handleExecReplies(rawReplies: Array): Array { - const execReply = rawReplies[rawReplies.length - 1] as (null | Array); - if (execReply === null) { - throw new WatchError(); - } - - return this.transformReplies(execReply); - } - transformReplies(rawReplies: Array): Array { return rawReplies.map((reply, i) => { const { transformReply, args } = this.queue[i]; From fcb3a011b5ce16de22003af67f2711e25b0c40ff Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 30 May 2023 19:23:14 +0300 Subject: [PATCH 115/325] cluster multi --- docs/v4-to-v5.md | 7 + packages/client/lib/client/index.ts | 4 +- packages/client/lib/client/multi-command.ts | 97 ++--- packages/client/lib/cluster/index.ts | 117 +++--- packages/client/lib/cluster/multi-command.ts | 386 ++++++++++++------- packages/client/lib/multi-command.ts | 13 +- 6 files changed, 373 insertions(+), 251 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index c81e2b29e3d..332bd12dcf5 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -71,6 +71,13 @@ legacyClient.set('key', 'value', (err, reply) => { TODO The `isolationPool` has been moved to it's on class `ClientPool`. You can create pool from a client using `client.createPool()`. +## Cluster MULTI + +Cluster MULTI supports readonly/replicas +`cluster.multi.addCommand` now requires `isReadonly` as the second argument, to match `cluster.sendCommand` + +TODO + ## Commands Some command arguments/replies have changed to align more closely to data types returned by Redis: diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index debfcec163f..e9b6c4e2bf7 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -3,7 +3,7 @@ import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket import RedisCommandsQueue, { QueueCommandOptions } from './commands-queue'; import { EventEmitter } from 'events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; -import { ClientClosedError, ClientOfflineError, DisconnectsClientError } from '../errors'; +import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchError } from '../errors'; import { URL } from 'url'; import { TcpSocketConnectOpts } from 'net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; @@ -692,7 +692,7 @@ export default class RedisClient< /** * @internal */ - async executePipeline(commands: Array) { + executePipeline(commands: Array) { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); } diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 90a5c7ccf9c..b011a08916f 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,5 +1,5 @@ import COMMANDS from '../commands'; -import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; +import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import { RedisClientType } from '.'; @@ -84,64 +84,50 @@ export type RedisClientMultiCommandType< WithScripts ); -type MULTI_REPLY = { - GENERIC: 'generic'; - TYPED: 'typed'; -}; - -type MultiReply = MULTI_REPLY[keyof MULTI_REPLY]; - -type ReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; - -export type RedisClientMultiExecutor = ( - queue: Array, - selectedDB?: number, - chainId?: symbol -) => Promise>; - -export default class RedisClientMultiCommand extends RedisMultiCommand { - static #createCommand(command: Command, resp: RespVersions) { +export default class RedisClientMultiCommand { + private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return function (this: RedisClientMultiCommand) { - return this.addCommand( - command.transformArguments.apply(undefined, arguments as any), + return function (this: RedisClientMultiCommand, ...args: Array) { + return this._multi.addCommand( + command.transformArguments(...args), transformReply ); }; } - static #createModuleCommand(command: Command, resp: RespVersions) { + private static _createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return function (this: { self: RedisClientMultiCommand }) { - return this.self.addCommand( - command.transformArguments.apply(undefined, arguments as any), + return function (this: { self: RedisClientMultiCommand }, ...args: Array) { + return this.self._multi.addCommand( + command.transformArguments(...args), transformReply ); }; } - static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); - return function (this: { self: RedisClientMultiCommand }) { - const fnArgs = fn.transformArguments.apply(undefined, arguments as any), - args: CommandArguments = prefix.concat(fnArgs); - args.preserve = fnArgs.preserve; - return this.self.addCommand( - args, + return function (this: { self: RedisClientMultiCommand }, ...args: Array) { + const fnArgs = fn.transformArguments(...args), + redisArgs: CommandArguments = prefix.concat(fnArgs); + redisArgs.preserve = fnArgs.preserve; + return this.self._multi.addCommand( + redisArgs, transformReply ); }; } - static #createScriptCommand(script: RedisScript, resp: RespVersions) { + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { const transformReply = getTransformReply(script, resp); - return function (this: RedisClientMultiCommand) { - return this.addScript( + return function (this: RedisClientMultiCommand, ...args: Array) { + this._multi.addScript( script, - script.transformArguments.apply(undefined, arguments as any), + script.transformArguments(...args), transformReply ); + return this; }; } @@ -154,35 +140,36 @@ export default class RedisClientMultiCommand extends RedisMultiCom return attachConfig({ BaseClass: RedisClientMultiCommand, commands: COMMANDS, - createCommand: RedisClientMultiCommand.#createCommand, - createModuleCommand: RedisClientMultiCommand.#createModuleCommand, - createFunctionCommand: RedisClientMultiCommand.#createFunctionCommand, - createScriptCommand: RedisClientMultiCommand.#createScriptCommand, + createCommand: RedisClientMultiCommand._createCommand, + createModuleCommand: RedisClientMultiCommand._createModuleCommand, + createFunctionCommand: RedisClientMultiCommand._createFunctionCommand, + createScriptCommand: RedisClientMultiCommand._createScriptCommand, config }); } - readonly #client: RedisClientType; - #selectedDB?: number; + private readonly _multi = new RedisMultiCommand(); + private readonly _client: RedisClientType; + private _selectedDB?: number; constructor(client: RedisClientType) { - super(); - this.#client = client; + this._client = client; } SELECT(db: number, transformReply?: TransformReply): this { - this.#selectedDB = db; - return this.addCommand(['SELECT', db.toString()], transformReply); + this._selectedDB = db; + this._multi.addCommand(['SELECT', db.toString()], transformReply); + return this; } select = this.SELECT; - async exec(execAsPipeline = false): Promise> { + async exec(execAsPipeline = false): Promise> { if (execAsPipeline) return this.execAsPipeline(); - return this.transformReplies( - await this.#client.executeMulti(this.queue, this.#selectedDB) - ) as ReplyType; + return this._multi.transformReplies( + await this._client.executeMulti(this._multi.queue, this._selectedDB) + ) as MultiReplyType; } EXEC = this.exec; @@ -191,12 +178,12 @@ export default class RedisClientMultiCommand extends RedisMultiCom return this.exec(execAsPipeline); } - async execAsPipeline(): Promise> { - if (this.queue.length === 0) return [] as ReplyType; + async execAsPipeline(): Promise> { + if (this._multi.queue.length === 0) return [] as MultiReplyType; - return this.transformReplies( - await this.#client.executePipeline(this.queue) - ) as ReplyType; + return this._multi.transformReplies( + await this._client.executePipeline(this._multi.queue) + ) as MultiReplyType; } execAsPipelineTyped() { diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index abec4cb7f3b..8fb5564cd03 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,11 +1,11 @@ -import { ClientCommandOptions, RedisClientOptions, RedisClientType } from '../client'; -import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandSignature, CommandWithPoliciesSignature, Flags, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, TransformReply } from '../RESP/types'; +import { ClientCommandOptions, RedisClientOptions } from '../client'; +import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, Flags, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; import { EventEmitter } from 'events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; -// import RedisClusterMultiCommand, { InstantiableRedisClusterMultiCommandType, RedisClusterMultiCommandType } from './multi-command'; -// import { RedisMultiQueuedCommand } from '../multi-command'; +import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command'; +import { RedisMultiQueuedCommand } from '../multi-command'; import { PubSubListener } from '../client/pub-sub'; import { ErrorReply } from '../errors'; @@ -85,7 +85,7 @@ export default class RedisCluster< FLAGS extends Flags, POLICIES extends CommandPolicies > extends EventEmitter { - private static _extractFirstKey( + static extractFirstKey( command: C, args: Parameters, redisArgs: Array @@ -101,46 +101,46 @@ export default class RedisCluster< private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return async function (this: ProxyCluster) { - const args = command.transformArguments.apply(undefined, arguments as any), - firstKey = RedisCluster._extractFirstKey( + return async function (this: ProxyCluster, ...args: Array) { + const redisArgs = command.transformArguments(...args), + firstKey = RedisCluster.extractFirstKey( command, - arguments as any, - args + args, + redisArgs ), reply = await this.sendCommand( firstKey, command.IS_READ_ONLY, - args, + redisArgs, this.commandOptions, command.POLICIES ); return transformReply ? - transformReply(reply, args.preserve) : + transformReply(reply, redisArgs.preserve) : reply; }; } private static _createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return async function (this: NamespaceProxyCluster) { - const args = command.transformArguments.apply(undefined, arguments as any), - firstKey = RedisCluster._extractFirstKey( + return async function (this: NamespaceProxyCluster, ...args: Array) { + const redisArgs = command.transformArguments(...args), + firstKey = RedisCluster.extractFirstKey( command, - arguments as any, - args + args, + redisArgs ), reply = await this.self.sendCommand( firstKey, command.IS_READ_ONLY, - args, + redisArgs, this.self.commandOptions, command.POLICIES ); return transformReply ? - transformReply(reply, args.preserve) : + transformReply(reply, redisArgs.preserve) : reply; }; } @@ -148,18 +148,18 @@ export default class RedisCluster< private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); - return async function (this: NamespaceProxyCluster) { - const fnArgs = fn.transformArguments.apply(undefined, arguments as any), - args = prefix.concat(fnArgs), - firstKey = RedisCluster._extractFirstKey( + return async function (this: NamespaceProxyCluster, ...args: Array) { + const fnArgs = fn.transformArguments(...args), + redisArgs = prefix.concat(fnArgs), + firstKey = RedisCluster.extractFirstKey( fn, - arguments as any, - args + fnArgs, + redisArgs ), reply = await this.self.sendCommand( firstKey, fn.IS_READ_ONLY, - args, + redisArgs, this.self.commandOptions, fn.POLICIES ); @@ -173,18 +173,18 @@ export default class RedisCluster< private static _createScriptCommand(script: RedisScript, resp: RespVersions) { const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); - return async function (this: ProxyCluster) { - const scriptArgs = script.transformArguments.apply(undefined, arguments as any), - args = prefix.concat(scriptArgs), - firstKey = RedisCluster._extractFirstKey( + return async function (this: ProxyCluster, ...args: Array) { + const scriptArgs = script.transformArguments(...args), + redisArgs = prefix.concat(scriptArgs), + firstKey = RedisCluster.extractFirstKey( script, - arguments as any, - args + scriptArgs, + redisArgs ), reply = await this.sendCommand( firstKey, script.IS_READ_ONLY, - args, + redisArgs, this.commandOptions, script.POLICIES ); @@ -211,7 +211,7 @@ export default class RedisCluster< config }); - // Client.prototype.Multi = RedisClientMultiCommand.extend(config); + Cluster.prototype.Multi = RedisClusterMultiCommand.extend(config); return (options?: Omit>) => { // returning a proxy of the client to prevent the namespaces.self to leak between proxies @@ -280,8 +280,6 @@ export default class RedisCluster< return this._slots.pubSubNode; } - // readonly #Multi: InstantiableRedisClusterMultiCommandType; - get isOpen() { return this._slots.isOpen; } @@ -291,7 +289,6 @@ export default class RedisCluster< this._options = options; this._slots = new RedisClusterSlots(options, this.emit.bind(this)); - // this.#Multi = RedisClusterMultiCommand.extend(options); } duplicate(overrides?: Partial>): RedisClusterType { @@ -400,20 +397,38 @@ export default class RedisCluster< } } - // MULTI(routing?: RedisCommandArgument): RedisClusterMultiCommandType { - // return new this.#Multi( - // (commands: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => { - // return this.#execute( - // firstKey, - // false, - // client => client.multiExecutor(commands, undefined, chainId) - // ); - // }, - // routing - // ); - // } - - // multi = this.MULTI; + /** + * @internal + */ + async executePipeline( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + commands: Array + ) { + const client = await this._slots.getClient(firstKey, isReadonly); + return client.executePipeline(commands); + } + + /** + * @internal + */ + async executeMulti( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + commands: Array + ) { + const client = await this._slots.getClient(firstKey, isReadonly); + return client.executeMulti(commands); + } + + MULTI(routing?: RedisArgument): RedisClusterMultiCommandType<[], M, F, S, RESP, FLAGS> { + return new (this as any).Multi( + this, + routing + ); + } + + multi = this.MULTI; async SUBSCRIBE( channels: string | Array, diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index 379af544af1..4ec8e0996dd 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,141 +1,245 @@ -// import COMMANDS from './commands'; -// import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, ExcludeMappedString, RedisFunction } from '../commands'; -// import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -// import { attachCommands, attachExtensions } from '../commander'; -// import RedisCluster from '.'; - -// type RedisClusterMultiCommandSignature< -// C extends RedisCommand, -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = (...args: Parameters) => RedisClusterMultiCommandType; - -// type WithCommands< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = { -// [P in keyof typeof COMMANDS]: RedisClusterMultiCommandSignature<(typeof COMMANDS)[P], M, F, S>; -// }; - -// type WithModules< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = { -// [P in keyof M as ExcludeMappedString

]: { -// [C in keyof M[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; -// }; -// }; - -// type WithFunctions< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = { -// [P in keyof F as ExcludeMappedString

]: { -// [FF in keyof F[P] as ExcludeMappedString]: RedisClusterMultiCommandSignature; -// }; -// }; - -// type WithScripts< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = { -// [P in keyof S as ExcludeMappedString

]: RedisClusterMultiCommandSignature; -// }; - -// export type RedisClusterMultiCommandType< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = RedisClusterMultiCommand & WithCommands & WithModules & WithFunctions & WithScripts; - -// export type InstantiableRedisClusterMultiCommandType< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// > = new (...args: ConstructorParameters) => RedisClusterMultiCommandType; - -// export type RedisClusterMultiExecutor = (queue: Array, firstKey?: RedisCommandArgument, chainId?: symbol) => Promise>; - -// export default class RedisClusterMultiCommand { -// readonly #multi = new RedisMultiCommand(); -// readonly #executor: RedisClusterMultiExecutor; -// #firstKey: RedisCommandArgument | undefined; - -// static extend< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// >(extensions?: RedisExtensions): InstantiableRedisClusterMultiCommandType { -// return attachExtensions({ -// BaseClass: RedisClusterMultiCommand, -// modulesExecutor: RedisClusterMultiCommand.prototype.commandsExecutor, -// modules: extensions?.modules, -// functionsExecutor: RedisClusterMultiCommand.prototype.functionsExecutor, -// functions: extensions?.functions, -// scriptsExecutor: RedisClusterMultiCommand.prototype.scriptsExecutor, -// scripts: extensions?.scripts -// }); -// } - -// constructor(executor: RedisClusterMultiExecutor, firstKey?: RedisCommandArgument) { -// this.#executor = executor; -// this.#firstKey = firstKey; -// } - -// commandsExecutor(command: RedisCommand, args: Array): this { -// const transformedArguments = command.transformArguments(...args); -// this.#firstKey ??= RedisCluster.extractFirstKey(command, args, transformedArguments); -// return this.addCommand(undefined, transformedArguments, command.transformReply); -// } - -// addCommand( -// firstKey: RedisCommandArgument | undefined, -// args: RedisCommandArguments, -// transformReply?: RedisCommand['transformReply'] -// ): this { -// this.#firstKey ??= firstKey; -// this.#multi.addCommand(args, transformReply); -// return this; -// } - -// functionsExecutor(fn: RedisFunction, args: Array, name: string): this { -// const transformedArguments = this.#multi.addFunction(name, fn, args); -// this.#firstKey ??= RedisCluster.extractFirstKey(fn, args, transformedArguments); -// return this; -// } - -// scriptsExecutor(script: RedisScript, args: Array): this { -// const transformedArguments = this.#multi.addScript(script, args); -// this.#firstKey ??= RedisCluster.extractFirstKey(script, args, transformedArguments); -// return this; -// } - -// async exec(execAsPipeline = false): Promise> { -// if (execAsPipeline) { -// return this.execAsPipeline(); -// } - -// return this.#multi.handleExecReplies( -// await this.#executor(this.#multi.queue, this.#firstKey, RedisMultiCommand.generateChainId()) -// ); -// } - -// EXEC = this.exec; - -// async execAsPipeline(): Promise> { -// return this.#multi.transformReplies( -// await this.#executor(this.#multi.queue, this.#firstKey) -// ); -// } -// } - -// attachCommands({ -// BaseClass: RedisClusterMultiCommand, -// commands: COMMANDS, -// executor: RedisClusterMultiCommand.prototype.commandsExecutor -// }); +import COMMANDS from '../commands'; +import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; +import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion, RedisArgument } from '../RESP/types'; +import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; +import RedisCluster, { RedisClusterType } from '.'; + +type CommandSignature< + REPLIES extends Array, + C extends Command, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = (...args: Parameters) => RedisClusterMultiCommandType< + [...REPLIES, ReplyWithFlags, FLAGS>], + M, + F, + S, + RESP, + FLAGS +>; + +type WithCommands< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof typeof COMMANDS]: CommandSignature; +}; + +type WithModules< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; +}; + +type WithFunctions< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; +}; + +type WithScripts< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = { + [P in keyof S]: CommandSignature; +}; + +export type RedisClusterMultiCommandType< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + FLAGS extends Flags +> = ( + RedisClusterMultiCommand & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); + +export default class RedisClusterMultiCommand { + private static _createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: RedisClusterMultiCommand, ...args: Array) { + const redisArgs = command.transformArguments(...args), + firstKey = RedisCluster.extractFirstKey( + command, + args, + redisArgs + ); + return this.addCommand( + firstKey, + command.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: { self: RedisClusterMultiCommand }, ...args: Array) { + const redisArgs = command.transformArguments(...args), + firstKey = RedisCluster.extractFirstKey( + command, + args, + redisArgs + ); + return this.self.addCommand( + firstKey, + command.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return function (this: { self: RedisClusterMultiCommand }, ...args: Array) { + const fnArgs = fn.transformArguments(...args), + redisArgs: CommandArguments = prefix.concat(fnArgs), + firstKey = RedisCluster.extractFirstKey( + fn, + args, + fnArgs + ); + redisArgs.preserve = fnArgs.preserve; + return this.self.addCommand( + firstKey, + fn.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + const transformReply = getTransformReply(script, resp); + return function (this: RedisClusterMultiCommand, ...args: Array) { + const scriptArgs = script.transformArguments(...args); + this._setState( + RedisCluster.extractFirstKey( + script, + args, + scriptArgs + ), + script.IS_READ_ONLY + ); + this._multi.addScript( + script, + scriptArgs, + transformReply + ); + return this; + }; + } + + static extend< + M extends RedisModules = Record, + F extends RedisFunctions = Record, + S extends RedisScripts = Record, + RESP extends RespVersions = 2 + >(config?: CommanderConfig) { + return attachConfig({ + BaseClass: RedisClusterMultiCommand, + commands: COMMANDS, + createCommand: RedisClusterMultiCommand._createCommand, + createModuleCommand: RedisClusterMultiCommand._createModuleCommand, + createFunctionCommand: RedisClusterMultiCommand._createFunctionCommand, + createScriptCommand: RedisClusterMultiCommand._createScriptCommand, + config + }); + } + + private readonly _multi = new RedisMultiCommand(); + private readonly _cluster: RedisClusterType; + private _firstKey: RedisArgument | undefined; + private _isReadonly: boolean | undefined = true; + + constructor(cluster: RedisClusterType, routing: RedisArgument | undefined) { + this._cluster = cluster; + this._firstKey = routing; + } + + private _setState( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + ) { + this._firstKey ??= firstKey; + this._isReadonly &&= isReadonly; + } + + addCommand( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + args: CommandArguments, + transformReply?: TransformReply + ) { + this._setState(firstKey, isReadonly); + this._multi.addCommand(args, transformReply); + return this; + } + + async exec(execAsPipeline = false) { + if (execAsPipeline) return this.execAsPipeline(); + + return this._multi.transformReplies( + await this._cluster.executeMulti( + this._firstKey, + this._isReadonly, + this._multi.queue + ) + ) as MultiReplyType; + } + + EXEC = this.exec; + + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); + } + + async execAsPipeline() { + if (this._multi.queue.length === 0) return [] as MultiReplyType; + + return this._multi.transformReplies( + await this._cluster.executePipeline( + this._firstKey, + this._isReadonly, + this._multi.queue + ) + ) as MultiReplyType; + } + + execAsPipelineTyped() { + return this.execAsPipeline(); + } +} diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 65570ff33aa..19bb680d687 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -1,5 +1,15 @@ import { CommandArguments, RedisScript, TransformReply } from './RESP/types'; +// TODO: enum? +export type MULTI_REPLY = { + GENERIC: 'generic'; + TYPED: 'typed'; +}; + +export type MultiReply = MULTI_REPLY[keyof MULTI_REPLY]; + +export type MultiReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; + export interface RedisMultiQueuedCommand { args: CommandArguments; transformReply?: TransformReply; @@ -15,7 +25,6 @@ export default class RedisMultiCommand { args, transformReply }); - return this; } addScript(script: RedisScript, args: CommandArguments, transformReply?: TransformReply) { @@ -34,7 +43,7 @@ export default class RedisMultiCommand { redisArgs.push(...args); redisArgs.preserve = args.preserve; - return this.addCommand(redisArgs, transformReply); + this.addCommand(redisArgs, transformReply); } transformReplies(rawReplies: Array): Array { From 8ef0e47e57a1e5aaaf65048630b4fe53aa60db5a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 1 Jun 2023 12:39:59 +0300 Subject: [PATCH 116/325] RESP docs --- docs/{RESP3.md => RESP.md} | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) rename docs/{RESP3.md => RESP.md} (75%) diff --git a/docs/RESP3.md b/docs/RESP.md similarity index 75% rename from docs/RESP3.md rename to docs/RESP.md index ed45ac8c87f..af33142740e 100644 --- a/docs/RESP3.md +++ b/docs/RESP.md @@ -1,4 +1,12 @@ -# RESP3 => JS Type Mappings: +# RESP2 -> JS + +- Integer (`:`) => `number` +- Simple String (`+`) => `string | Buffer` +- Blob String (`$`) => `string | Buffer` +- Simple Error (`-`) => `ErrorReply` +- Array (`*`) => `Array` + +# RESP3 -> JS - Null (`_`) => `null` - Boolean (`#`) => `boolean` @@ -19,7 +27,7 @@ ## Map keys and Set members -When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. +When decoding Map to `Map | object` or Set to `Set`, keys/members (respectively) of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. ## Not Implemented From eb47bb03fce3826f1d9787325a6a58cb69f920af Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 7 Jun 2023 11:32:15 -0400 Subject: [PATCH 117/325] some docs Co-authored-by: Guy Royse --- docs/command-options.md | 37 +++++++++++++++++++++++++++++++++++++ docs/scan-iterators.md | 29 +++++++++++++++++++++++++++++ docs/v4-to-v5.md | 28 +++++++++++++++++++++++----- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 docs/command-options.md create mode 100644 docs/scan-iterators.md diff --git a/docs/command-options.md b/docs/command-options.md new file mode 100644 index 00000000000..0f2a27ec75f --- /dev/null +++ b/docs/command-options.md @@ -0,0 +1,37 @@ +# Command Options + +> :warning: The command options API in v5 has breaking changes from the previous version. For more details, refer to the [v4-to-v5 guide](./v4-to-v5.md#command-options). + +TODO: "proxy client" concept + +## Type Mapping + +TODO [RESP](./RESP.md) + +`withTypeMapping` + +```javascript +await client.get('key'); // `string | null` + +const proxyClient = client.withTypeMapping({ + [TYPES.BLOB_STRING]: Buffer +}); + +await proxyClient.get('key'); // `Buffer | null` +``` + +## Abort Signal + +TODO + +`withAbortSignal` + +## ASAP + +TODO + +`asap` + +## `withCommandOptions` + +TODO diff --git a/docs/scan-iterators.md b/docs/scan-iterators.md new file mode 100644 index 00000000000..cfb7545e58f --- /dev/null +++ b/docs/scan-iterators.md @@ -0,0 +1,29 @@ +# Scan Iterators + +> :warning: The scan iterators API in v5 has breaking changes from the previous version. For more details, refer to the [v4-to-v5 guide](./v4-to-v5.md#scan-iterators). + +[`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 keys of client.scanIterator()) { + const values = await client.mGet(keys); +} +``` + +This works with `HSCAN`, `SSCAN`, and `ZSCAN` too: + +```typescript +for await (const entries of client.hScanIterator('hash')) {} +for await (const members of client.sScanIterator('set')) {} +for await (const membersWithScores 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 +}); +``` diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 332bd12dcf5..6d24149ff7e 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -22,7 +22,7 @@ With the new API, instead of passing the options directly to the commands we use await client.get('key'); // `string | null` const proxyClient = client.withCommandOptions({ - flags: { + typeMapping: { [TYPES.BLOB_STRING]: Buffer } }); @@ -33,10 +33,13 @@ await proxyClient.get('key'); // `Buffer | null` `withCommandOptions` can be used to override all of the command options, without reusing any existing ones. To override just a specific option, use the following functions: -- `withFlags` - override `flags` only. +- `withTypeMapping` - override `typeMapping` only. +- `withAbortSignal` - override `abortSignal` only. - `asap` - override `asap` to `true`. - `isolated` - override `isolated` to `true`. +[TODO](./command-options.md) + ## Quit VS Disconnect The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection. @@ -45,9 +48,24 @@ The `QUIT` command has been deprecated in Redis 7.2 and should now also be consi ## Scan Iterators -TODO -Yields chunks instead of individual items. Allows multi key operations. -See the [Scan Iterators guide](./scan-iterators.md). +Iterator commands like `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN` return collections of elements (depending on the data type). However, v4 iterators loop over these collections and yield individual items: + +```javascript +for await (const key of client.scanIterator()) { + console.log(key, await client.get(key)); +} +``` + +This mismatch can be awkward and makes "multi-key" commands like `MGET`, `UNLINK`, etc. pointless. So, in v5 the iterators now yield a collection instead of an element: + +```javascript +for await (const keys of client.scanIterator()) { + // we can now meaningfully utilize "multi-key" commands + console.log(keys, await client.mGet(keys)); +} +``` + +for more information, see the [Scan Iterators guide](./scan-iterators.md). ## Legacy Mode From 05f9f0ee0d72642b80dce56d38ca7e32ed7e6c69 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 7 Jun 2023 11:41:23 -0400 Subject: [PATCH 118/325] WIP --- examples/README.md | 2 +- examples/blocking-list-pop.js | 2 +- examples/bloom-filter.js | 2 +- examples/check-connection-status.js | 2 +- examples/command-with-modifiers.js | 38 ++- examples/connect-as-acl-user.js | 2 +- examples/count-min-sketch.js | 2 +- examples/cuckoo-filter.js | 2 +- examples/get-server-time.js | 2 +- examples/hyperloglog.js | 2 +- examples/lua-multi-incr.js | 2 +- examples/managing-json.js | 2 +- examples/search-hashes.js | 2 +- examples/search-json.js | 2 +- examples/search-knn.js | 2 +- examples/set-scan.js | 2 +- examples/sorted-set.js | 2 +- examples/stream-producer.js | 2 +- examples/time-series.js | 2 +- examples/topk.js | 2 +- .../transaction-with-arbitrary-commands.js | 2 +- packages/client/lib/RESP/decoder.ts | 290 +++++++++--------- packages/client/lib/RESP/types.ts | 36 +-- packages/client/lib/client/commands-queue.ts | 38 +-- packages/client/lib/client/index.ts | 117 +++---- packages/client/lib/client/legacy-mode.ts | 2 +- packages/client/lib/client/multi-command.ts | 34 +- packages/client/lib/client/socket.ts | 8 +- packages/client/lib/cluster/multi-command.ts | 34 +- packages/client/lib/multi-command.spec.ts | 137 ++++----- packages/client/lib/multi-command.ts | 2 +- 31 files changed, 390 insertions(+), 386 deletions(-) diff --git a/examples/README.md b/examples/README.md index 19e9df31f90..62b7efe38d8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -90,5 +90,5 @@ await client.connect(); // Add your example code here... -await client.quit(); +client.destroy(); ``` diff --git a/examples/blocking-list-pop.js b/examples/blocking-list-pop.js index 099c73a2a96..ec9bec4d639 100644 --- a/examples/blocking-list-pop.js +++ b/examples/blocking-list-pop.js @@ -27,4 +27,4 @@ console.log('blpopPromise resolved'); // {"key":"keyName","element":"value"} console.log(`listItem is '${JSON.stringify(listItem)}'`); -await client.quit(); +client.destroy(); diff --git a/examples/bloom-filter.js b/examples/bloom-filter.js index cf5f1940b3e..a133b0274f2 100644 --- a/examples/bloom-filter.js +++ b/examples/bloom-filter.js @@ -77,4 +77,4 @@ const info = await client.bf.info('mybloom'); // } console.log(info); -await client.quit(); +client.destroy(); diff --git a/examples/check-connection-status.js b/examples/check-connection-status.js index 0ccf8ff5e21..ae3c863fb14 100644 --- a/examples/check-connection-status.js +++ b/examples/check-connection-status.js @@ -25,4 +25,4 @@ console.log('Afer connectPromise has resolved...'); // isReady will return True here, client is ready to use. console.log(`client.isOpen: ${client.isOpen}, client.isReady: ${client.isReady}`); -await client.quit(); +client.destroy(); diff --git a/examples/command-with-modifiers.js b/examples/command-with-modifiers.js index 974f78dc5d8..31106b17e45 100644 --- a/examples/command-with-modifiers.js +++ b/examples/command-with-modifiers.js @@ -1,25 +1,31 @@ // Define a custom script that shows example of SET command // with several modifiers. -import { createClient } from 'redis'; +import { createClient } from '../packages/client'; const client = createClient(); await client.connect(); await client.del('mykey'); -let result = await client.set('mykey', 'myvalue', { - EX: 60, - GET: true -}); - -console.log(result); //null - -result = await client.set('mykey', 'newvalue', { - EX: 60, - GET: true -}); - -console.log(result); //myvalue - -await client.quit(); +console.log( + await client.set('mykey', 'myvalue', { + expiration: { + type: 'EX', + value: 60 + }, + GET: true + }) +); // null + +console.log( + await client.set('mykey', 'newvalue', { + expiration: { + type: 'EX', + value: 60 + }, + GET: true + }) +); // 'myvalue' + +await client.close(); diff --git a/examples/connect-as-acl-user.js b/examples/connect-as-acl-user.js index df46aa1e288..bc3069b5bbc 100644 --- a/examples/connect-as-acl-user.js +++ b/examples/connect-as-acl-user.js @@ -23,4 +23,4 @@ try { console.log(`GET command failed: ${e.message}`); } -await client.quit(); +client.destroy(); diff --git a/examples/count-min-sketch.js b/examples/count-min-sketch.js index f88a148986f..ffbe13a7c27 100644 --- a/examples/count-min-sketch.js +++ b/examples/count-min-sketch.js @@ -77,4 +77,4 @@ console.log('Count-Min Sketch info:'); // } console.log(info); -await client.quit(); +client.destroy(); diff --git a/examples/cuckoo-filter.js b/examples/cuckoo-filter.js index 87976f3fefb..6ab58fbfa5c 100644 --- a/examples/cuckoo-filter.js +++ b/examples/cuckoo-filter.js @@ -76,4 +76,4 @@ const info = await client.cf.info('mycuckoo'); // } console.log(info); -await client.quit(); +client.destroy(); diff --git a/examples/get-server-time.js b/examples/get-server-time.js index 967859f0136..0e32c1296af 100644 --- a/examples/get-server-time.js +++ b/examples/get-server-time.js @@ -9,4 +9,4 @@ const serverTime = await client.time(); // 2022-02-25T12:57:40.000Z { microseconds: 351346 } console.log(serverTime); -await client.quit(); +client.destroy(); diff --git a/examples/hyperloglog.js b/examples/hyperloglog.js index 4ac9b575f96..027112a08bf 100644 --- a/examples/hyperloglog.js +++ b/examples/hyperloglog.js @@ -48,4 +48,4 @@ try { console.error(e); } -await client.quit(); +client.destroy(); diff --git a/examples/lua-multi-incr.js b/examples/lua-multi-incr.js index 8eb1092c295..5cf39142006 100644 --- a/examples/lua-multi-incr.js +++ b/examples/lua-multi-incr.js @@ -24,4 +24,4 @@ await client.connect(); await client.set('mykey', '5'); console.log(await client.mincr('mykey', 'myotherkey', 10)); // [ 15, 10 ] -await client.quit(); +client.destroy(); diff --git a/examples/managing-json.js b/examples/managing-json.js index 81949d5c222..a28a0ee5106 100644 --- a/examples/managing-json.js +++ b/examples/managing-json.js @@ -73,4 +73,4 @@ const numPets = await client.json.arrLen('noderedis:jsondata', '$.pets'); // We now have 4 pets. console.log(`We now have ${numPets} pets.`); -await client.quit(); +client.destroy(); diff --git a/examples/search-hashes.js b/examples/search-hashes.js index 85e6106a99a..f0a4560f903 100644 --- a/examples/search-hashes.js +++ b/examples/search-hashes.js @@ -85,4 +85,4 @@ for (const doc of results.documents) { console.log(`${doc.id}: ${doc.value.name}, ${doc.value.age} years old.`); } -await client.quit(); +client.destroy(); diff --git a/examples/search-json.js b/examples/search-json.js index 6481889ecfd..bff5b2cb362 100644 --- a/examples/search-json.js +++ b/examples/search-json.js @@ -145,4 +145,4 @@ console.log( // ] // } -await client.quit(); +client.destroy(); diff --git a/examples/search-knn.js b/examples/search-knn.js index ea20f52e3fe..49bd00d86df 100644 --- a/examples/search-knn.js +++ b/examples/search-knn.js @@ -88,4 +88,4 @@ console.log(JSON.stringify(results, null, 2)); // } // ] // } -await client.quit(); +client.destroy(); diff --git a/examples/set-scan.js b/examples/set-scan.js index 73f6c443444..0e379224d9d 100644 --- a/examples/set-scan.js +++ b/examples/set-scan.js @@ -12,4 +12,4 @@ for await (const member of client.sScanIterator(setName)) { console.log(member); } -await client.quit(); +client.destroy(); diff --git a/examples/sorted-set.js b/examples/sorted-set.js index eb1f82867c1..3fcc24b8442 100644 --- a/examples/sorted-set.js +++ b/examples/sorted-set.js @@ -28,4 +28,4 @@ for await (const memberWithScore of client.zScanIterator('mysortedset')) { console.log(memberWithScore); } -await client.quit(); +client.destroy(); diff --git a/examples/stream-producer.js b/examples/stream-producer.js index f81931e5197..113265dbd40 100644 --- a/examples/stream-producer.js +++ b/examples/stream-producer.js @@ -47,4 +47,4 @@ console.log(`Length of mystream: ${await client.xLen('mystream')}.`); // Should be approximately 1000: console.log(`Length of mytrimmedstream: ${await client.xLen('mytrimmedstream')}.`); -await client.quit(); +client.destroy(); diff --git a/examples/time-series.js b/examples/time-series.js index 2f2ac598032..1d61ff94408 100644 --- a/examples/time-series.js +++ b/examples/time-series.js @@ -119,4 +119,4 @@ try { console.error(e); } -await client.quit(); +client.destroy(); diff --git a/examples/topk.js b/examples/topk.js index 35cdc4a8500..d09144c230c 100644 --- a/examples/topk.js +++ b/examples/topk.js @@ -110,4 +110,4 @@ const [ simonCount, lanceCount ] = await client.topK.count('mytopk', [ console.log(`Count estimate for simon: ${simonCount}.`); console.log(`Count estimate for lance: ${lanceCount}.`); -await client.quit(); +client.destroy(); diff --git a/examples/transaction-with-arbitrary-commands.js b/examples/transaction-with-arbitrary-commands.js index 274a362d57e..d68533205a1 100644 --- a/examples/transaction-with-arbitrary-commands.js +++ b/examples/transaction-with-arbitrary-commands.js @@ -37,4 +37,4 @@ console.log(responses); // Clean up fixtures. await client.del(['hash1', 'hash2', 'hash3']); -await client.quit(); +client.destroy(); diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 98cd7bcdc81..af312788b9e 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -1,7 +1,7 @@ // @ts-nocheck import { VerbatimString } from './verbatim-string'; import { SimpleError, BlobError, ErrorReply } from '../errors'; -import { Flags } from './types'; +import { TypeMapping } from './types'; // https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md export const RESP_TYPES = { @@ -34,7 +34,7 @@ const ASCII = { 'e': 101 } as const; -export const PUSH_FLAGS = { +export const PUSH_TYPE_MAPPING = { [RESP_TYPES.BLOB_STRING]: Buffer }; @@ -45,7 +45,7 @@ interface DecoderOptions { onReply(reply: any): unknown; onErrorReply(err: ErrorReply): unknown; onPush(push: Array): unknown; - getFlags(): Flags; + getTypeMapping(): TypeMapping; } export class Decoder { @@ -118,7 +118,7 @@ export class Decoder { return this._handleDecodedValue( this._config.onReply, this._decodeBigNumber( - this._config.getFlags()[RESP_TYPES.BIG_NUMBER], + this._config.getTypeMapping()[RESP_TYPES.BIG_NUMBER], chunk ) ); @@ -127,7 +127,7 @@ export class Decoder { return this._handleDecodedValue( this._config.onReply, this._decodeDouble( - this._config.getFlags()[RESP_TYPES.DOUBLE], + this._config.getTypeMapping()[RESP_TYPES.DOUBLE], chunk ) ); @@ -136,7 +136,7 @@ export class Decoder { return this._handleDecodedValue( this._config.onReply, this._decodeSimpleString( - this._config.getFlags()[RESP_TYPES.SIMPLE_STRING], + this._config.getTypeMapping()[RESP_TYPES.SIMPLE_STRING], chunk ) ); @@ -145,7 +145,7 @@ export class Decoder { return this._handleDecodedValue( this._config.onReply, this._decodeBlobString( - this._config.getFlags()[RESP_TYPES.BLOB_STRING], + this._config.getTypeMapping()[RESP_TYPES.BLOB_STRING], chunk ) ); @@ -154,7 +154,7 @@ export class Decoder { return this._handleDecodedValue( this._config.onReply, this._decodeVerbatimString( - this._config.getFlags()[RESP_TYPES.VERBATIM_STRING], + this._config.getTypeMapping()[RESP_TYPES.VERBATIM_STRING], chunk ) ); @@ -174,26 +174,29 @@ export class Decoder { case RESP_TYPES.ARRAY: return this._handleDecodedValue( this._config.onReply, - this._decodeArray(this._config.getFlags(), chunk) + this._decodeArray(this._config.getTypeMapping(), chunk) ); case RESP_TYPES.SET: return this._handleDecodedValue( this._config.onReply, - this._decodeSet(this._config.getFlags(), chunk) + this._decodeSet(this._config.getTypeMapping(), chunk) ); case RESP_TYPES.MAP: return this._handleDecodedValue( this._config.onReply, - this._decodeMap(this._config.getFlags(), chunk) + this._decodeMap(this._config.getTypeMapping(), chunk) ); case RESP_TYPES.PUSH: return this._handleDecodedValue( this._config.onPush, - this._decodeArray(PUSH_FLAGS, chunk) + this._decodeArray(PUSH_TYPE_MAPPING, chunk) ); + + default: + throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); } } @@ -269,8 +272,8 @@ export class Decoder { return this._decodeUnsingedNumber.bind(this, number); } - private _decodeBigNumber(flag, chunk) { - if (flag === String) { + private _decodeBigNumber(type, chunk) { + if (type === String) { return this._decodeSimpleString(String, chunk); } @@ -319,8 +322,8 @@ export class Decoder { return this._decodeUnsingedBigNumber.bind(this, bigNumber); } - private _decodeDouble(flag, chunk) { - if (flag === String) { + private _decodeDouble(type, chunk) { + if (type === String) { return this._decodeSimpleString(String, chunk); } @@ -464,38 +467,38 @@ export class Decoder { return cursor; } - private _decodeSimpleString(flag, chunk) { + private _decodeSimpleString(type, chunk) { const start = this._cursor, crlfIndex = this._findCRLF(chunk, start); if (crlfIndex === -1) { return this._continueDecodeSimpleString.bind( this, [chunk.subarray(start)], - flag + type ); } const slice = chunk.subarray(start, crlfIndex); - return flag === Buffer ? + return type === Buffer ? slice : slice.toString(); } - private _continueDecodeSimpleString(chunks, flag, chunk) { + private _continueDecodeSimpleString(chunks, type, chunk) { const start = this._cursor, crlfIndex = this._findCRLF(chunk, start); if (crlfIndex === -1) { chunks.push(chunk.subarray(start)); - return this._continueDecodeSimpleString.bind(this, chunks, flag); + return this._continueDecodeSimpleString.bind(this, chunks, type); } chunks.push(chunk.subarray(start, crlfIndex)); - return flag === Buffer ? + return type === Buffer ? Buffer.concat(chunks) : chunks.join(''); } - private _decodeBlobString(flag, chunk) { + private _decodeBlobString(type, chunk) { // RESP 2 bulk string null // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings if (chunk[this._cursor] === ASCII['-']) { @@ -505,26 +508,26 @@ export class Decoder { const length = this._decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeBlobStringLength.bind(this, length, flag); + return this._continueDecodeBlobStringLength.bind(this, length, type); } else if (this._cursor >= chunk.length) { - return this._decodeBlobStringWithLength.bind(this, length, flag); + return this._decodeBlobStringWithLength.bind(this, length, type); } - return this._decodeBlobStringWithLength(length, flag, chunk); + return this._decodeBlobStringWithLength(length, type, chunk); } - private _continueDecodeBlobStringLength(lengthCb, flag, chunk) { + private _continueDecodeBlobStringLength(lengthCb, type, chunk) { const length = lengthCb(chunk); if (typeof length === 'function') { - return this._continueDecodeBlobStringLength.bind(this, length, flag); + return this._continueDecodeBlobStringLength.bind(this, length, type); } else if (this._cursor >= chunk.length) { - return this._decodeBlobStringWithLength.bind(this, length, flag); + return this._decodeBlobStringWithLength.bind(this, length, type); } - return this._decodeBlobStringWithLength(length, flag, chunk); + return this._decodeBlobStringWithLength(length, type, chunk); } - private _decodeStringWithLength(length, skip, flag, chunk) { + private _decodeStringWithLength(length, skip, type, chunk) { const end = this._cursor + length; if (end >= chunk.length) { const slice = chunk.subarray(this._cursor); @@ -534,18 +537,18 @@ export class Decoder { length - slice.length, [slice], skip, - flag + type ); } const slice = chunk.subarray(this._cursor, end); this._cursor = end + skip; - return flag === Buffer ? + return type === Buffer ? slice : slice.toString(); } - private _continueDecodeStringWithLength(length, chunks, skip, flag, chunk) { + private _continueDecodeStringWithLength(length, chunks, skip, type, chunk) { const end = this._cursor + length; if (end >= chunk.length) { const slice = chunk.subarray(this._cursor); @@ -556,46 +559,46 @@ export class Decoder { length - slice.length, chunks, skip, - flag + type ); } chunks.push(chunk.subarray(this._cursor, end)); this._cursor = end + skip; - return flag === Buffer ? + return type === Buffer ? Buffer.concat(chunks) : chunks.join(''); } - private _decodeBlobStringWithLength(length, flag, chunk) { - return this._decodeStringWithLength(length, 2, flag, chunk); + private _decodeBlobStringWithLength(length, type, chunk) { + return this._decodeStringWithLength(length, 2, type, chunk); } - private _decodeVerbatimString(flag, chunk) { + private _decodeVerbatimString(type, chunk) { return this._continueDecodeVerbatimStringLength( this._decodeUnsingedNumber.bind(this, 0), - flag, + type, chunk ); } - private _continueDecodeVerbatimStringLength(lengthCb, flag, chunk) { + private _continueDecodeVerbatimStringLength(lengthCb, type, chunk) { const length = lengthCb(chunk); return typeof length === 'function'? - this._continueDecodeVerbatimStringLength.bind(this, length, flag) : - this._decodeVerbatimStringWithLength(length, flag, chunk); + this._continueDecodeVerbatimStringLength.bind(this, length, type) : + this._decodeVerbatimStringWithLength(length, type, chunk); } - private _decodeVerbatimStringWithLength(length, flag, chunk) { + private _decodeVerbatimStringWithLength(length, type, chunk) { const stringLength = length - 4; // skip : - if (flag === VerbatimString) { + if (type === VerbatimString) { return this._decodeVerbatimStringFormat(stringLength, chunk); } this._cursor += 4; // skip : return this._cursor >= chunk.length ? - this._decodeBlobStringWithLength.bind(this, stringLength, flag) : - this._decodeBlobStringWithLength(stringLength, flag, chunk); + this._decodeBlobStringWithLength.bind(this, stringLength, type) : + this._decodeBlobStringWithLength(stringLength, type, chunk); } private _decodeVerbatimStringFormat(stringLength, chunk) { @@ -656,14 +659,14 @@ export class Decoder { new BlobError(string); } - private _decodeNestedType(flags, chunk) { + private _decodeNestedType(typeMapping, chunk) { const type = chunk[this._cursor]; return ++this._cursor === chunk.length ? - this._decodeNestedTypeValue.bind(this, type, flags) : - this._decodeNestedTypeValue(type, flags, chunk); + this._decodeNestedTypeValue.bind(this, type, typeMapping) : + this._decodeNestedTypeValue(type, typeMapping, chunk); } - private _decodeNestedTypeValue(type, flags, chunk) { + private _decodeNestedTypeValue(type, typeMapping, chunk) { switch (type) { case RESP_TYPES.NULL: return this._decodeNull(); @@ -675,19 +678,19 @@ export class Decoder { return this._decodeNumber(chunk); case RESP_TYPES.BIG_NUMBER: - return this._decodeBigNumber(flags[RESP_TYPES.BIG_NUMBER], chunk); + return this._decodeBigNumber(typeMapping[RESP_TYPES.BIG_NUMBER], chunk); case RESP_TYPES.DOUBLE: - return this._decodeDouble(flags[RESP_TYPES.DOUBLE], chunk); + return this._decodeDouble(typeMapping[RESP_TYPES.DOUBLE], chunk); case RESP_TYPES.SIMPLE_STRING: - return this._decodeSimpleString(flags[RESP_TYPES.SIMPLE_STRING], chunk); + return this._decodeSimpleString(typeMapping[RESP_TYPES.SIMPLE_STRING], chunk); case RESP_TYPES.BLOB_STRING: - return this._decodeBlobString(flags[RESP_TYPES.BLOB_STRING], chunk); + return this._decodeBlobString(typeMapping[RESP_TYPES.BLOB_STRING], chunk); case RESP_TYPES.VERBATIM_STRING: - return this._decodeVerbatimString(flags[RESP_TYPES.VERBATIM_STRING], chunk); + return this._decodeVerbatimString(typeMapping[RESP_TYPES.VERBATIM_STRING], chunk); case RESP_TYPES.SIMPLE_ERROR: return this._decodeSimpleError(chunk); @@ -696,17 +699,20 @@ export class Decoder { return this._decodeBlobError(chunk); case RESP_TYPES.ARRAY: - return this._decodeArray(flags, chunk); + return this._decodeArray(typeMapping, chunk); case RESP_TYPES.SET: - return this._decodeSet(flags, chunk); + return this._decodeSet(typeMapping, chunk); case RESP_TYPES.MAP: - return this._decodeMap(flags, chunk); + return this._decodeMap(typeMapping, chunk); + + default: + throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); } } - private _decodeArray(flags, chunk) { + private _decodeArray(typeMapping, chunk) { // RESP 2 null // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays if (chunk[this._cursor] === ASCII['-']) { @@ -716,49 +722,49 @@ export class Decoder { return this._decodeArrayWithLength( this._decodeUnsingedNumber(0, chunk), - flags, + typeMapping, chunk ); } - private _decodeArrayWithLength(length, flags, chunk) { + private _decodeArrayWithLength(length, typeMapping, chunk) { return typeof length === 'function' ? - this._continueDecodeArrayLength.bind(this, length, flags) : + this._continueDecodeArrayLength.bind(this, length, typeMapping) : this._decodeArrayItems( new Array(length), 0, - flags, + typeMapping, chunk ); } - private _continueDecodeArrayLength(lengthCb, flags, chunk) { + private _continueDecodeArrayLength(lengthCb, typeMapping, chunk) { return this._decodeArrayWithLength( lengthCb(chunk), - flags, + typeMapping, chunk ); } - private _decodeArrayItems(array, filled, flags, chunk) { + private _decodeArrayItems(array, filled, typeMapping, chunk) { for (let i = filled; i < array.length; i++) { if (this._cursor >= chunk.length) { return this._decodeArrayItems.bind( this, array, i, - flags + typeMapping ); } - const item = this._decodeNestedType(flags, chunk); + const item = this._decodeNestedType(typeMapping, chunk); if (typeof item === 'function') { return this._continueDecodeArrayItems.bind( this, array, i, item, - flags + typeMapping ); } @@ -768,7 +774,7 @@ export class Decoder { return array; } - private _continueDecodeArrayItems(array, filled, itemCb, flags, chunk) { + private _continueDecodeArrayItems(array, filled, itemCb, typeMapping, chunk) { const item = itemCb(chunk); if (typeof item === 'function') { return this._continueDecodeArrayItems.bind( @@ -776,52 +782,52 @@ export class Decoder { array, filled, item, - flags + typeMapping ); } array[filled++] = item; - return this._decodeArrayItems(array, filled, flags, chunk); + return this._decodeArrayItems(array, filled, typeMapping, chunk); } - private _decodeSet(flags, chunk) { + private _decodeSet(typeMapping, chunk) { const length = this._decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeSetLength.bind(this, length, flags); + return this._continueDecodeSetLength.bind(this, length, typeMapping); } return this._decodeSetItems( length, - flags, + typeMapping, chunk ); } - private _continueDecodeSetLength(lengthCb, flags, chunk) { + private _continueDecodeSetLength(lengthCb, typeMapping, chunk) { const length = lengthCb(chunk); return typeof length === 'function' ? - this._continueDecodeSetLength.bind(this, length, flags) : - this._decodeSetItems(length, flags, chunk); + this._continueDecodeSetLength.bind(this, length, typeMapping) : + this._decodeSetItems(length, typeMapping, chunk); } - private _decodeSetItems(length, flags, chunk) { - return flags[RESP_TYPES.SET] === Set ? + private _decodeSetItems(length, typeMapping, chunk) { + return typeMapping[RESP_TYPES.SET] === Set ? this._decodeSetAsSet( new Set(), length, - flags, + typeMapping, chunk ) : this._decodeArrayItems( new Array(length), 0, - flags, + typeMapping, chunk ); } - private _decodeSetAsSet(set, remaining, flags, chunk) { + private _decodeSetAsSet(set, remaining, typeMapping, chunk) { // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates while (remaining > 0) { if (this._cursor >= chunk.length) { @@ -829,18 +835,18 @@ export class Decoder { this, set, remaining, - flags + typeMapping ); } - const item = this._decodeNestedType(flags, chunk); + const item = this._decodeNestedType(typeMapping, chunk); if (typeof item === 'function') { return this._continueDecodeSetAsSet.bind( this, set, remaining, item, - flags + typeMapping ); } @@ -851,7 +857,7 @@ export class Decoder { return set; } - private _continueDecodeSetAsSet(set, remaining, itemCb, flags, chunk) { + private _continueDecodeSetAsSet(set, remaining, itemCb, typeMapping, chunk) { const item = itemCb(chunk); if (typeof item === 'function') { return this._continueDecodeSetAsSet.bind( @@ -859,42 +865,42 @@ export class Decoder { set, remaining, item, - flags + typeMapping ); } set.add(item); - return this._decodeSetAsSet(set, remaining - 1, flags, chunk); + return this._decodeSetAsSet(set, remaining - 1, typeMapping, chunk); } - private _decodeMap(flags, chunk) { + private _decodeMap(typeMapping, chunk) { const length = this._decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeMapLength.bind(this, length, flags); + return this._continueDecodeMapLength.bind(this, length, typeMapping); } return this._decodeMapItems( length, - flags, + typeMapping, chunk ); } - private _continueDecodeMapLength(lengthCb, flags, chunk) { + private _continueDecodeMapLength(lengthCb, typeMapping, chunk) { const length = lengthCb(chunk); return typeof length === 'function' ? - this._continueDecodeMapLength.bind(this, length, flags) : - this._decodeMapItems(length, flags, chunk); + this._continueDecodeMapLength.bind(this, length, typeMapping) : + this._decodeMapItems(length, typeMapping, chunk); } - private _decodeMapItems(length, flags, chunk) { - switch (flags[RESP_TYPES.MAP]) { + private _decodeMapItems(length, typeMapping, chunk) { + switch (typeMapping[RESP_TYPES.MAP]) { case Map: return this._decodeMapAsMap( new Map(), length, - flags, + typeMapping, chunk ); @@ -902,7 +908,7 @@ export class Decoder { return this._decodeArrayItems( new Array(length * 2), 0, - flags, + typeMapping, chunk ); @@ -910,13 +916,13 @@ export class Decoder { return this._decodeMapAsObject( Object.create(null), length, - flags, + typeMapping, chunk ); } } - private _decodeMapAsMap(map, remaining, flags, chunk) { + private _decodeMapAsMap(map, remaining, typeMapping, chunk) { // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys while (remaining > 0) { if (this._cursor >= chunk.length) { @@ -924,18 +930,18 @@ export class Decoder { this, map, remaining, - flags + typeMapping ); } - const key = this._decodeMapKey(flags, chunk); + const key = this._decodeMapKey(typeMapping, chunk); if (typeof key === 'function') { return this._continueDecodeMapKey.bind( this, map, remaining, key, - flags + typeMapping ); } @@ -945,12 +951,12 @@ export class Decoder { map, remaining, key, - this._decodeNestedType.bind(this, flags), - flags + this._decodeNestedType.bind(this, typeMapping), + typeMapping ); } - const value = this._decodeNestedType(flags, chunk); + const value = this._decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { return this._continueDecodeMapValue.bind( this, @@ -958,7 +964,7 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } @@ -969,14 +975,14 @@ export class Decoder { return map; } - private _decodeMapKey(flags, chunk) { + private _decodeMapKey(typeMapping, chunk) { const type = chunk[this._cursor]; return ++this._cursor === chunk.length ? - this._decodeMapKeyValue.bind(this, type, flags) : - this._decodeMapKeyValue(type, flags, chunk); + this._decodeMapKeyValue.bind(this, type, typeMapping) : + this._decodeMapKeyValue(type, typeMapping, chunk); } - private _decodeMapKeyValue(type, flags, chunk) { + private _decodeMapKeyValue(type, typeMapping, chunk) { switch (type) { // decode simple string map key as string (and not as buffer) case RESP_TYPES.SIMPLE_STRING: @@ -987,11 +993,11 @@ export class Decoder { return this._decodeBlobString(String, chunk); default: - return this._decodeNestedTypeValue(type, flags, chunk); + return this._decodeNestedTypeValue(type, typeMapping, chunk); } } - private _continueDecodeMapKey(map, remaining, keyCb, flags, chunk) { + private _continueDecodeMapKey(map, remaining, keyCb, typeMapping, chunk) { const key = keyCb(chunk); if (typeof key === 'function') { return this._continueDecodeMapKey.bind( @@ -999,7 +1005,7 @@ export class Decoder { map, remaining, key, - flags + typeMapping ); } @@ -1009,12 +1015,12 @@ export class Decoder { map, remaining, key, - this._decodeNestedType.bind(this, flags), - flags + this._decodeNestedType.bind(this, typeMapping), + typeMapping ); } - const value = this._decodeNestedType(flags, chunk); + const value = this._decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { return this._continueDecodeMapValue.bind( this, @@ -1022,15 +1028,15 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } map.set(key, value); - return this._decodeMapAsMap(map, remaining - 1, flags, chunk); + return this._decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - private _continueDecodeMapValue(map, remaining, key, valueCb, flags, chunk) { + private _continueDecodeMapValue(map, remaining, key, valueCb, typeMapping, chunk) { const value = valueCb(chunk); if (typeof value === 'function') { return this._continueDecodeMapValue.bind( @@ -1039,34 +1045,34 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } map.set(key, value); - return this._decodeMapAsMap(map, remaining - 1, flags, chunk); + return this._decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - private _decodeMapAsObject(object, remaining, flags, chunk) { + private _decodeMapAsObject(object, remaining, typeMapping, chunk) { while (remaining > 0) { if (this._cursor >= chunk.length) { return this._decodeMapAsObject.bind( this, object, remaining, - flags + typeMapping ); } - const key = this._decodeMapKey(flags, chunk); + const key = this._decodeMapKey(typeMapping, chunk); if (typeof key === 'function') { return this._continueDecodeMapAsObjectKey.bind( this, object, remaining, key, - flags + typeMapping ); } @@ -1076,12 +1082,12 @@ export class Decoder { object, remaining, key, - this._decodeNestedType.bind(this, flags), - flags + this._decodeNestedType.bind(this, typeMapping), + typeMapping ); } - const value = this._decodeNestedType(flags, chunk); + const value = this._decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { return this._continueDecodeMapAsObjectValue.bind( this, @@ -1089,7 +1095,7 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } @@ -1100,7 +1106,7 @@ export class Decoder { return object; } - private _continueDecodeMapAsObjectKey(object, remaining, keyCb, flags, chunk) { + private _continueDecodeMapAsObjectKey(object, remaining, keyCb, typeMapping, chunk) { const key = keyCb(chunk); if (typeof key === 'function') { return this._continueDecodeMapAsObjectKey.bind( @@ -1108,7 +1114,7 @@ export class Decoder { object, remaining, key, - flags + typeMapping ); } @@ -1118,12 +1124,12 @@ export class Decoder { object, remaining, key, - this._decodeNestedType.bind(this, flags), - flags + this._decodeNestedType.bind(this, typeMapping), + typeMapping ); } - const value = this._decodeNestedType(flags, chunk); + const value = this._decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { return this._continueDecodeMapAsObjectValue.bind( this, @@ -1131,16 +1137,16 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } object[key] = value; - return this._decodeMapAsObject(object, remaining - 1, flags, chunk); + return this._decodeMapAsObject(object, remaining - 1, typeMapping, chunk); } - private _continueDecodeMapAsObjectValue(object, remaining, key, valueCb, flags, chunk) { + private _continueDecodeMapAsObjectValue(object, remaining, key, valueCb, typeMapping, chunk) { const value = valueCb(chunk); if (typeof value === 'function') { return this._continueDecodeMapAsObjectValue.bind( @@ -1149,12 +1155,12 @@ export class Decoder { remaining, key, value, - flags + typeMapping ); } object[key] = value; - return this._decodeMapAsObject(object, remaining - 1, flags, chunk); + return this._decodeMapAsObject(object, remaining - 1, typeMapping, chunk); } } diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index d6b11db72b6..812c79c4963 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -148,45 +148,45 @@ export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply Map | Array >; -export type Reply = ReplyWithFlags; +export type Reply = ReplyWithTypeMapping; export type Flag = ((...args: any) => T) | (new (...args: any) => T); type RespTypeUnion = T extends RespType ? FLAG_TYPES : never; -export type Flags = { +export type TypeMapping = { [P in RespTypes]?: Flag>>>; }; type MapKey< T, - FLAGS extends Flags -> = ReplyWithFlags = ReplyWithTypeMapping; -export type ReplyWithFlags< +export type ReplyWithTypeMapping< REPLY, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = ( - // if REPLY is a type, extract the coresponding type from FLAGS or use the default type + // if REPLY is a type, extract the coresponding type from TYPE_MAPPING or use the default type REPLY extends RespType ? - FLAGS[RESP_TYPE] extends Flag ? - ReplyWithFlags, FLAGS> : - ReplyWithFlags + TYPE_MAPPING[RESP_TYPE] extends Flag ? + ReplyWithTypeMapping, TYPE_MAPPING> : + ReplyWithTypeMapping : ( // if REPLY is a known generic type, convert its generic arguments // TODO: tuples? - REPLY extends Array ? Array> : - REPLY extends Set ? Set> : - REPLY extends Map ? Map, ReplyWithFlags> : + REPLY extends Array ? Array> : + REPLY extends Set ? Set> : + REPLY extends Map ? Map, ReplyWithTypeMapping> : // `Date` & `Buffer` are supersets of `Record`, so they need to be checked first REPLY extends Date ? REPLY : REPLY extends Buffer ? REPLY : REPLY extends Record ? { - [P in keyof REPLY]: ReplyWithFlags; + [P in keyof REPLY]: ReplyWithTypeMapping; } : // otherwise, just return the REPLY as is REPLY @@ -333,17 +333,17 @@ export type CommandReply< export type CommandSignature< COMMAND extends Command, RESP extends RespVersions, - FLAGS extends Flags -> = (...args: Parameters) => Promise, FLAGS>>; + TYPE_MAPPING extends TypeMapping +> = (...args: Parameters) => Promise, TYPE_MAPPING>>; export type CommandWithPoliciesSignature< COMMAND extends Command, RESP extends RespVersions, - FLAGS extends Flags, + TYPE_MAPPING extends TypeMapping, POLICIES extends CommandPolicies > = (...args: Parameters) => Promise< ReplyWithPolicy< - ReplyWithFlags, FLAGS>, + ReplyWithTypeMapping, TYPE_MAPPING>, MergePolicies > >; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 55efe68080a..57b7999dfa3 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,7 +1,7 @@ import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list'; import encodeCommand from '../RESP/encoder'; -import { Decoder, PUSH_FLAGS, RESP_TYPES } from '../RESP/decoder'; -import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; +import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder'; +import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; import { EventEmitter } from 'stream'; @@ -10,7 +10,7 @@ export interface QueueCommandOptions { chainId?: symbol; asap?: boolean; abortSignal?: AbortSignal; - flags?: Flags; + typeMapping?: TypeMapping; } export interface CommandWaitingToBeSent extends CommandWaitingForReply { @@ -26,15 +26,15 @@ interface CommandWaitingForReply { resolve(reply?: unknown): void; reject(err: unknown): void; channelsCounter?: number; - flags?: Flags; + typeMapping?: TypeMapping; } export type OnShardedChannelMoved = (channel: string, listeners: ChannelListeners) => void; const PONG = Buffer.from('pong'); -const RESP2_PUSH_FLAGS = { - ...PUSH_FLAGS, +const RESP2_PUSH_TYPE_MAPPING = { + ...PUSH_TYPE_MAPPING, [RESP_TYPES.SIMPLE_STRING]: Buffer }; @@ -102,8 +102,8 @@ export default class RedisCommandsQueue { } } - private _getFlags() { - return this._waitingForReply.head!.value.flags ?? {}; + private _getTypeMapping() { + return this._waitingForReply.head!.value.typeMapping ?? {}; } private _initiateResp3Decoder() { @@ -115,7 +115,7 @@ export default class RedisCommandsQueue { } }, - getFlags: () => this._getFlags() + getTypeMapping: () => this._getTypeMapping() }); } @@ -126,9 +126,9 @@ export default class RedisCommandsQueue { if (this._onPush(reply)) return; if (PONG.equals(reply[0] as Buffer)) { - const { resolve, flags } = this._waitingForReply.shift()!, + const { resolve, typeMapping } = this._waitingForReply.shift()!, buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(flags?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); return; } } @@ -140,11 +140,11 @@ export default class RedisCommandsQueue { // PubSub is handled in onReply // @ts-expect-error onPush: undefined, - getFlags: () => { + getTypeMapping: () => { // PubSub push is an Array in RESP2 return this._pubSub.isActive ? - RESP2_PUSH_FLAGS : - this._getFlags(); + RESP2_PUSH_TYPE_MAPPING : + this._getTypeMapping(); } }); } @@ -161,7 +161,7 @@ export default class RedisCommandsQueue { const value: CommandWaitingToBeSent = { args, chainId: options?.chainId, - flags: options?.flags, + typeMapping: options?.typeMapping, resolve, reject, abort: undefined @@ -243,7 +243,7 @@ export default class RedisCommandsQueue { this._waitingToBeSent.push({ args: command.args, channelsCounter: command.channelsCounter, - flags: PUSH_FLAGS, + typeMapping: PUSH_TYPE_MAPPING, resolve: () => { command.resolve(); resolve(); @@ -282,7 +282,7 @@ export default class RedisCommandsQueue { return encoded; } - #flushWaitingForReply(err: Error): void { + private _flushWaitingForReply(err: Error): void { while (this._waitingForReply.head) { this._waitingForReply.shift()!.reject(err); } @@ -304,7 +304,7 @@ export default class RedisCommandsQueue { this.decoder.reset(); this._pubSub.reset(); - this.#flushWaitingForReply(err); + this._flushWaitingForReply(err); if (!this._chainInExecution) return; @@ -321,7 +321,7 @@ export default class RedisCommandsQueue { flushAll(err: Error): void { this.decoder.reset(); this._pubSub.reset(); - this.#flushWaitingForReply(err); + this._flushWaitingForReply(err); while (this._waitingToBeSent.head) { RedisCommandsQueue._flushWaitingToBeSent( this._waitingToBeSent.shift()!, diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index e9b6c4e2bf7..25a0ddf6c41 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -7,14 +7,14 @@ import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchErr import { URL } from 'url'; import { TcpSocketConnectOpts } from 'net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; -import { Command, CommandArguments, CommandSignature, Flags, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; +import { Command, CommandArguments, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; -import { ReplyWithFlags, CommandReply } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply } from '../RESP/types'; import SCAN, { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; -import { RedisClientPool } from './pool'; +// import { RedisClientPool } from './pool'; export interface RedisClientOptions< M extends RedisModules = RedisModules, @@ -69,37 +69,37 @@ export interface RedisClientOptions< type WithCommands< RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, FLAGS>; + [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING>; }; type WithModules< M extends RedisModules, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [P in keyof M]: { - [C in keyof M[P]]: CommandSignature; + [C in keyof M[P]]: CommandSignature; }; }; type WithFunctions< F extends RedisFunctions, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [L in keyof F]: { - [C in keyof F[L]]: CommandSignature; + [C in keyof F[L]]: CommandSignature; }; }; type WithScripts< S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof S]: CommandSignature; + [P in keyof S]: CommandSignature; }; export type RedisClientType< @@ -107,20 +107,20 @@ export type RedisClientType< F extends RedisFunctions = {}, S extends RedisScripts = {}, RESP extends RespVersions = 2, - FLAGS extends Flags = {} + TYPE_MAPPING extends TypeMapping = {} > = ( - RedisClient & - WithCommands & - WithModules & - WithFunctions & - WithScripts + RedisClient & + WithCommands & + WithModules & + WithFunctions & + WithScripts ); export interface ClientCommandOptions extends QueueCommandOptions { // isolated?: boolean; } -type ProxyClient = RedisClient<{}, {}, {}, RespVersions, Flags> & { commandOptions?: ClientCommandOptions }; +type ProxyClient = RedisClient<{}, {}, {}, RespVersions, TypeMapping> & { commandOptions?: ClientCommandOptions }; type NamespaceProxyClient = { self: ProxyClient }; @@ -133,7 +133,7 @@ export default class RedisClient< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > extends EventEmitter { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); @@ -396,7 +396,15 @@ export default class RedisClient< }; return new RedisSocket(socketInitiator, this._options?.socket) - .on('data', chunk => this._queue.decoder.write(chunk)) + .on('data', chunk => { + try { + this._queue.decoder.write(chunk); + } catch (err) { + this._queue.decoder.reset(); + this.emit('error', err); + + } + }) .on('error', err => { this.emit('error', err); if (this._socket.isOpen && !this._options?.disableOfflineQueue) { @@ -440,7 +448,7 @@ export default class RedisClient< F, S, RESP, - T['flags'] extends Flags ? T['flags'] : {} + T['typeMapping'] extends TypeMapping ? T['typeMapping'] : {} >; } @@ -459,17 +467,20 @@ export default class RedisClient< F, S, RESP, - K extends 'flags' ? V extends Flags ? V : {} : FLAGS + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING >; } /** - * Override the `flags` command option + * Override the `typeMapping` command option */ - withFlags(flags: FLAGS) { - return this._commandOptionsProxy('flags', flags); + withTypeMapping(typeMapping: TYPE_MAPPING) { + return this._commandOptionsProxy('typeMapping', typeMapping); } + /** + * Override the `abortSignal` command option + */ withAbortSignal(abortSignal: AbortSignal) { return this._commandOptionsProxy('abortSignal', abortSignal); } @@ -482,7 +493,7 @@ export default class RedisClient< } /** - * Get the "legacy" (v3/callback) interface + * Create the "legacy" (v3/callback) interface */ legacy(): RedisLegacyClientType { return new RedisLegacyClient( @@ -493,11 +504,11 @@ export default class RedisClient< /** * Create `RedisClientPool` using this client as a prototype */ - pool() { - return RedisClientPool.fromClient( - this as unknown as RedisClientType - ); - } + // pool() { + // return RedisClientPool.fromClient( + // this as unknown as RedisClientType + // ); + // } duplicate(overrides?: Partial>) { return new (Object.getPrototypeOf(this).constructor)({ @@ -679,12 +690,12 @@ export default class RedisClient< private _addMultiCommands( commands: Array, chainId?: symbol, - flags?: Flags + typeMapping?: TypeMapping ) { return Promise.all( commands.map(({ args }) => this._queue.addCommand(args, { chainId, - flags + typeMapping })) ); } @@ -699,7 +710,7 @@ export default class RedisClient< const promise = Promise.all( commands.map(({ args }) => this._queue.addCommand(args, { - flags: (this as ProxyClient).commandOptions?.flags + typeMapping: (this as ProxyClient).commandOptions?.typeMapping })) ); this._tick(); @@ -710,24 +721,24 @@ export default class RedisClient< * @internal */ async executeMulti( - commands: Array, + commands: Array, selectedDB?: number ) { - if (!this._socket.isOpen) { - return Promise.reject(new ClientClosedError()); - } + if (!this._socket.isOpen) { + return Promise.reject(new ClientClosedError()); + } - const flags = (this as ProxyClient).commandOptions?.flags, + const typeMapping = (this as ProxyClient).commandOptions?.typeMapping, chainId = Symbol('MULTI Chain'), promises = [ - this._queue.addCommand(['MULTI'], { chainId }), + this._queue.addCommand(['MULTI'], { chainId }), ]; for (const { args } of commands) { promises.push( this._queue.addCommand(args, { chainId, - flags + typeMapping }) ); } @@ -736,7 +747,7 @@ export default class RedisClient< this._queue.addCommand(['EXEC'], { chainId }) ); - this._tick(); + this._tick(); const results = await Promise.all(promises), execResult = results[results.length - 1]; @@ -745,23 +756,23 @@ export default class RedisClient< throw new WatchError(); } - if (selectedDB !== undefined) { - this._selectedDB = selectedDB; - } + if (selectedDB !== undefined) { + this._selectedDB = selectedDB; + } return execResult as Array; - } + } - MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, FLAGS> { + MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { return new (this as any).Multi(this); } multi = this.MULTI; async* scanIterator( - this: RedisClientType, + this: RedisClientType, options?: ScanOptions & ScanIteratorOptions - ): AsyncIterable['keys'], FLAGS>> { + ): AsyncIterable['keys'], TYPE_MAPPING>> { let cursor = options?.cursor ?? 0; do { const reply = await this.scan(cursor, options); @@ -771,7 +782,7 @@ export default class RedisClient< } async* hScanIterator( - this: RedisClientType, + this: RedisClientType, key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { @@ -784,7 +795,7 @@ export default class RedisClient< } async* sScanIterator( - this: RedisClientType, + this: RedisClientType, key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { @@ -797,7 +808,7 @@ export default class RedisClient< } async* zScanIterator( - this: RedisClientType, + this: RedisClientType, key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { @@ -843,7 +854,7 @@ export default class RedisClient< const maybeClose = () => { if (!this._queue.isEmpty()) return; - + this._socket.off('data', maybeClose); this._socket.destroySocket(); resolve(); diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 87de34bd7e1..78793c5f800 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -1,4 +1,4 @@ -import { RedisModules, RedisFunctions, RedisScripts, RespVersions, Flags, Command, CommandArguments, ReplyUnion } from '../RESP/types'; +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, Command, CommandArguments, ReplyUnion } from '../RESP/types'; import { RedisClientType } from '.'; import { getTransformReply } from '../commander'; import { ErrorReply } from '../errors'; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index b011a08916f..625e449da5b 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import { RedisClientType } from '.'; @@ -11,14 +11,14 @@ type CommandSignature< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = (...args: Parameters) => RedisClientMultiCommandType< - [...REPLIES, ReplyWithFlags, FLAGS>], + [...REPLIES, ReplyWithTypeMapping, TYPE_MAPPING>], M, F, S, RESP, - FLAGS + TYPE_MAPPING >; type WithCommands< @@ -27,9 +27,9 @@ type WithCommands< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof typeof COMMANDS]: CommandSignature; + [P in keyof typeof COMMANDS]: CommandSignature; }; type WithModules< @@ -38,10 +38,10 @@ type WithModules< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [P in keyof M]: { - [C in keyof M[P]]: CommandSignature; + [C in keyof M[P]]: CommandSignature; }; }; @@ -51,10 +51,10 @@ type WithFunctions< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [L in keyof F]: { - [C in keyof F[L]]: CommandSignature; + [C in keyof F[L]]: CommandSignature; }; }; @@ -64,9 +64,9 @@ type WithScripts< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof S]: CommandSignature; + [P in keyof S]: CommandSignature; }; export type RedisClientMultiCommandType< @@ -75,13 +75,13 @@ export type RedisClientMultiCommandType< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = ( RedisClientMultiCommand & - WithCommands & - WithModules & - WithFunctions & - WithScripts + WithCommands & + WithModules & + WithFunctions & + WithScripts ); export default class RedisClientMultiCommand { diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index a7f3d77dd61..47c4616c191 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -46,7 +46,7 @@ interface CreateSocketReturn { export type RedisSocketInitiator = () => Promise; export default class RedisSocket extends EventEmitter { - static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { + private static _initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { options ??= {}; if (!(options as net.IpcSocketConnectOpts).path) { (options as net.TcpSocketConnectOpts).port ??= 6379; @@ -60,7 +60,7 @@ export default class RedisSocket extends EventEmitter { return options; } - static #isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { + private static _isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { return (options as RedisTlsSocketOptions).tls === true; } @@ -96,7 +96,7 @@ export default class RedisSocket extends EventEmitter { super(); this._initiator = initiator; - this._options = RedisSocket.#initiateOptions(options); + this._options = RedisSocket._initiateOptions(options); } private _reconnectStrategy(retries: number, cause: Error) { @@ -176,7 +176,7 @@ export default class RedisSocket extends EventEmitter { private _createSocket(): Promise { return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket.#isTlsSocket(this._options) ? + const { connectEvent, socket } = RedisSocket._isTlsSocket(this._options) ? this._createTlsSocket() : this._createNetSocket(); diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index 4ec8e0996dd..dc351d42fc4 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion, RedisArgument } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion, RedisArgument } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import RedisCluster, { RedisClusterType } from '.'; @@ -11,14 +11,14 @@ type CommandSignature< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = (...args: Parameters) => RedisClusterMultiCommandType< - [...REPLIES, ReplyWithFlags, FLAGS>], + [...REPLIES, ReplyWithTypeMapping, TYPE_MAPPING>], M, F, S, RESP, - FLAGS + TYPE_MAPPING >; type WithCommands< @@ -27,9 +27,9 @@ type WithCommands< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof typeof COMMANDS]: CommandSignature; + [P in keyof typeof COMMANDS]: CommandSignature; }; type WithModules< @@ -38,10 +38,10 @@ type WithModules< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [P in keyof M]: { - [C in keyof M[P]]: CommandSignature; + [C in keyof M[P]]: CommandSignature; }; }; @@ -51,10 +51,10 @@ type WithFunctions< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { [L in keyof F]: { - [C in keyof F[L]]: CommandSignature; + [C in keyof F[L]]: CommandSignature; }; }; @@ -64,9 +64,9 @@ type WithScripts< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = { - [P in keyof S]: CommandSignature; + [P in keyof S]: CommandSignature; }; export type RedisClusterMultiCommandType< @@ -75,13 +75,13 @@ export type RedisClusterMultiCommandType< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags + TYPE_MAPPING extends TypeMapping > = ( RedisClusterMultiCommand & - WithCommands & - WithModules & - WithFunctions & - WithScripts + WithCommands & + WithModules & + WithFunctions & + WithScripts ); export default class RedisClusterMultiCommand { diff --git a/packages/client/lib/multi-command.spec.ts b/packages/client/lib/multi-command.spec.ts index b0f79c6e157..eebb29f7985 100644 --- a/packages/client/lib/multi-command.spec.ts +++ b/packages/client/lib/multi-command.spec.ts @@ -1,96 +1,77 @@ import { strict as assert } from 'assert'; import RedisMultiCommand from './multi-command'; -import { WatchError } from './errors'; import { SQUARE_SCRIPT } from './client/index.spec'; describe('Multi Command', () => { - it('generateChainId', () => { - assert.equal( - typeof RedisMultiCommand.generateChainId(), - 'symbol' - ); - }); - - it('addCommand', () => { - const multi = new RedisMultiCommand(); - multi.addCommand(['PING']); - - assert.deepEqual( - multi.queue[0].args, - ['PING'] - ); - }); + it('addCommand', () => { + const multi = new RedisMultiCommand(); + multi.addCommand(['PING']); - it('addScript', () => { - const multi = new RedisMultiCommand(); + assert.deepEqual( + multi.queue[0].args, + ['PING'] + ); + }); - multi.addScript(SQUARE_SCRIPT, ['1']); - assert.equal( - multi.scriptsInUse.has(SQUARE_SCRIPT.SHA1), - true - ); - assert.deepEqual( - multi.queue[0].args, - ['EVAL', SQUARE_SCRIPT.SCRIPT, '0', '1'] - ); + describe('addScript', () => { + const multi = new RedisMultiCommand(); - multi.addScript(SQUARE_SCRIPT, ['2']); - assert.equal( - multi.scriptsInUse.has(SQUARE_SCRIPT.SHA1), - true - ); - assert.deepEqual( - multi.queue[1].args, - ['EVALSHA', SQUARE_SCRIPT.SHA1, '0', '2'] - ); + it('should use EVAL', () => { + multi.addScript(SQUARE_SCRIPT, ['1']); + assert.deepEqual( + Array.from(multi.queue.at(-1).args), + ['EVAL', SQUARE_SCRIPT.SCRIPT, '0', '1'] + ); }); - describe('exec', () => { - it('without commands', () => { - assert.deepEqual( - new RedisMultiCommand().queue, - [] - ); - }); + it('should use EVALSHA', () => { + multi.addScript(SQUARE_SCRIPT, ['2']); + assert.deepEqual( + Array.from(multi.queue.at(-1).args), + ['EVALSHA', SQUARE_SCRIPT.SHA1, '0', '2'] + ); + }); - it('with commands', () => { - const multi = new RedisMultiCommand(); - multi.addCommand(['PING']); + it('without NUMBER_OF_KEYS', () => { + multi.addScript({ + ...SQUARE_SCRIPT, + NUMBER_OF_KEYS: undefined + }, ['2']); + assert.deepEqual( + Array.from(multi.queue.at(-1).args), + ['EVALSHA', SQUARE_SCRIPT.SHA1, '2'] + ); + }); + }); - assert.deepEqual( - multi.queue, - [{ - args: ['PING'], - transformReply: undefined - }] - ); - }); + describe('exec', () => { + it('without commands', () => { + assert.deepEqual( + new RedisMultiCommand().queue, + [] + ); }); - describe('handleExecReplies', () => { - it('WatchError', () => { - assert.throws( - () => new RedisMultiCommand().handleExecReplies([null]), - WatchError - ); - }); + it('with commands', () => { + const multi = new RedisMultiCommand(); + multi.addCommand(['PING']); - it('with replies', () => { - const multi = new RedisMultiCommand(); - multi.addCommand(['PING']); - assert.deepEqual( - multi.handleExecReplies(['OK', 'QUEUED', ['PONG']]), - ['PONG'] - ); - }); + assert.deepEqual( + multi.queue, + [{ + args: ['PING'], + transformReply: undefined + }] + ); }); + }); - it('transformReplies', () => { - const multi = new RedisMultiCommand(); - multi.addCommand(['PING'], (reply: string) => reply.substring(0, 2)); - assert.deepEqual( - multi.transformReplies(['PONG']), - ['PO'] - ); - }); + it('transformReplies', () => { + const multi = new RedisMultiCommand(); + multi.addCommand(['PING'], (reply: string) => reply.substring(0, 2)); + assert.deepEqual( + multi.transformReplies(['PONG']), + ['PO'] + ); + }); }); diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 19bb680d687..54b4bd22728 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -29,6 +29,7 @@ export default class RedisMultiCommand { addScript(script: RedisScript, args: CommandArguments, transformReply?: TransformReply) { const redisArgs: CommandArguments = []; + redisArgs.preserve = args.preserve; if (this.scriptsInUse.has(script.SHA1)) { redisArgs.push('EVALSHA', script.SHA1); } else { @@ -41,7 +42,6 @@ export default class RedisMultiCommand { } redisArgs.push(...args); - redisArgs.preserve = args.preserve; this.addCommand(redisArgs, transformReply); } From cf79a806c557b0a09b20944282870f2eacb2ed1f Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 7 Jun 2023 11:45:48 -0400 Subject: [PATCH 119/325] WIP --- docs/RESP.md | 2 +- docs/v5.md | 4 +- package-lock.json | 7032 ++++-------------- package.json | 22 +- packages/bloom/package.json | 16 +- packages/client/.eslintrc.json | 15 - packages/client/lib/RESP/decoder-ts.ts | 1043 --- packages/client/lib/client/index.spec.ts | 1717 +++-- packages/client/lib/cluster/cluster-slots.ts | 2 +- packages/client/lib/cluster/index.ts | 26 +- packages/client/package.json | 26 +- packages/graph/package.json | 17 +- packages/json/package.json | 16 +- packages/redis/README.md | 197 +- packages/redis/package.json | 7 - packages/search/package.json | 16 +- packages/test-utils/lib/dockers.ts | 30 +- packages/test-utils/lib/index.ts | 32 +- packages/test-utils/package.json | 19 +- packages/time-series/package.json | 16 +- tsconfig.base.json | 5 +- tsconfig.json | 25 + 22 files changed, 2389 insertions(+), 7896 deletions(-) delete mode 100644 packages/client/.eslintrc.json delete mode 100644 packages/client/lib/RESP/decoder-ts.ts create mode 100644 tsconfig.json diff --git a/docs/RESP.md b/docs/RESP.md index af33142740e..5d428497c9a 100644 --- a/docs/RESP.md +++ b/docs/RESP.md @@ -27,7 +27,7 @@ ## Map keys and Set members -When decoding Map to `Map | object` or Set to `Set`, keys/members (respectively) of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. +When decoding Map to `Map | object` or Set to `Set`, keys/members (respectively) of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring type mapping) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. ## Not Implemented diff --git a/docs/v5.md b/docs/v5.md index a38d7800d7c..68fa4d6778e 100644 --- a/docs/v5.md +++ b/docs/v5.md @@ -13,11 +13,11 @@ await client.connect(); client.hGetAll('key'); // Record -client.withFlags({ +client.withTypeMapping({ [TYPES.MAP]: Map }).hGetAll('key'); // Map -client.withFlags({ +client.withTypeMapping({ [TYPES.MAP]: Map, [TYPES.BLOB_STRING]: Buffer }).hGetAll('key'); // Map diff --git a/package-lock.json b/package-lock.json index 50671184fd4..0eaf067a557 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,18 @@ "./packages/*" ], "devDependencies": { - "@tsconfig/node16": "^1.0.3", - "gh-pages": "^5.0.0" + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@tsconfig/node16": "^1.0.4", + "@types/mocha": "^10.0.1", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "gh-pages": "^5.0.0", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "source-map-support": "^0.5.21", + "ts-node": "^10.9.1", + "typedoc": "^0.24.7", + "typescript": "^5.0.4" } }, "node_modules/@ampproject/remapping": { @@ -39,30 +49,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", + "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", + "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/generator": "^7.22.0", + "@babel/helper-compilation-targets": "^7.22.1", + "@babel/helper-module-transforms": "^7.22.1", + "@babel/helpers": "^7.22.0", + "@babel/parser": "^7.22.0", + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -77,13 +87,22 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", + "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -93,12 +112,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", + "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.21.4", + "@babel/compat-data": "^7.22.0", "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", @@ -111,10 +130,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", + "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -158,31 +186,31 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", + "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-environment-visitor": "^7.22.1", + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-simple-access": "^7.21.5", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", + "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -201,9 +229,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", + "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -228,14 +256,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", + "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.3" }, "engines": { "node": ">=6.9.0" @@ -296,6 +324,15 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -318,9 +355,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.22.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz", + "integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -330,33 +367,33 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", + "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", + "version": "7.22.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz", + "integrity": "sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", + "@babel/generator": "^7.22.3", + "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/parser": "^7.22.4", + "@babel/types": "^7.22.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -374,12 +411,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "version": "7.22.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.4.tgz", + "integrity": "sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, @@ -425,23 +462,24 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, + "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -457,19 +495,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", - "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", + "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", "dev": true, + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, + "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -484,6 +524,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "peer": true, "engines": { "node": ">=12.22" }, @@ -496,13 +537,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -529,6 +565,19 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -542,6 +591,45 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -664,226 +752,6 @@ "node": ">= 8" } }, - "node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", - "dev": true, - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", - "dev": true, - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.0.0.tgz", - "integrity": "sha512-V8BVJGN0ZmMlURF55VFHFd/L92XQQ43KvFjNmY1IYbCN3V/h/uUFV6iQi19WEHM395Nn+1qhUbViCAD/1czzog==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", - "dev": true, - "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request/node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", - "dev": true, - "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/types": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.1.2.tgz", - "integrity": "sha512-LPbJIuu1WNoRHbN4UMysEdlissRFpTCWyoKT7kHPufI8T+XX33/qilfMWJo3mCOjNIKu0+43oSQPf+HJa0+TTQ==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^17.0.0" - } - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.1.1.tgz", - "integrity": "sha512-yfRcuupmxxeDOSxvw4g+wFCrGiPD0L32f5WMzqMXp7Rl93EOCdFiDcaSNnZ10Up9GdNqkj70UTa8hfhPFphaZA==", - "dev": true, - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@redis/bloom": { "resolved": "packages/bloom", "link": true @@ -912,18 +780,6 @@ "resolved": "packages/time-series", "link": true }, - "node_modules/@sindresorhus/is": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", - "integrity": "sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -934,21 +790,12 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0" - } - }, - "node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", + "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { @@ -977,27 +824,6 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1017,21 +843,15 @@ "dev": true }, "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/mocha": { @@ -1041,21 +861,22 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.16.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", - "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", - "dev": true + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", + "dev": true, + "peer": true }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.14", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.14.tgz", - "integrity": "sha512-mn72up6cjaMyMuaPaa/AwKf6WtsSRysQC7wxFkCm1XcOKXPM1z+5Y4H5wjIVBz4gdAkjvZxVVfjA6ba1nHr5WQ==", + "version": "10.0.15", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", + "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -1067,12 +888,6 @@ "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", "dev": true }, - "node_modules/@types/yallist": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", - "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", - "dev": true - }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -1089,15 +904,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz", - "integrity": "sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", + "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.1", - "@typescript-eslint/type-utils": "5.59.1", - "@typescript-eslint/utils": "5.59.1", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/type-utils": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1122,43 +937,16 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@typescript-eslint/parser": { + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", + "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.1.tgz", - "integrity": "sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.1", - "@typescript-eslint/types": "5.59.1", - "@typescript-eslint/typescript-estree": "5.59.1", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", + "debug": "^4.3.4" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1177,13 +965,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz", - "integrity": "sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", + "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.1", - "@typescript-eslint/visitor-keys": "5.59.1" + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1194,13 +982,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz", - "integrity": "sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", + "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.1", - "@typescript-eslint/utils": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/utils": "5.59.9", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1221,9 +1009,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.1.tgz", - "integrity": "sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", + "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1234,13 +1022,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz", - "integrity": "sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", + "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.1", - "@typescript-eslint/visitor-keys": "5.59.1", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/visitor-keys": "5.59.9", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1260,74 +1048,18 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", - "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", + "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.1", - "@typescript-eslint/types": "5.59.1", - "@typescript-eslint/typescript-estree": "5.59.1", + "@typescript-eslint/scope-manager": "5.59.9", + "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/typescript-estree": "5.59.9", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1342,40 +1074,13 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", - "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", + "version": "5.59.9", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", + "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/types": "5.59.9", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1403,6 +1108,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1416,18 +1122,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1446,6 +1140,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1457,35 +1152,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "dev": true - }, - "node_modules/ansi-align/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -1495,33 +1161,6 @@ "node": ">=6" } }, - "node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", - "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.9.0.tgz", - "integrity": "sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "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", @@ -1595,29 +1234,13 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/array-uniq": { @@ -1629,105 +1252,18 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.map": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", - "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1737,188 +1273,64 @@ "node": ">=8" } }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "fill-range": "^7.0.1" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, - "node_modules/boxen": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.2.tgz", - "integrity": "sha512-1Z4UJabXUP1/R9rLpoU3O2lEMnG3pPLAs/ZD2lF3t2q7qD5lM8rqbtnvtvm4N0wEyNlE+9yZVTVAGmd1V5jabg==", + "node_modules/browserslist": { + "version": "4.21.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.7.tgz", + "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" + "caniuse-lite": "^1.0.30001489", + "electron-to-chromium": "^1.4.411", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" }, - "engines": { - "node": ">=14.16" + "bin": { + "browserslist": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/buffer-from": { @@ -1927,57 +1339,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.10", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.10.tgz", - "integrity": "sha512-v6WB+Epm/qO4Hdlio/sfUn69r5Shgh39SsE9DSd4bIezP0mblOlObI+I0kUEM7J0JFc+I7pSeMeYaOYtX1N/VQ==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "^4.0.1", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.2", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1993,24 +1354,12 @@ "node": ">=8" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "peer": true, "engines": { "node": ">=6" } @@ -2025,9 +1374,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001481", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", - "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==", + "version": "1.0.30001495", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz", + "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==", "dev": true, "funding": [ { @@ -2060,12 +1409,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2105,21 +1448,6 @@ "node": ">= 6" } }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2129,112 +1457,15 @@ "node": ">=6" } }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.8.0.tgz", - "integrity": "sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", - "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", + "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/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==", - "dev": true - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" } }, "node_modules/cluster-key-slot": { @@ -2281,71 +1512,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/configstore": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", - "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", - "dev": true, - "dependencies": { - "dot-prop": "^6.0.1", - "graceful-fs": "^4.2.6", - "unique-string": "^3.0.0", - "write-file-atomic": "^3.0.3", - "xdg-basedir": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/yeoman/configstore?sponsor=1" - } - }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2366,52 +1538,16 @@ "node": ">= 8" } }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "type-fest": "^1.0.1" + "ms": "2.1.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" + "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { @@ -2428,81 +1564,12 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peer": true }, "node_modules/default-require-extensions": { "version": "3.0.1", @@ -2519,85 +1586,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/degenerator": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.4.tgz", - "integrity": "sha512-Z66uPeBfHZAHVmue3HPfyKu2Q0rC2cRxbTOsvmU/po5fvvcx27W4mIu9n0PUlQih4oUYvcG1BsbtVv8x7KDOSw==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.17" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -2624,6 +1612,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -2631,31 +1620,10 @@ "node": ">=6.0.0" } }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/electron-to-chromium": { - "version": "1.4.373", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.373.tgz", - "integrity": "sha512-whGyixOVSRlyOBQDsRH9xltFaMij2/+DQRdaYahCq0P/fiVnAVGaW7OVsFnEjze/qUo298ez9C46gnALpo6ukg==", + "version": "1.4.423", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.423.tgz", + "integrity": "sha512-y4A7YfQcDGPAeSWM1IuoWzXpg9RY1nwHzHSwRtCSQFp9FgAVDgdWlFf0RbdWfLWQ2WUI+bddUgk5RgTjqRE6FQ==", "dev": true }, "node_modules/email-addresses": { @@ -2665,125 +1633,11 @@ "dev": true }, "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2799,111 +1653,30 @@ "node": ">=6" } }, - "node_modules/escape-goat": { + "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", - "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", - "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", + "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.39.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.42.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -2913,8 +1686,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2922,13 +1695,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -2964,9 +1736,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2975,23 +1747,12 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -3008,92 +1769,33 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "peer": true, "engines": { "node": ">=4.0" } }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, + "peer": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { "esparse": "bin/esparse.js", @@ -3108,6 +1810,7 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -3120,6 +1823,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -3159,64 +1863,17 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "peer": true }, "node_modules/fast-glob": { "version": "3.2.12", @@ -3250,13 +1907,15 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/fastq": { "version": "1.15.0", @@ -3267,74 +1926,12 @@ "reusify": "^1.0.4" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "peer": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -3342,15 +1939,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", - "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -3407,16 +1995,19 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -3433,6 +2024,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "peer": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -3445,16 +2037,8 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } + "peer": true }, "node_modules/foreground-child": { "version": "2.0.0", @@ -3469,27 +2053,6 @@ "node": ">=8.0.0" } }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", @@ -3544,52 +2107,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", - "dev": true, - "dependencies": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -3616,20 +2133,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3639,60 +2142,6 @@ "node": ">=8.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", - "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/get-uri/node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/gh-pages": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", @@ -3715,35 +2164,44 @@ "node": ">=10" } }, - "node_modules/git-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, "dependencies": { - "is-ssh": "^1.4.0", - "parse-url": "^8.1.0" + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/git-url-parse": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, "dependencies": { - "git-up": "^7.0.0" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.1.1", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -3759,6 +2217,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -3766,102 +2225,40 @@ "node": ">=10.13.0" } }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, + "peer": true, "dependencies": { - "ini": "2.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.0.tgz", - "integrity": "sha512-WTcaQ963xV97MN3x0/CbAriXFZcXCfgxVp91I+Ze6pawQOa7SgzwSx2zIJJsX+kTajMnVs0xcFD1TxZKFqhdnQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { @@ -3876,26 +2273,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "peer": true }, "node_modules/has-flag": { "version": "4.0.0", @@ -3906,69 +2289,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-yarn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", - "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -4009,109 +2329,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -4126,6 +2343,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "peer": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -4137,15 +2355,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4180,2909 +2389,1201 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/inquirer": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.5.tgz", - "integrity": "sha512-3ygAIh8gcZavV9bj6MTdYddG2zPSYswP808fKS46NOwlF0zZljVpnLCHODDqItWJDbDpLb3aouAxGaJbkxoppA==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "ansi-escapes": "^6.0.0", - "chalk": "^5.2.0", - "cli-cursor": "^4.0.0", - "cli-width": "^4.0.0", - "external-editor": "^3.0.3", - "figures": "^5.0.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^6.1.2", - "run-async": "^2.4.0", - "rxjs": "^7.8.0", - "string-width": "^5.1.2", - "strip-ansi": "^7.0.1", - "through": "^2.3.6", - "wrap-ansi": "^8.1.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=14.18.0" + "node": ">=8" } }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "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==", "dev": true, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=8" } }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, "engines": { - "node": ">= 0.4" + "node": ">=0.12.0" } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "peer": true, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" + "engines": { + "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "dependencies": { - "has": "^1.0.3" + "append-transform": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "semver": "bin/semver.js" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-fullwidth-code-point": { + "node_modules/istanbul-lib-report": { "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==", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "engines": { - "node": ">=12" + "bin": { + "jsesc": "bin/jsesc" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "peer": true }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "engines": { - "node": ">= 0.4" + "peer": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 0.8.0" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "peer": true }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "dependencies": { - "protocols": "^2.0.1" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, - "engines": { - "node": ">=8" + "bin": { + "marked": "bin/marked.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 12" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.6" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, "engines": { - "node": ">=10" + "node": ">= 14.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/mochajs" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "balanced-match": "^1.0.0" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { - "is-docker": "^2.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "bin": { - "is-docker": "cli.js" + "dependencies": { + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-yarn-global": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", - "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, "engines": { - "node": ">=12" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "peer": true }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, - "node_modules/issue-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", - "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "node_modules/nise": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, "dependencies": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - }, - "engines": { - "node": ">=10.13" + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterate-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", - "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "dependencies": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", - "dev": true, - "dependencies": { - "package-json": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.capitalize": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/macos-release": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.1.0.tgz", - "integrity": "sha512-/M/R0gCDgM+Cv1IuBG1XGdfTFnMEG6PZeT+KGWHO/OG+imqmaD9CH5vHBTycEM3+Kc4uG2Il+tFAuUWLqQOeUA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/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==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", - "dev": true, - "dependencies": { - "type-fest": "^2.5.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/new-github-release-url/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "dev": true, - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/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==", - "dev": true - }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz", - "integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==", - "dev": true, - "dependencies": { - "chalk": "^5.0.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.6.1", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.1.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "strip-ansi": "^7.0.1", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", - "dev": true, - "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/os-name": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", - "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", - "dev": true, - "dependencies": { - "macos-release": "^3.1.0", - "windows-release": "^5.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pac-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", - "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/pac-resolver": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", - "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", - "dev": true, - "dependencies": { - "degenerator": "^3.0.2", - "ip": "^1.1.5", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.0.tgz", - "integrity": "sha512-hySwcV8RAWeAfPsXb9/HGSPn8lwDnv6fabH+obUZKX169QknRkRhPxd1yMubpKDskLFATkl3jHpNtVtDPFA0Wg==", - "dev": true, - "dependencies": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" + "process-on-spawn": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-path": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", - "dev": true, - "dependencies": { - "protocols": "^2.0.0" - } - }, - "node_modules/parse-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", - "dev": true, - "dependencies": { - "parse-path": "^7.0.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "node_modules/node-releases": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", "dev": true }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "dependencies": { - "pinkie": "^2.0.0" + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.9" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "fromentries": "^1.2.0" + "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, - "node_modules/promise.allsettled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.6.tgz", - "integrity": "sha512-22wJUOD3zswWFqgwjNHa1965LvqTX87WPu/lreY2KSd7SVcERfuZ4GfUaOnJNnvtoIv2yXT/W00YIGMetXtFXg==", + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "array.prototype.map": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "iterate-value": "^1.0.2" + "p-try": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "node_modules/protocols": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", - "dev": true - }, - "node_modules/proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", - "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "node_modules/nyc/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==", "dev": true, "dependencies": { - "escape-goat": "^4.0.0" - }, - "engines": { - "node": ">=12.20" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">=6" } }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "wrappy": "1" } }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, + "peer": true, "dependencies": { - "picomatch": "^2.2.1" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.8.0" } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "resolve": "^1.1.6" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/redis": { - "resolved": "packages/redis", - "link": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { - "@pnpm/npm-conf": "^2.1.0" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=8" } }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { - "rc": "1.2.8" + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/release-it": { - "version": "15.10.1", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.10.1.tgz", - "integrity": "sha512-Wkk4aFHSo27vQwHIlcEy77lJwnQlh4UDQckc53gh5tKo7F22mAUEAe8SYQZJcFh7icdkf0OV70onhB1dDmeClA==", - "dev": true, - "dependencies": { - "@iarna/toml": "2.2.5", - "@octokit/rest": "19.0.7", - "async-retry": "1.3.3", - "chalk": "5.2.0", - "cosmiconfig": "8.1.3", - "execa": "7.1.1", - "git-url-parse": "13.1.0", - "globby": "13.1.3", - "got": "12.6.0", - "inquirer": "9.1.5", - "is-ci": "3.0.1", - "issue-parser": "6.0.0", - "lodash": "4.17.21", - "mime-types": "2.1.35", - "new-github-release-url": "2.0.0", - "node-fetch": "3.3.1", - "open": "9.1.0", - "ora": "6.3.0", - "os-name": "5.1.0", - "promise.allsettled": "1.0.6", - "proxy-agent": "5.0.0", - "semver": "7.3.8", - "shelljs": "0.8.5", - "update-notifier": "6.0.2", - "url-join": "5.0.0", - "wildcard-match": "5.1.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "release-it": "bin/release-it.js" + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0" }, "engines": { - "node": ">=14.9" + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/release-it/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/release-it/node_modules/globby": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz", - "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/release-it/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "isarray": "0.0.1" } }, - "node_modules/release-it/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/release-it/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/release-it/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "find-up": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "lowercase-keys": "^3.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "p-limit": "^2.2.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/restore-cursor/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==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "fromentries": "^1.2.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, + "peer": true, "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "safe-buffer": "^5.1.0" } }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "execa": "^5.0.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.10.0" } }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/redis": { + "resolved": "packages/redis", + "link": true + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "es6-error": "^4.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=4" } }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">=0.10.0" } }, - "node_modules/run-applescript/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==", + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, "engines": { - "node": ">=8" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=6" + "bin": { + "rimraf": "bin.js" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/run-parallel": { @@ -7108,15 +3609,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7137,51 +3629,22 @@ } ] }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" - } - }, - "node_modules/semver-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", - "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/semver-diff/node_modules/lru-cache": { + "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -7193,20 +3656,11 @@ "node": ">=10" } }, - "node_modules/semver-diff/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/serialize-javascript": { "version": "6.0.0", @@ -7223,12 +3677,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7250,27 +3698,10 @@ "node": ">=8" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/shiki": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.1.tgz", - "integrity": "sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -7279,20 +3710,6 @@ "vscode-textmate": "^8.0.0" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7300,13 +3717,13 @@ "dev": true }, "node_modules/sinon": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.4.tgz", - "integrity": "sha512-uzmfN6zx3GQaria1kwgWGeKiXSSbShBbue6Dcj0SI8fiCNFbiUDqKl57WFlY5lyhxZVUKmXvzgG2pilRQCBwWg==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz", + "integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/fake-timers": "^10.2.0", "@sinonjs/samsam": "^8.0.0", "diff": "^5.1.0", "nise": "^5.1.4", @@ -7335,50 +3752,6 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7421,135 +3794,18 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", - "dev": true, - "dependencies": { - "bl": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - }, "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, "node_modules/strip-ansi": { @@ -7573,18 +3829,6 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -7609,6 +3853,15 @@ "node": ">=0.10.0" } }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7621,68 +3874,27 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=0.6.0" + "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7704,21 +3916,6 @@ "node": ">=8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -7731,6 +3928,15 @@ "node": ">=0.10.0" } }, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -7784,9 +3990,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "node_modules/tsutils": { @@ -7804,17 +4010,12 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -7836,6 +4037,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "peer": true, "engines": { "node": ">=10" }, @@ -7843,20 +4045,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -7867,9 +4055,9 @@ } }, "node_modules/typedoc": { - "version": "0.24.6", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", - "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -7884,7 +4072,7 @@ "node": ">= 14.14" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -7897,9 +4085,9 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7912,54 +4100,18 @@ } }, "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.17" } }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -7969,24 +4121,6 @@ "node": ">= 4.0.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", @@ -8013,353 +4147,74 @@ "bin": { "update-browserslist-db": "cli.js" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-notifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", - "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", - "dev": true, - "dependencies": { - "boxen": "^7.0.0", - "chalk": "^5.0.1", - "configstore": "^6.0.0", - "has-yarn": "^3.0.0", - "import-lazy": "^4.0.0", - "is-ci": "^3.0.1", - "is-installed-globally": "^0.4.0", - "is-npm": "^6.0.0", - "is-yarn-global": "^0.4.0", - "latest-version": "^7.0.0", - "pupa": "^3.1.0", - "semver": "^7.3.7", - "semver-diff": "^4.0.0", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/vm2": { - "version": "3.9.17", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.17.tgz", - "integrity": "sha512-AqwtCnZ/ERcX+AVj9vUsphY56YANXxRuqMb7GsDtAr0m0PcQX3u0Aj3KWiXM0YAHy7i6JEeHrwOnwXbGYgRpAw==", - "dev": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - }, - "bin": { - "vm2": "bin/vm2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "dev": true, - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wildcard-match": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", - "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", - "dev": true - }, - "node_modules/windows-release": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.1.0.tgz", - "integrity": "sha512-CddHecz5dt0ngTjGPP1uYr9Tjl4qq5rEKNk8UGb8XCdngNXI+GRYvqelD055FdiUgqODZz3R/5oZWYldPtXQpA==", - "dev": true, - "dependencies": { - "execa": "^5.1.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/windows-release/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "engines": { - "node": ">=10.17.0" + "peer": true, + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/windows-release/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==", + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "engines": { - "node": ">=6" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/windows-release/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, - "node_modules/windows-release/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=6" + "bin": { + "node-which": "bin/node-which" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { - "node": ">=6" + "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8371,61 +4226,22 @@ "dev": true }, "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8444,27 +4260,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -8475,26 +4270,27 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "cliui": "^8.0.1", + "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^4.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^20.2.2" }, "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/yargs-parser": { @@ -8545,35 +4341,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/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==", - "dev": true - }, - "node_modules/yargs/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -8596,90 +4363,49 @@ } }, "packages/bloom": { - "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" } }, "packages/client": { - "name": "@redis/client", - "version": "1.5.7", + "version": "2.0.0-next.1", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" + "generic-pool": "3.9.0" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "@types/sinon": "^10.0.14", - "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.1", - "@typescript-eslint/parser": "^5.59.1", - "eslint": "^8.39.0", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "sinon": "^15.0.4", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@types/sinon": "^10.0.15", + "sinon": "^15.1.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "packages/graph": { - "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" } }, "packages/json": { - "name": "@redis/json", "version": "1.0.4", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" } }, "packages/redis": { @@ -8692,66 +4418,94 @@ "@redis/json": "1.0.4", "@redis/search": "1.1.2", "@redis/time-series": "1.0.4" + } + }, + "packages/redis/node_modules/@redis/client": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz", + "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==", + "dependencies": { + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" }, - "devDependencies": { - "release-it": "^15.9.3", - "typescript": "^5.0.2" + "engines": { + "node": ">=14" } }, + "packages/redis/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "packages/search": { - "name": "@redis/search", "version": "1.1.2", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" } }, "packages/test-utils": { - "name": "@redis/test-utils", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.1", - "@types/node": "^18.16.1", "@types/yargs": "^17.0.24", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typescript": "^5.0.4", - "yargs": "^17.7.1" + "yargs": "^17.7.2" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" + } + }, + "packages/test-utils/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "packages/test-utils/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "packages/test-utils/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" } }, "packages/time-series": { - "name": "@redis/time-series", "version": "1.0.4", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" } } } diff --git a/package.json b/package.json index afb549a486c..27e6c63d60b 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,22 @@ ], "scripts": { "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:modules": "npm run build -w ./packages/bloom -w ./packages/graph -w ./packages/json -w ./packages/search -w ./packages/time-series", - "build:redis": "npm run build -w ./packages/redis", - "build": "npm run build:client && npm run build:test-utils && npm run build:modules && npm run build:redis", - "documentation": "npm run documentation -ws --if-present", + "build": "tsc --build", + "documentation": "typedoc", "gh-pages": "gh-pages -d ./documentation -e ./documentation -u 'documentation-bot '" }, "devDependencies": { - "@tsconfig/node16": "^1.0.3", - "gh-pages": "^5.0.0" + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@tsconfig/node16": "^1.0.4", + "@types/mocha": "^10.0.1", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.59.7", + "gh-pages": "^5.0.0", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "source-map-support": "^0.5.21", + "ts-node": "^10.9.1", + "typedoc": "^0.24.7", + "typescript": "^5.0.4" } } diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 9bcae785dd9..b151421c70a 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -8,23 +8,13 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "documentation": "typedoc" + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "repository": { "type": "git", diff --git a/packages/client/.eslintrc.json b/packages/client/.eslintrc.json deleted file mode 100644 index 3037932fd97..00000000000 --- a/packages/client/.eslintrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "rules": { - "semi": [2, "always"] - } -} diff --git a/packages/client/lib/RESP/decoder-ts.ts b/packages/client/lib/RESP/decoder-ts.ts deleted file mode 100644 index 0586940f692..00000000000 --- a/packages/client/lib/RESP/decoder-ts.ts +++ /dev/null @@ -1,1043 +0,0 @@ -// import { ErrorReply } from '../../errors'; -// import { Flags, ReplyUnion, RespTypesUnion, ReplyWithFlags, RespTypes, Flag } from './types'; - -// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md -// export const TYPES = { -// NULL: 95, // _ -// BOOLEAN: 35, // # -// NUMBER: 58, // : -// BIG_NUMBER: 40, // ( -// DOUBLE: 44, // , -// SIMPLE_STRING: 43, // + -// BLOB_STRING: 36, // $ -// VERBATIM_STRING: 61, // = -// SIMPLE_ERROR: 45, // - -// BLOB_ERROR: 33, // ! -// ARRAY: 42, // * -// SET: 126, // ~ -// MAP: 37, // % -// PUSH: 62 // > -// } as const; - -// const ASCII = { -// '\r': 13, -// 't': 116, -// '-': 45, -// '0': 48, -// '.': 46, -// 'i': 105, -// 'n': 110 -// } as const; - -// // this was written with performance in mind, so it's not very readable... sorry :( - -// interface DecoderConfig { -// // TODO: on parser error? -// // TODO: types -// onReply(reply: unknown): unknown; -// onErrorReply(reply: unknown): unknown; -// onPush(push: unknown): unknown; -// getFlags(): Flags; -// } - -// type ValueCb = DecoderConfig['onReply'] | DecoderConfig['onErrorReply'] | DecoderConfig['onPush']; - -// type Next = (chunk: Buffer) => ValueOrNext; - -// type ValueOrNext = T | Next; - -// export class Decoder { -// #config: DecoderConfig; - -// #cursor = 0; - -// #next: Next | undefined; - -// constructor(config: DecoderConfig) { -// this.#config = config; -// } - -// reset() { -// this.#cursor = 0; -// this.#next = undefined; -// } - -// write(chunk: Buffer) { -// if (this.#cursor >= chunk.length) { -// this.#cursor -= chunk.length; -// return; -// } - -// if (this.#next) { -// if (this.#next(chunk) || this.#cursor >= chunk.length) { -// this.#cursor -= chunk.length; -// return; -// } -// } - -// do { -// const flags = this.#config.getFlags(), -// type = chunk[this.#cursor] as RespTypesUnion; - -// if (++this.#cursor === chunk.length) { -// this.#next = this.#continueDecodeTypeValue.bind(this, type, flags); -// break; -// } - -// if (this.#decodeTypeValue(type, flags, chunk)) { -// break; -// } -// } while (this.#cursor < chunk.length); -// this.#cursor -= chunk.length; -// } - -// #continueDecodeTypeValue( -// type: RespTypesUnion, -// flags: Flags, -// chunk: Buffer -// ) { -// this.#next = undefined; -// return this.#decodeTypeValue(type, flags, chunk); -// } - -// #decodeTypeValue( -// type: RespTypesUnion, -// flags: Flags, -// chunk: Buffer -// ) { -// switch (type) { -// case TYPES.NULL: -// this.#config.onReply(this.#decodeNull()); -// return false; - -// case TYPES.BOOLEAN: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeBoolean(chunk) -// ); - -// case TYPES.NUMBER: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeNumber(chunk) -// ); - -// case TYPES.BIG_NUMBER: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk) -// ); - -// case TYPES.DOUBLE: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeDouble(flags[TYPES.DOUBLE], chunk) -// ); - -// case TYPES.SIMPLE_STRING: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeDouble(flags[TYPES.DOUBLE], chunk) -// ); - -// case TYPES.BLOB_STRING: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeBlobString(flags[TYPES.BLOB_STRING], chunk) -// ); - -// case TYPES.VERBATIM_STRING: -// throw new Error('TODO: verbatim string'); - -// case TYPES.SIMPLE_ERROR: -// return this.#handleDecodedValue( -// this.#config.onErrorReply, -// this.#decodeSimpleError(chunk) -// ); - -// case TYPES.BLOB_ERROR: -// return this.#handleDecodedValue( -// this.#config.onErrorReply, -// this.#decodeBlobError(chunk) -// ); - -// case TYPES.ARRAY: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeArray(flags, chunk) -// ); - -// case TYPES.SET: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeSet(flags, chunk) -// ); - -// case TYPES.MAP: -// return this.#handleDecodedValue( -// this.#config.onReply, -// this.#decodeMap(flags, chunk) -// ); - -// case TYPES.PUSH: -// return this.#handleDecodedValue( -// this.#config.onPush, -// this.#decodeArray(flags, chunk) -// ); -// } -// } - -// #handleDecodedValue(cb: ValueCb, value: ValueOrNext) { -// if (typeof value === 'function') { -// this.#next = this.#continueDecodeValue.bind(this, cb, value); -// return true; -// } - -// cb(value); -// return false; -// } - -// #continueDecodeValue( -// cb: ValueCb, -// next: Next, -// chunk: Buffer -// ) { -// this.#next = undefined; -// return this.#handleDecodedValue(cb, next(chunk)); -// } - -// #decodeNull() { -// this.#cursor += 2; // skip \r\n -// return null; -// } - -// #decodeBoolean(chunk: Buffer) { -// const boolean = chunk[this.#cursor] === ASCII['t']; -// this.#cursor += 3; // skip {t | f}\r\n -// return boolean; -// } - -// #decodeNumber(chunk: Buffer) { -// const isNegative = chunk[this.#cursor] === ASCII['-']; -// if (isNegative && ++this.#cursor === chunk.length) { -// return this.#continueDecodeNumber.bind( -// this, -// isNegative, -// this.#decodeUnsingedNumber.bind(this, 0) -// ); -// } - -// const number = this.#decodeUnsingedNumber(0, chunk); -// return typeof number === 'function' ? -// this.#continueDecodeNumber.bind(this, isNegative, number) : -// isNegative ? -number : number; -// } - -// #continueDecodeNumber( -// isNegative: boolean, -// numberCb: Next, -// chunk: Buffer -// ): ValueOrNext { -// const number = numberCb(chunk); -// return typeof number === 'function' ? -// this.#continueDecodeNumber.bind(this, isNegative, number) : -// isNegative ? -number : number; -// } - -// #decodeUnsingedNumber( -// number: number, -// chunk: Buffer -// ): ValueOrNext { -// let cursor = this.#cursor; -// do { -// const byte = chunk[cursor]; -// if (byte === ASCII['\r']) { -// this.#cursor = cursor + 2; // skip \r\n -// return number; -// } -// number = number * 10 + byte - ASCII['0']; -// } while (++cursor < chunk.length); - -// this.#cursor = cursor; -// return this.#decodeUnsingedNumber.bind(this, number); -// } - -// #decodeBigNumber(flag: Flags[typeof TYPES.BIG_NUMBER], chunk: Buffer) { -// if (flag === String) { -// return this.#decodeSimpleString(String, chunk); -// } - -// const isNegative = chunk[this.#cursor] === ASCII['-']; -// if (isNegative && ++this.#cursor === chunk.length) { -// return this.#continueDecodeBigNumber.bind( -// this, -// isNegative, -// this.#decodeUnsingedBigNumber.bind(this, 0n) -// ); -// } - -// const bigNumber = this.#decodeUnsingedBigNumber(0n, chunk); -// return typeof bigNumber === 'function' ? -// this.#continueDecodeBigNumber.bind(this, isNegative, bigNumber) : -// isNegative ? -bigNumber : bigNumber; -// } - -// #continueDecodeBigNumber( -// isNegative: boolean, -// bigNumberCb: Next, -// chunk: Buffer -// ): ValueOrNext { -// const bigNumber = bigNumberCb(chunk); -// return typeof bigNumber === 'function' ? -// this.#continueDecodeBigNumber.bind(this, isNegative, bigNumber) : -// isNegative ? -bigNumber : bigNumber; -// } - -// #decodeUnsingedBigNumber( -// bigNumber: bigint, -// chunk: Buffer -// ): ValueOrNext { -// let cursor = this.#cursor; -// do { -// const byte = chunk[cursor]; -// if (byte === ASCII['\r']) { -// this.#cursor = cursor + 2; // skip \r\n -// return bigNumber; -// } -// bigNumber = bigNumber * 10n + BigInt(byte - ASCII['0']); -// } while (++cursor < chunk.length); - -// this.#cursor = cursor; -// return this.#decodeUnsingedBigNumber.bind(this, bigNumber); -// } - -// #decodeDouble(flag: Flags[RespTypes['DOUBLE']], chunk: Buffer) { -// if (flag === String) { -// return this.#decodeSimpleString(String, chunk); -// } - -// switch (chunk[this.#cursor]) { -// case ASCII['n']: -// this.#cursor += 5; // skip nan\r\n -// return NaN; - -// case ASCII['-']: -// return ++this.#cursor === chunk.length ? -// this.#decodeDoubleInteger.bind(this, true, 0, chunk) : -// this.#decodeDoubleInteger(true, 0, chunk); - -// default: -// return this.#decodeDoubleInteger(false, 0, chunk); -// } -// } - -// #decodeDoubleInteger( -// isNegative: boolean, -// integer: number, -// chunk: Buffer -// ) { -// if (chunk[this.#cursor] === ASCII['i']) { -// this.#cursor += 5; // skip inf\r\n -// return isNegative ? -Infinity : Infinity; -// } - -// return this.#continueDecodeDoubleInteger(isNegative, integer, chunk); -// } - -// #continueDecodeDoubleInteger( -// isNegative: boolean, -// integer: number, -// chunk: Buffer -// ): ValueOrNext { -// let cursor = this.#cursor; -// do { -// const byte = chunk[cursor]; -// switch (byte) { -// case ASCII['.']: -// this.#cursor = ++cursor; -// return cursor < chunk.length ? -// this.#decodeDoubleDecimal(isNegative, 0, integer, chunk) : -// this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer); - -// case ASCII['\r']: -// this.#cursor = cursor + 2; // skip \r\n -// return isNegative ? -integer : integer; - -// default: -// integer = integer * 10 + byte - ASCII['0']; -// } -// } while (++cursor < chunk.length); - -// this.#cursor = cursor; -// return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer); -// } - -// // Precalculated multipliers for decimal points to improve performance -// // "A Number only keeps about 17 decimal places of precision" -// // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number -// static #DOUBLE_DECIMAL_MULTIPLIERS = [ -// 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, -// 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, -// 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 -// ]; - -// #decodeDoubleDecimal( -// isNegative: boolean, -// decimalIndex: number, -// double: number, -// chunk: Buffer -// ): ValueOrNext { -// let cursor = this.#cursor; -// do { -// const byte = chunk[cursor]; -// if (byte === ASCII['\r']) { -// this.#cursor = cursor + 2; // skip \r\n -// return isNegative ? -double : double; -// } - -// if (decimalIndex < Decoder.#DOUBLE_DECIMAL_MULTIPLIERS.length) { -// double += (byte - ASCII['0']) * Decoder.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; -// } -// } while (++cursor < chunk.length); - -// this.#cursor = cursor; -// return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); -// } - -// #findCRLF(chunk: Buffer, cursor: number) { -// while (chunk[cursor] !== ASCII['\r']) { -// if (++cursor === chunk.length) { -// this.#cursor = chunk.length; -// return -1; -// } -// } - -// this.#cursor = cursor + 2; // skip \r\n -// return cursor; -// } - -// #decodeSimpleString( -// flag: F, -// chunk: Buffer -// ): ValueOrNext ? T : never> { -// const start = this.#cursor, -// crlfIndex = this.#findCRLF(chunk, start); -// if (crlfIndex === -1) { -// return this.#continueDecodeSimpleString.bind( -// this, -// [chunk.subarray(start)], -// flag -// ); -// } - -// const slice = chunk.subarray(start, crlfIndex); -// return (flag === Buffer ? -// slice : -// slice.toString()) as (F extends Flag ? T : never); -// } - -// #continueDecodeSimpleString( -// chunks: Array, -// flag: F, -// chunk: Buffer -// ): ValueOrNext ? T : never> { -// const start = this.#cursor, -// crlfIndex = this.#findCRLF(chunk, start); -// if (crlfIndex === -1) { -// chunks.push(chunk.subarray(start)); -// return this.#continueDecodeSimpleString.bind(this, chunks, flag) as Next ? T : never>; -// } - -// chunks.push(chunk.subarray(start, crlfIndex)); -// return (flag === Buffer ? -// Buffer.concat(chunks) : -// chunks.join('')) as ValueOrNext ? T : never>; -// } - -// #decodeBlobString(flag: Flags[RespTypes['BLOB_STRING']], chunk: Buffer) { -// // RESP 2 bulk string null -// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings -// if (chunk[this.#cursor] === ASCII['-']) { -// this.#cursor += 4; // skip -1\r\n -// return null; -// } - -// const length = this.#decodeUnsingedNumber(0, chunk); -// if (typeof length === 'function') { -// return this.#continueDecodeBlobStringLength.bind(this, length, flag); -// } else if (this.#cursor >= chunk.length) { -// return this.#decodeBlobStringWithLength.bind(this, length, flag); -// } - -// return this.#decodeBlobStringWithLength(length, flag, chunk); -// } - -// #continueDecodeBlobStringLength( -// lengthCb: Next, -// flag: Flags[RespTypes['BLOB_STRING']], -// chunk: Buffer -// ): ValueOrNext { -// const length = lengthCb(chunk); -// if (typeof length === 'function') { -// return this.#continueDecodeBlobStringLength.bind(this, length, flag); -// } else if (this.#cursor >= chunk.length) { -// return this.#decodeBlobStringWithLength.bind(this, length, flag); -// } - -// return this.#decodeBlobStringWithLength(length, flag, chunk); -// } - -// #decodeBlobStringWithLength( -// length: number, -// flag: Flags[RespTypes['BLOB_STRING']], -// chunk: Buffer -// ) { -// const end = this.#cursor + length; -// if (end >= chunk.length) { -// const slice = chunk.subarray(this.#cursor); -// this.#cursor = chunk.length; -// return this.#continueDecodeBlobStringWithLength.bind( -// this, -// length - slice.length, -// [slice], -// flag -// ); -// } - -// const slice = chunk.subarray(this.#cursor, end); -// this.#cursor = end + 2; // skip ${string}\r\n -// return flag === Buffer ? -// slice : -// slice.toString(); -// } - -// #continueDecodeBlobStringWithLength( -// length: number, -// chunks: Array, -// flag: Flags[RespTypes['BLOB_STRING']], -// chunk: Buffer -// ): ValueOrNext { -// const end = this.#cursor + length; -// if (end >= chunk.length) { -// const slice = chunk.subarray(this.#cursor); -// chunks.push(slice); -// this.#cursor = chunk.length; -// return this.#continueDecodeBlobStringWithLength.bind( -// this, -// length - slice.length, -// chunks, -// flag -// ); -// } - -// chunks.push(chunk.subarray(this.#cursor, end)); -// this.#cursor = end + 2; // skip ${string}\r\n -// return flag === Buffer ? -// Buffer.concat(chunks) : -// chunks.join(''); -// } - -// #decodeSimpleError(chunk: Buffer) { -// const string = this.#decodeSimpleString(String, chunk); -// return typeof string === 'function' ? -// this.#continueDecodeSimpleError.bind(this, string) : -// new Error(string); // TODO use custom error -// } - -// #continueDecodeSimpleError(stringCb, chunk) { -// const string = stringCb(chunk); -// return typeof string === 'function' ? -// this.#continueDecodeSimpleError.bind(this, string) : -// new Error(string); // TODO use custom error -// } - -// #decodeBlobError(chunk) { -// const string = this.#decodeBlobString(String, chunk); -// return typeof string === 'function' ? -// this.#continueDecodeBlobError.bind(this, string) : -// new Error(string); // TODO use custom error -// } - -// #continueDecodeBlobError(stringCb, chunk) { -// const string = stringCb(chunk); -// return typeof string === 'function' ? -// this.#continueDecodeBlobError.bind(this, string) : -// new Error(string); // TODO use custom error -// } - -// #decodeNestedType(flags, chunk) { -// const type = chunk[this.#cursor]; -// return ++this.#cursor === chunk.length ? -// this.#decodeReplyValue.bind(this, type, flags) : -// this.#decodeReplyValue(type, flags, chunk); -// } - -// #decodeArray(flags, chunk) { -// // RESP 2 null -// // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays -// if (chunk[this.#cursor] === ASCII['-']) { -// this.#cursor += 4; // skip -1\r\n -// return null; -// } - -// return this.#decodeArrayWithLength( -// this.#decodeUnsingedNumber(0, chunk), -// flags, -// chunk -// ); -// } - -// #decodeArrayWithLength(length, flags, chunk) { -// return typeof length === 'function' ? -// this.#continueDecodeArrayLength.bind(this, length, flags) : -// this.#decodeArrayItems( -// new Array(length), -// 0, -// flags, -// chunk -// ); -// } - -// #continueDecodeArrayLength(lengthCb, flags, chunk) { -// return this.#decodeArrayWithLength( -// lengthCb(chunk), -// flags, -// chunk -// ); -// } - -// #decodeArrayItems(array, filled, flags, chunk) { -// for (let i = filled; i < array.length; i++) { -// if (this.#cursor >= chunk.length) { -// return this.#decodeArrayItems.bind( -// this, -// array, -// i, -// flags -// ); -// } - -// const item = this.#decodeNestedType(flags, chunk); -// if (typeof item === 'function') { -// return this.#continueDecodeArrayItems.bind( -// this, -// array, -// i, -// item, -// flags -// ); -// } - -// array[i] = item; -// } - -// return array; -// } - -// #continueDecodeArrayItems(array, filled, itemCb, flags, chunk) { -// const item = itemCb(chunk); -// if (typeof item === 'function') { -// return this.#continueDecodeArrayItems.bind( -// this, -// array, -// filled, -// item, -// flags -// ); -// } - -// array[filled++] = item; - -// return this.#decodeArrayItems(array, filled, flags, chunk); -// } - -// #decodeSet(flags, chunk) { -// const length = this.#decodeUnsingedNumber(0, chunk); -// if (typeof length === 'function') { -// return this.#continueDecodeSetLength.bind(this, length, flags); -// } - -// return this.#decodeSetItems( -// length, -// flags, -// chunk -// ); -// } - -// #continueDecodeSetLength(lengthCb, flags, chunk) { -// const length = lengthCb(chunk); -// return typeof length === 'function' ? -// this.#continueDecodeSetLength.bind(this, length, flags) : -// this.#decodeSetItems(length, flags, chunk); -// } - -// #decodeSetItems(length, flags, chunk) { -// return flags[TYPES.SET] === Set ? -// this.#decodeSetAsSet( -// new Set(), -// length, -// flags, -// chunk -// ) : -// this.#decodeArrayItems( -// new Array(length), -// 0, -// flags, -// chunk -// ); -// } - -// #decodeSetAsSet(set, remaining, flags, chunk) { -// // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates -// while (remaining > 0) { -// if (this.#cursor >= chunk.length) { -// return this.#decodeSetAsSet.bind( -// this, -// set, -// remaining, -// flags -// ); -// } - -// const item = this.#decodeNestedType(flags, chunk); -// if (typeof item === 'function') { -// return this.#continueDecodeSetAsSet.bind( -// this, -// set, -// remaining, -// item, -// flags -// ); -// } - -// set.add(item); -// --remaining; -// } - -// return set; -// } - -// #continueDecodeSetAsSet(set, remaining, itemCb, flags, chunk) { -// const item = itemCb(chunk); -// if (typeof item === 'function') { -// return this.#continueDecodeSetAsSet.bind( -// this, -// set, -// remaining, -// item, -// flags -// ); -// } - -// set.add(item); - -// return this.#decodeSetAsSet(set, remaining - 1, flags, chunk); -// } - -// #decodeMap(flags, chunk) { -// const length = this.#decodeUnsingedNumber(0, chunk); -// if (typeof length === 'function') { -// return this.#continueDecodeMapLength.bind(this, length, flags); -// } - -// return this.#decodeMapItems( -// length, -// flags, -// chunk -// ); -// } - -// #continueDecodeMapLength(lengthCb, flags, chunk) { -// const length = lengthCb(chunk); -// return typeof length === 'function' ? -// this.#continueDecodeMapLength.bind(this, length, flags) : -// this.#decodeMapItems(length, flags, chunk); -// } - -// #decodeMapItems(length, flags, chunk) { -// switch (flags[TYPES.MAP]) { -// case Map: -// return this.#decodeMapAsMap( -// new Map(), -// length, -// flags, -// chunk -// ); - -// case Array: -// return this.#decodeArrayItems( -// new Array(length * 2), -// 0, -// flags, -// chunk -// ); - -// default: -// return this.#decodeMapAsObject( -// Object.create(null), -// length, -// flags, -// chunk -// ); -// } -// } - -// #decodeMapAsMap(map, remaining, flags, chunk) { -// // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys -// while (remaining > 0) { -// if (this.#cursor >= chunk.length) { -// return this.#decodeMapAsMap.bind( -// this, -// map, -// remaining, -// flags -// ); -// } - -// const key = this.#decodeMapKey(flags, chunk); -// if (typeof key === 'function') { -// return this.#continueDecodeMapKey.bind( -// this, -// map, -// remaining, -// key, -// flags -// ); -// } - -// if (this.#cursor >= chunk.length) { -// return this.#continueDecodeMapValue.bind( -// this, -// map, -// remaining, -// key, -// this.#decodeNestedType.bind(this, flags), -// flags -// ); -// } - -// const value = this.#decodeNestedType(flags, chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapValue.bind( -// this, -// map, -// remaining, -// key, -// value, -// flags -// ); -// } - -// map.set(key, value); -// --remaining; -// } - -// return map; -// } - -// #decodeMapKey(flags, chunk) { -// const type = chunk[this.#cursor]; -// return ++this.#cursor === chunk.length ? -// this.#decodeMapKeyValue.bind(this, type, flags) : -// this.#decodeMapKeyValue(type, flags, chunk); -// } - -// #decodeMapKeyValue(type, flags, chunk) { -// switch (type) { -// // decode simple string map key as string (and not as buffer) -// case TYPES.SIMPLE_STRING: -// return this.#decodeSimpleString(String, chunk); - -// // decode blob string map key as string (and not as buffer) -// case TYPES.BLOB_STRING: -// return this.#decodeBlobString(String, chunk); - -// default: -// return this.#decodeReplyValue(type, flags, chunk); -// } -// } - -// #continueDecodeMapKey(map, remaining, keyCb, flags, chunk) { -// const key = keyCb(chunk); -// if (typeof key === 'function') { -// return this.#continueDecodeMapKey.bind( -// this, -// map, -// remaining, -// key, -// flags -// ); -// } - -// if (this.#cursor >= chunk.length) { -// return this.#continueDecodeMapValue.bind( -// this, -// map, -// remaining, -// key, -// this.#decodeNestedType.bind(this, flags), -// flags -// ); -// } - -// const value = this.#decodeNestedType(flags, chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapValue.bind( -// this, -// map, -// remaining, -// key, -// value, -// flags -// ); -// } - -// map.set(key, value); -// return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); -// } - -// #continueDecodeMapValue(map, remaining, key, valueCb, flags, chunk) { -// const value = valueCb(chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapValue.bind( -// this, -// map, -// remaining, -// key, -// value, -// flags -// ); -// } - -// map.set(key, value); - -// return this.#decodeMapAsMap(map, remaining - 1, flags, chunk); -// } - -// #decodeMapAsObject(object, remaining, flags, chunk) { -// while (remaining > 0) { -// if (this.#cursor >= chunk.length) { -// return this.#decodeMapAsObject.bind( -// this, -// object, -// remaining, -// flags -// ); -// } - -// const key = this.#decodeMapKey(flags, chunk); -// if (typeof key === 'function') { -// return this.#continueDecodeMapAsObjectKey.bind( -// this, -// object, -// remaining, -// key, -// flags -// ); -// } - -// if (this.#cursor >= chunk.length) { -// return this.#continueDecodeMapAsObjectValue.bind( -// this, -// object, -// remaining, -// key, -// this.#decodeNestedType.bind(this, flags), -// flags -// ); -// } - -// const value = this.#decodeNestedType(flags, chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapAsObjectValue.bind( -// this, -// object, -// remaining, -// key, -// value, -// flags -// ); -// } - -// object[key] = value; -// --remaining; -// } - -// return object; -// } - -// #continueDecodeMapAsObjectKey(object, remaining, keyCb, flags, chunk) { -// const key = keyCb(chunk); -// if (typeof key === 'function') { -// return this.#continueDecodeMapAsObjectKey.bind( -// this, -// object, -// remaining, -// key, -// flags -// ); -// } - -// if (this.#cursor >= chunk.length) { -// return this.#continueDecodeMapAsObjectValue.bind( -// this, -// object, -// remaining, -// key, -// this.#decodeNestedType.bind(this, flags), -// flags -// ); -// } - -// const value = this.#decodeNestedType(flags, chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapAsObjectValue.bind( -// this, -// object, -// remaining, -// key, -// value, -// flags -// ); -// } - -// object[key] = value; - -// return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); -// } - -// #continueDecodeMapAsObjectValue(object, remaining, key, valueCb, flags, chunk) { -// const value = valueCb(chunk); -// if (typeof value === 'function') { -// return this.#continueDecodeMapAsObjectValue.bind( -// this, -// object, -// remaining, -// key, -// value, -// flags -// ); -// } - -// object[key] = value; - -// return this.#decodeMapAsObject(object, remaining - 1, flags, chunk); -// } -// } - -// const a = new Decoder({ -// onReply(reply) { -// console.log('[REPLY]', reply); -// }, -// onErrorReply(err) { -// console.log('[ERROR REPLY]', err); -// }, -// onPush(push) { -// console.log('[PUSH]', push); -// }, -// getFlags() { -// return {}; -// } -// }); - -// a.write(Buffer.from('+PONG\r\n')); diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 8003590e70b..9ffcf815ed9 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -1,981 +1,952 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; -// import RedisClient, { RedisClientType } from '.'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; +import RedisClient, { RedisClientType } from '.'; // import { RedisClientMultiCommandType } from './multi-command'; // import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; // import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; -// import { defineScript } from '../lua-script'; +import { defineScript } from '../lua-script'; // import { spy } from 'sinon'; // import { once } from 'events'; // import { ClientKillFilters } from '../commands/CLIENT_KILL'; // import { promisify } from 'util'; -// export const SQUARE_SCRIPT = defineScript({ -// SCRIPT: 'return ARGV[1] * ARGV[1];', -// NUMBER_OF_KEYS: 0, -// transformArguments(number: number): Array { -// return [number.toString()]; -// } -// }); - -// export const MATH_FUNCTION = { -// name: 'math', -// engine: 'LUA', -// code: `#!LUA name=math -// redis.register_function{ -// function_name = "square", -// callback = function(keys, args) return args[1] * args[1] end, -// flags = { "no-writes" } -// }`, -// library: { -// square: { -// NAME: 'square', -// IS_READ_ONLY: true, -// NUMBER_OF_KEYS: 0, -// transformArguments(number: number): Array { -// return [number.toString()]; -// } -// } -// } -// }; - -// export async function loadMathFunction( -// client: RedisClientType -// ): Promise { -// await client.functionLoad( -// MATH_FUNCTION.code, -// { REPLACE: true } -// ); -// } - -// describe('Client', () => { -// describe('parseURL', () => { -// it('redis://user:secret@localhost:6379/0', () => { -// assert.deepEqual( -// RedisClient.parseURL('redis://user:secret@localhost:6379/0'), -// { -// socket: { -// host: 'localhost', -// port: 6379 -// }, -// username: 'user', -// password: 'secret', -// database: 0 -// } -// ); -// }); - -// it('rediss://user:secret@localhost:6379/0', () => { -// assert.deepEqual( -// RedisClient.parseURL('rediss://user:secret@localhost:6379/0'), -// { -// socket: { -// host: 'localhost', -// port: 6379, -// tls: true -// }, -// username: 'user', -// password: 'secret', -// database: 0 -// } -// ); -// }); - -// it('Invalid protocol', () => { -// assert.throws( -// () => RedisClient.parseURL('redi://user:secret@localhost:6379/0'), -// TypeError -// ); -// }); +export const SQUARE_SCRIPT = defineScript({ + SCRIPT: 'return ARGV[1] * ARGV[1];', + NUMBER_OF_KEYS: 0, + transformArguments(number: number): Array { + return [number.toString()]; + }, + transformReply: undefined as unknown as () => number +}); + +describe('Client', () => { + describe('parseURL', () => { + it('redis://user:secret@localhost:6379/0', () => { + assert.deepEqual( + RedisClient.parseURL('redis://user:secret@localhost:6379/0'), + { + socket: { + host: 'localhost', + port: 6379 + }, + username: 'user', + password: 'secret', + database: 0 + } + ); + }); + + it('rediss://user:secret@localhost:6379/0', () => { + assert.deepEqual( + RedisClient.parseURL('rediss://user:secret@localhost:6379/0'), + { + socket: { + host: 'localhost', + port: 6379, + tls: true + }, + username: 'user', + password: 'secret', + database: 0 + } + ); + }); + + it('Invalid protocol', () => { + assert.throws( + () => RedisClient.parseURL('redi://user:secret@localhost:6379/0'), + TypeError + ); + }); + + it('Invalid pathname', () => { + assert.throws( + () => RedisClient.parseURL('redis://user:secret@localhost:6379/NaN'), + TypeError + ); + }); + + it('redis://localhost', () => { + assert.deepEqual( + RedisClient.parseURL('redis://localhost'), + { + socket: { + host: 'localhost', + } + } + ); + }); + }); + + describe('authentication', () => { + testUtils.testWithClient('Client should be authenticated', async client => { + assert.equal( + await client.ping(), + 'PONG' + ); + }, GLOBAL.SERVERS.PASSWORD); + + testUtils.testWithClient('should execute AUTH before SELECT', async client => { + assert.equal( + (await client.clientInfo()).db, + 2 + ); + }, { + ...GLOBAL.SERVERS.PASSWORD, + clientOptions: { + ...GLOBAL.SERVERS.PASSWORD.clientOptions, + database: 2 + }, + minimumDockerVersion: [6, 2] + }); + }); + + testUtils.testWithClient('should set connection name', async client => { + assert.equal( + await client.clientGetName(), + 'name' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + name: 'name' + } + }); + +// describe('legacyMode', () => { +// testUtils.testWithClient('client.sendCommand should call the callback', async client => { +// assert.equal( +// await promisify(client.sendCommand).call(client, 'PING'), +// 'PONG' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// it('Invalid pathname', () => { -// assert.throws( -// () => RedisClient.parseURL('redis://user:secret@localhost:6379/NaN'), -// TypeError -// ); -// }); +// testUtils.testWithClient('client.sendCommand should work without callback', async client => { +// client.sendCommand(['PING']); +// await client.v4.ping(); // make sure the first command was replied +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// it('redis://localhost', () => { -// assert.deepEqual( -// RedisClient.parseURL('redis://localhost'), -// { -// socket: { -// host: 'localhost', -// } -// } -// ); -// }); +// testUtils.testWithClient('client.sendCommand should reply with error', async client => { +// await assert.rejects( +// promisify(client.sendCommand).call(client, '1', '2') +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } // }); -// describe('authentication', () => { -// testUtils.testWithClient('Client should be authenticated', async client => { -// assert.equal( -// await client.ping(), -// 'PONG' -// ); -// }, GLOBAL.SERVERS.PASSWORD); - -// testUtils.testWithClient('should execute AUTH before SELECT', async client => { -// assert.equal( -// (await client.clientInfo()).db, -// 2 -// ); -// }, { -// ...GLOBAL.SERVERS.PASSWORD, -// clientOptions: { -// ...GLOBAL.SERVERS.PASSWORD.clientOptions, -// database: 2 -// }, -// minimumDockerVersion: [6, 2] -// }); +// testUtils.testWithClient('client.hGetAll should reply with error', async client => { +// await assert.rejects( +// promisify(client.hGetAll).call(client) +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } // }); -// testUtils.testWithClient('should set connection name', async client => { -// assert.equal( -// await client.clientGetName(), -// 'name' -// ); +// testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { +// assert.equal( +// await client.v4.sendCommand(['PING']), +// 'PONG' +// ); // }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// name: 'name' -// } +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } // }); -// describe('legacyMode', () => { -// testUtils.testWithClient('client.sendCommand should call the callback', async client => { -// assert.equal( -// await promisify(client.sendCommand).call(client, 'PING'), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.v4.{command} should return a promise', async client => { +// assert.equal( +// await client.v4.ping(), +// 'PONG' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.sendCommand should work without callback', async client => { -// client.sendCommand(['PING']); -// await client.v4.ping(); // make sure the first command was replied -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { +// assert.equal( +// await promisify(client.set).call(client, 'a', 'b'), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.sendCommand should reply with error', async client => { -// await assert.rejects( -// promisify(client.sendCommand).call(client, '1', '2') -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.{command} should accept arguments array', async client => { +// assert.equal( +// await promisify(client.set).call(client, ['a', 'b']), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.hGetAll should reply with error', async client => { -// await assert.rejects( -// promisify(client.hGetAll).call(client) -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { +// assert.equal( +// await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), +// 'OK' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { -// assert.equal( -// await client.v4.sendCommand(['PING']), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.hGetAll should return object', async client => { +// await client.v4.hSet('key', 'field', 'value'); + +// assert.deepEqual( +// await promisify(client.hGetAll).call(client, 'key'), +// Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true +// } +// }) +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.v4.{command} should return a promise', async client => { -// assert.equal( -// await client.v4.ping(), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// function multiExecAsync< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// >(multi: RedisClientMultiCommandType): Promise> { +// return new Promise((resolve, reject) => { +// (multi as any).exec((err: Error | undefined, replies: Array) => { +// if (err) return reject(err); -// testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { -// assert.equal( -// await promisify(client.set).call(client, 'a', 'b'), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } +// resolve(replies); // }); +// }); +// } -// testUtils.testWithClient('client.{command} should accept arguments array', async client => { -// assert.equal( -// await promisify(client.set).call(client, ['a', 'b']), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { +// assert.deepEqual( +// await multiExecAsync( +// client.multi().ping() +// ), +// ['PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { -// assert.equal( -// await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { +// client.multi() +// .ping() +// .exec(); +// await client.v4.ping(); // make sure the first command was replied +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.hGetAll should return object', async client => { -// await client.v4.hSet('key', 'field', 'value'); - -// assert.deepEqual( -// await promisify(client.hGetAll).call(client, 'key'), -// Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .v4.ping() +// .v4.exec(), +// ['PONG', 'PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// function multiExecAsync< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// >(multi: RedisClientMultiCommandType): Promise> { -// return new Promise((resolve, reject) => { -// (multi as any).exec((err: Error | undefined, replies: Array) => { -// if (err) return reject(err); - -// resolve(replies); -// }); -// }); +// testUtils.testWithClient('client.{script} should return a promise', async client => { +// assert.equal( +// await client.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true, +// scripts: { +// square: SQUARE_SCRIPT // } +// } +// }); -// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { -// assert.deepEqual( -// await multiExecAsync( -// client.multi().ping() -// ), -// ['PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { -// client.multi() -// .ping() -// .exec(); -// await client.v4.ping(); // make sure the first command was replied -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('client.multi.{command}.exec should flatten array arguments', async client => { +// assert.deepEqual( +// await client.multi() +// .sAdd('a', ['b', 'c']) +// .v4.exec(), +// [2] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); -// testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .v4.ping() -// .v4.exec(), -// ['PONG', 'PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true +// testUtils.testWithClient('client.multi.hGetAll should return object', async client => { +// assert.deepEqual( +// await multiExecAsync( +// client.multi() +// .hSet('key', 'field', 'value') +// .hGetAll('key') +// ), +// [ +// 1, +// Object.create(null, { +// field: { +// value: 'value', +// configurable: true, +// enumerable: true // } -// }); +// }) +// ] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// legacyMode: true +// } +// }); +// }); + +// describe('events', () => { +// testUtils.testWithClient('connect, ready, end', async client => { +// await Promise.all([ +// once(client, 'connect'), +// once(client, 'ready'), +// client.connect() +// ]); + +// await Promise.all([ +// once(client, 'end'), +// client.disconnect() +// ]); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); +// }); -// testUtils.testWithClient('client.{script} should return a promise', async client => { -// assert.equal( -// await client.square(2), -// 4 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true, -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); +// describe('sendCommand', () => { +// testUtils.testWithClient('PING', async client => { +// assert.equal(await client.sendCommand(['PING']), 'PONG'); +// }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('client.multi.{command}.exec should flatten array arguments', async client => { -// assert.deepEqual( -// await client.multi() -// .sAdd('a', ['b', 'c']) -// .v4.exec(), -// [2] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); +// testUtils.testWithClient('returnBuffers', async client => { +// assert.deepEqual( +// await client.sendCommand(['PING'], { +// returnBuffers: true +// }), +// Buffer.from('PONG') +// ); +// }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('client.multi.hGetAll should return object', async client => { -// assert.deepEqual( -// await multiExecAsync( -// client.multi() -// .hSet('key', 'field', 'value') -// .hGetAll('key') -// ), -// [ -// 1, -// Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// ] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); -// }); +// describe('AbortController', () => { +// before(function () { +// if (!global.AbortController) { +// this.skip(); +// } +// }); -// describe('events', () => { -// testUtils.testWithClient('connect, ready, end', async client => { -// await Promise.all([ -// once(client, 'connect'), -// once(client, 'ready'), -// client.connect() -// ]); - -// await Promise.all([ -// once(client, 'end'), -// client.disconnect() -// ]); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true +// testUtils.testWithClient('success', async client => { +// await client.sendCommand(['PING'], { +// signal: new AbortController().signal // }); -// }); +// }, GLOBAL.SERVERS.OPEN); -// describe('sendCommand', () => { -// testUtils.testWithClient('PING', async client => { -// assert.equal(await client.sendCommand(['PING']), 'PONG'); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('returnBuffers', async client => { -// assert.deepEqual( -// await client.sendCommand(['PING'], { -// returnBuffers: true -// }), -// Buffer.from('PONG') -// ); -// }, GLOBAL.SERVERS.OPEN); - -// describe('AbortController', () => { -// before(function () { -// if (!global.AbortController) { -// this.skip(); -// } -// }); - -// testUtils.testWithClient('success', async client => { -// await client.sendCommand(['PING'], { -// signal: new AbortController().signal -// }); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('AbortError', client => { -// const controller = new AbortController(); -// controller.abort(); - -// return assert.rejects( -// client.sendCommand(['PING'], { -// signal: controller.signal -// }), -// AbortError -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); +// testUtils.testWithClient('AbortError', client => { +// const controller = new AbortController(); +// controller.abort(); -// testUtils.testWithClient('undefined and null should not break the client', async client => { -// await assert.rejects( -// client.sendCommand([null as any, undefined as any]), -// TypeError -// ); - -// assert.equal( -// await client.ping(), -// 'PONG' -// ); -// }, GLOBAL.SERVERS.OPEN); +// return assert.rejects( +// client.sendCommand(['PING'], { +// signal: controller.signal +// }), +// AbortError +// ); +// }, GLOBAL.SERVERS.OPEN); // }); -// describe('multi', () => { -// testUtils.testWithClient('simple', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .set('key', 'value') -// .get('key') -// .exec(), -// ['PONG', 'OK', 'value'] -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should reject the whole chain on error', client => { -// return assert.rejects( -// client.multi() -// .ping() -// .addCommand(['INVALID COMMAND']) -// .ping() -// .exec() -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { -// await client.disconnect(); - -// return assert.rejects( -// client.multi() -// .ping() -// .set('key', 'value') -// .get('key') -// .exec(), -// ClientClosedError -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('with script', async client => { -// assert.deepEqual( -// await client.multi() -// .square(2) -// .exec(), -// [4] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); +// testUtils.testWithClient('undefined and null should not break the client', async client => { +// await assert.rejects( +// client.sendCommand([null as any, undefined as any]), +// TypeError +// ); -// testUtils.testWithClient('WatchError', async client => { -// await client.watch('key'); - -// await client.set( -// RedisClient.commandOptions({ -// isolated: true -// }), -// 'key', -// '1' -// ); - -// await assert.rejects( -// client.multi() -// .decr('key') -// .exec(), -// WatchError -// ); -// }, GLOBAL.SERVERS.OPEN); - -// describe('execAsPipeline', () => { -// testUtils.testWithClient('exec(true)', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .exec(true), -// ['PONG'] -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('empty execAsPipeline', async client => { -// assert.deepEqual( -// await client.multi().execAsPipeline(), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); +// assert.equal( +// await client.ping(), +// 'PONG' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// describe('multi', () => { +// testUtils.testWithClient('simple', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .set('key', 'value') +// .get('key') +// .exec(), +// ['PONG', 'OK', 'value'] +// ); +// }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('should remember selected db', async client => { -// await client.multi() -// .select(1) -// .exec(); -// await killClient(client); -// assert.equal( -// (await client.clientInfo()).db, -// 1 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [6, 2] // CLIENT INFO -// }); -// }); +// testUtils.testWithClient('should reject the whole chain on error', client => { +// return assert.rejects( +// client.multi() +// .ping() +// .addCommand(['INVALID COMMAND']) +// .ping() +// .exec() +// ); +// }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('scripts', async client => { -// assert.equal( -// await client.square(2), -// 4 -// ); +// testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { +// await client.disconnect(); + +// return assert.rejects( +// client.multi() +// .ping() +// .set('key', 'value') +// .get('key') +// .exec(), +// ClientClosedError +// ); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('with script', async client => { +// assert.deepEqual( +// await client.multi() +// .square(2) +// .exec(), +// [4] +// ); // }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// scripts: { -// square: SQUARE_SCRIPT -// } +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// scripts: { +// square: SQUARE_SCRIPT // } +// } // }); -// const module = { -// echo: { -// transformArguments(message: string): Array { -// return ['ECHO', message]; -// }, -// transformReply(reply: string): string { -// return reply; -// } -// } -// }; +// testUtils.testWithClient('WatchError', async client => { +// await client.watch('key'); + +// await client.set( +// RedisClient.commandOptions({ +// isolated: true +// }), +// 'key', +// '1' +// ); + +// await assert.rejects( +// client.multi() +// .decr('key') +// .exec(), +// WatchError +// ); +// }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('modules', async client => { -// assert.equal( -// await client.module.echo('message'), -// 'message' +// describe('execAsPipeline', () => { +// testUtils.testWithClient('exec(true)', async client => { +// assert.deepEqual( +// await client.multi() +// .ping() +// .exec(true), +// ['PONG'] // ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// modules: { -// module -// } -// } -// }); - -// testUtils.testWithClient('functions', async client => { -// await loadMathFunction(client); +// }, GLOBAL.SERVERS.OPEN); -// assert.equal( -// await client.math.square(2), -// 4 +// testUtils.testWithClient('empty execAsPipeline', async client => { +// assert.deepEqual( +// await client.multi().execAsPipeline(), +// [] // ); +// }, GLOBAL.SERVERS.OPEN); +// }); + +// testUtils.testWithClient('should remember selected db', async client => { +// await client.multi() +// .select(1) +// .exec(); +// await killClient(client); +// assert.equal( +// (await client.clientInfo()).db, +// 1 +// ); // }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [7, 0], -// clientOptions: { -// functions: { -// math: MATH_FUNCTION.library -// } -// } +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [6, 2] // CLIENT INFO // }); +// }); -// describe('isolationPool', () => { -// testUtils.testWithClient('executeIsolated', async client => { -// const id = await client.clientId(), -// isolatedId = await client.executeIsolated(isolatedClient => isolatedClient.clientId()); -// assert.ok(id !== isolatedId); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should be able to use pool even before connect', async client => { -// await client.executeIsolated(() => Promise.resolve()); -// // make sure to destroy isolation pool -// await client.connect(); -// await client.disconnect(); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); +// testUtils.testWithClient('scripts', async client => { +// assert.equal( +// await client.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// scripts: { +// square: SQUARE_SCRIPT +// } +// } +// }); + +// const module = { +// echo: { +// transformArguments(message: string): Array { +// return ['ECHO', message]; +// }, +// transformReply(reply: string): string { +// return reply; +// } +// } +// }; -// testUtils.testWithClient('should work after reconnect (#2406)', async client => { -// await client.disconnect(); -// await client.connect(); -// await client.executeIsolated(() => Promise.resolve()); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should throw ClientClosedError after disconnect', async client => { -// await client.connect(); -// await client.disconnect(); -// await assert.rejects( -// client.executeIsolated(() => Promise.resolve()), -// ClientClosedError -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); -// }); +// testUtils.testWithClient('modules', async client => { +// assert.equal( +// await client.module.echo('message'), +// 'message' +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// modules: { +// module +// } +// } +// }); -// async function killClient< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// >( -// client: RedisClientType, -// errorClient: RedisClientType = client -// ): Promise { -// const onceErrorPromise = once(errorClient, 'error'); -// await client.sendCommand(['QUIT']); -// await Promise.all([ -// onceErrorPromise, -// assert.rejects(client.ping(), SocketClosedUnexpectedlyError) -// ]); +// testUtils.testWithClient('functions', async client => { +// await loadMathFunction(client); + +// assert.equal( +// await client.math.square(2), +// 4 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [7, 0], +// clientOptions: { +// functions: { +// math: MATH_FUNCTION.library +// } // } +// }); -// testUtils.testWithClient('should reconnect when socket disconnects', async client => { -// await killClient(client); -// await assert.doesNotReject(client.ping()); +// describe('isolationPool', () => { +// testUtils.testWithClient('executeIsolated', async client => { +// const id = await client.clientId(), +// isolatedId = await client.executeIsolated(isolatedClient => isolatedClient.clientId()); +// assert.ok(id !== isolatedId); // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('should remember selected db', async client => { -// await client.select(1); -// await killClient(client); -// assert.equal( -// (await client.clientInfo()).db, -// 1 -// ); +// testUtils.testWithClient('should be able to use pool even before connect', async client => { +// await client.executeIsolated(() => Promise.resolve()); +// // make sure to destroy isolation pool +// await client.connect(); +// await client.disconnect(); // }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [6, 2] // CLIENT INFO +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true // }); -// testUtils.testWithClient('should propagated errors from "isolated" clients', client => { -// client.on('error', () => { -// // ignore errors -// }); -// return client.executeIsolated(isolated => killClient(isolated, client)); +// testUtils.testWithClient('should work after reconnect (#2406)', async client => { +// await client.disconnect(); +// await client.connect(); +// await client.executeIsolated(() => Promise.resolve()); // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('scanIterator', async client => { -// const promises = [], -// keys = new Set(); -// for (let i = 0; i < 100; i++) { -// const key = i.toString(); -// keys.add(key); -// promises.push(client.set(key, '')); -// } - -// await Promise.all(promises); - -// const results = new Set(); -// for await (const key of client.scanIterator()) { -// results.add(key); -// } - -// assert.deepEqual(keys, results); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('hScanIterator', async client => { -// const hash: Record = {}; -// for (let i = 0; i < 100; i++) { -// hash[i.toString()] = i.toString(); -// } - -// await client.hSet('key', hash); +// testUtils.testWithClient('should throw ClientClosedError after disconnect', async client => { +// await client.connect(); +// await client.disconnect(); +// await assert.rejects( +// client.executeIsolated(() => Promise.resolve()), +// ClientClosedError +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); +// }); + +// async function killClient< +// M extends RedisModules, +// F extends RedisFunctions, +// S extends RedisScripts +// >( +// client: RedisClientType, +// errorClient: RedisClientType = client +// ): Promise { +// const onceErrorPromise = once(errorClient, 'error'); +// await client.sendCommand(['QUIT']); +// await Promise.all([ +// onceErrorPromise, +// assert.rejects(client.ping(), SocketClosedUnexpectedlyError) +// ]); +// } + +// testUtils.testWithClient('should reconnect when socket disconnects', async client => { +// await killClient(client); +// await assert.doesNotReject(client.ping()); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should remember selected db', async client => { +// await client.select(1); +// await killClient(client); +// assert.equal( +// (await client.clientInfo()).db, +// 1 +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// minimumDockerVersion: [6, 2] // CLIENT INFO +// }); + +// testUtils.testWithClient('should propagated errors from "isolated" clients', client => { +// client.on('error', () => { +// // ignore errors +// }); +// return client.executeIsolated(isolated => killClient(isolated, client)); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('scanIterator', async client => { +// const promises = [], +// keys = new Set(); +// for (let i = 0; i < 100; i++) { +// const key = i.toString(); +// keys.add(key); +// promises.push(client.set(key, '')); +// } -// const results: Record = {}; -// for await (const { field, value } of client.hScanIterator('key')) { -// results[field] = value; -// } +// await Promise.all(promises); -// assert.deepEqual(hash, results); -// }, GLOBAL.SERVERS.OPEN); +// const results = new Set(); +// for await (const key of client.scanIterator()) { +// results.add(key); +// } -// testUtils.testWithClient('sScanIterator', async client => { -// const members = new Set(); -// for (let i = 0; i < 100; i++) { -// members.add(i.toString()); -// } +// assert.deepEqual(keys, results); +// }, GLOBAL.SERVERS.OPEN); -// await client.sAdd('key', Array.from(members)); +// testUtils.testWithClient('hScanIterator', async client => { +// const hash: Record = {}; +// for (let i = 0; i < 100; i++) { +// hash[i.toString()] = i.toString(); +// } -// const results = new Set(); -// for await (const key of client.sScanIterator('key')) { -// results.add(key); -// } +// await client.hSet('key', hash); -// assert.deepEqual(members, results); -// }, GLOBAL.SERVERS.OPEN); +// const results: Record = {}; +// for await (const { field, value } of client.hScanIterator('key')) { +// results[field] = value; +// } -// testUtils.testWithClient('zScanIterator', async client => { -// const members = []; -// for (let i = 0; i < 100; i++) { -// members.push({ -// score: 1, -// value: i.toString() -// }); -// } +// assert.deepEqual(hash, results); +// }, GLOBAL.SERVERS.OPEN); -// await client.zAdd('key', members); +// testUtils.testWithClient('sScanIterator', async client => { +// const members = new Set(); +// for (let i = 0; i < 100; i++) { +// members.add(i.toString()); +// } -// const map = new Map(); -// for await (const member of client.zScanIterator('key')) { -// map.set(member.value, member.score); -// } +// await client.sAdd('key', Array.from(members)); -// type MemberTuple = [string, number]; +// const results = new Set(); +// for await (const key of client.sScanIterator('key')) { +// results.add(key); +// } -// function sort(a: MemberTuple, b: MemberTuple) { -// return Number(b[0]) - Number(a[0]); -// } +// assert.deepEqual(members, results); +// }, GLOBAL.SERVERS.OPEN); -// assert.deepEqual( -// [...map.entries()].sort(sort), -// members.map(member => [member.value, member.score]).sort(sort) -// ); -// }, GLOBAL.SERVERS.OPEN); - -// describe('PubSub', () => { -// testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { -// function assertStringListener(message: string, channel: string) { -// assert.equal(typeof message, 'string'); -// assert.equal(typeof channel, 'string'); -// } +// testUtils.testWithClient('zScanIterator', async client => { +// const members = []; +// for (let i = 0; i < 100; i++) { +// members.push({ +// score: 1, +// value: i.toString() +// }); +// } -// function assertBufferListener(message: Buffer, channel: Buffer) { -// assert.ok(Buffer.isBuffer(message)); -// assert.ok(Buffer.isBuffer(channel)); -// } +// await client.zAdd('key', members); -// const subscriber = publisher.duplicate(); - -// await subscriber.connect(); - -// try { -// const channelListener1 = spy(assertBufferListener), -// channelListener2 = spy(assertStringListener), -// patternListener = spy(assertStringListener); - -// await Promise.all([ -// subscriber.subscribe('channel', channelListener1, true), -// subscriber.subscribe('channel', channelListener2), -// subscriber.pSubscribe('channel*', patternListener) -// ]); -// await Promise.all([ -// waitTillBeenCalled(channelListener1), -// waitTillBeenCalled(channelListener2), -// waitTillBeenCalled(patternListener), -// publisher.publish(Buffer.from('channel'), Buffer.from('message')) -// ]); - -// assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); -// assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); -// assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); - -// await subscriber.unsubscribe('channel', channelListener1, true); -// await Promise.all([ -// waitTillBeenCalled(channelListener2), -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); -// assert.ok(patternListener.calledTwice); -// assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); -// await subscriber.unsubscribe('channel'); -// await Promise.all([ -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(patternListener.calledThrice); -// assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); -// await subscriber.pUnsubscribe(); -// await publisher.publish('channel', 'message'); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(patternListener.calledThrice); -// // should be able to send commands when unsubsribed from all channels (see #1652) -// await assert.doesNotReject(subscriber.ping()); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); +// const map = new Map(); +// for await (const member of client.zScanIterator('key')) { +// map.set(member.value, member.score); +// } -// testUtils.testWithClient('should resubscribe', async publisher => { -// const subscriber = publisher.duplicate(); +// type MemberTuple = [string, number]; -// await subscriber.connect(); +// function sort(a: MemberTuple, b: MemberTuple) { +// return Number(b[0]) - Number(a[0]); +// } -// try { -// const channelListener = spy(); -// await subscriber.subscribe('channel', channelListener); +// assert.deepEqual( +// [...map.entries()].sort(sort), +// members.map(member => [member.value, member.score]).sort(sort) +// ); +// }, GLOBAL.SERVERS.OPEN); -// const patternListener = spy(); -// await subscriber.pSubscribe('channe*', patternListener); +// describe('PubSub', () => { +// testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { +// function assertStringListener(message: string, channel: string) { +// assert.equal(typeof message, 'string'); +// assert.equal(typeof channel, 'string'); +// } -// await Promise.all([ -// once(subscriber, 'error'), -// publisher.clientKill({ -// filter: ClientKillFilters.SKIP_ME, -// skipMe: true -// }) -// ]); +// function assertBufferListener(message: Buffer, channel: Buffer) { +// assert.ok(message instanceof Buffer); +// assert.ok(channel instanceof Buffer); +// } -// await once(subscriber, 'ready'); +// const subscriber = publisher.duplicate(); -// await Promise.all([ -// waitTillBeenCalled(channelListener), -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { -// const subscriber = publisher.duplicate(); - -// await subscriber.connect(); - -// try { -// await assert.doesNotReject(Promise.all([ -// subscriber.subscribe('channel', () => { -// // noop -// }), -// publisher.publish('channel', 'message') -// ])); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); +// await subscriber.connect(); -// testUtils.testWithClient('should be able to quit in PubSub mode', async client => { -// await client.subscribe('channel', () => { -// // noop -// }); +// try { +// const channelListener1 = spy(assertBufferListener), +// channelListener2 = spy(assertStringListener), +// patternListener = spy(assertStringListener); -// await assert.doesNotReject(client.quit()); +// await Promise.all([ +// subscriber.subscribe('channel', channelListener1, true), +// subscriber.subscribe('channel', channelListener2), +// subscriber.pSubscribe('channel*', patternListener) +// ]); +// await Promise.all([ +// waitTillBeenCalled(channelListener1), +// waitTillBeenCalled(channelListener2), +// waitTillBeenCalled(patternListener), +// publisher.publish(Buffer.from('channel'), Buffer.from('message')) +// ]); -// assert.equal(client.isOpen, false); -// }, GLOBAL.SERVERS.OPEN); -// }); +// assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); +// assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); +// assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); -// testUtils.testWithClient('ConnectionTimeoutError', async client => { -// const promise = assert.rejects(client.connect(), ConnectionTimeoutError), -// start = process.hrtime.bigint(); +// await subscriber.unsubscribe('channel', channelListener1, true); +// await Promise.all([ +// waitTillBeenCalled(channelListener2), +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') +// ]); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); +// assert.ok(patternListener.calledTwice); +// assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); +// await subscriber.unsubscribe('channel'); +// await Promise.all([ +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') +// ]); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(patternListener.calledThrice); +// assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); +// await subscriber.pUnsubscribe(); +// await publisher.publish('channel', 'message'); +// assert.ok(channelListener1.calledOnce); +// assert.ok(channelListener2.calledTwice); +// assert.ok(patternListener.calledThrice); +// // should be able to send commands when unsubsribed from all channels (see #1652) +// await assert.doesNotReject(subscriber.ping()); +// } finally { +// await subscriber.disconnect(); +// } +// }, GLOBAL.SERVERS.OPEN); -// while (process.hrtime.bigint() - start < 1_000_000) { -// // block the event loop for 1ms, to make sure the connection will timeout -// } +// testUtils.testWithClient('should resubscribe', async publisher => { +// const subscriber = publisher.duplicate(); -// await promise; -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// socket: { -// connectTimeout: 1 -// } -// }, -// disableClientSetup: true -// }); +// await subscriber.connect(); -// testUtils.testWithClient('client.quit', async client => { -// await client.connect(); +// try { +// const channelListener = spy(); +// await subscriber.subscribe('channel', channelListener); -// const pingPromise = client.ping(), -// quitPromise = client.quit(); -// assert.equal(client.isOpen, false); +// const patternListener = spy(); +// await subscriber.pSubscribe('channe*', patternListener); -// const [ping, quit] = await Promise.all([ -// pingPromise, -// quitPromise, -// assert.rejects(client.ping(), ClientClosedError) +// await Promise.all([ +// once(subscriber, 'error'), +// publisher.clientKill({ +// filter: ClientKillFilters.SKIP_ME, +// skipMe: true +// }) // ]); -// assert.equal(ping, 'PONG'); -// assert.equal(quit, 'OK'); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); +// await once(subscriber, 'ready'); -// testUtils.testWithClient('client.disconnect', async client => { -// const pingPromise = client.ping(), -// disconnectPromise = client.disconnect(); -// assert.equal(client.isOpen, false); // await Promise.all([ -// assert.rejects(pingPromise, DisconnectsClientError), -// assert.doesNotReject(disconnectPromise), -// assert.rejects(client.ping(), ClientClosedError) +// waitTillBeenCalled(channelListener), +// waitTillBeenCalled(patternListener), +// publisher.publish('channel', 'message') // ]); +// } finally { +// await subscriber.disconnect(); +// } // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { -// await client.disconnect(); -// await client.connect(); +// testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { +// const subscriber = publisher.duplicate(); + +// await subscriber.connect(); + +// try { +// await assert.doesNotReject(Promise.all([ +// subscriber.subscribe('channel', () => { +// // noop +// }), +// publisher.publish('channel', 'message') +// ])); +// } finally { +// await subscriber.disconnect(); +// } // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('should be able to use ref and unref', client => { -// client.unref(); -// client.ref(); +// testUtils.testWithClient('should be able to quit in PubSub mode', async client => { +// await client.subscribe('channel', () => { +// // noop +// }); + +// await assert.doesNotReject(client.quit()); + +// assert.equal(client.isOpen, false); // }, GLOBAL.SERVERS.OPEN); +// }); -// testUtils.testWithClient('pingInterval', async client => { -// assert.deepEqual( -// await once(client, 'ping-interval'), -// ['PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// pingInterval: 1 -// } -// }); +// testUtils.testWithClient('ConnectionTimeoutError', async client => { +// const promise = assert.rejects(client.connect(), ConnectionTimeoutError), +// start = process.hrtime.bigint(); -// testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { -// const connectPromise = client.connect(); -// await assert.rejects( -// client.ping(), -// ClientOfflineError -// ); -// await connectPromise; -// await client.disconnect(); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// disableOfflineQueue: true -// }, -// disableClientSetup: true -// }); -// }); +// while (process.hrtime.bigint() - start < 1_000_000) { +// // block the event loop for 1ms, to make sure the connection will timeout +// } + +// await promise; +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// socket: { +// connectTimeout: 1 +// } +// }, +// disableClientSetup: true +// }); + +// testUtils.testWithClient('client.quit', async client => { +// await client.connect(); + +// const pingPromise = client.ping(), +// quitPromise = client.quit(); +// assert.equal(client.isOpen, false); + +// const [ping, quit] = await Promise.all([ +// pingPromise, +// quitPromise, +// assert.rejects(client.ping(), ClientClosedError) +// ]); + +// assert.equal(ping, 'PONG'); +// assert.equal(quit, 'OK'); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// disableClientSetup: true +// }); + +// testUtils.testWithClient('client.disconnect', async client => { +// const pingPromise = client.ping(), +// disconnectPromise = client.disconnect(); +// assert.equal(client.isOpen, false); +// await Promise.all([ +// assert.rejects(pingPromise, DisconnectsClientError), +// assert.doesNotReject(disconnectPromise), +// assert.rejects(client.ping(), ClientClosedError) +// ]); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { +// await client.disconnect(); +// await client.connect(); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('should be able to use ref and unref', client => { +// client.unref(); +// client.ref(); +// }, GLOBAL.SERVERS.OPEN); + +// testUtils.testWithClient('pingInterval', async client => { +// assert.deepEqual( +// await once(client, 'ping-interval'), +// ['PONG'] +// ); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// pingInterval: 1 +// } +// }); + +// testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { +// const connectPromise = client.connect(); +// await assert.rejects( +// client.ping(), +// ClientOfflineError +// ); +// await connectPromise; +// await client.disconnect(); +// }, { +// ...GLOBAL.SERVERS.OPEN, +// clientOptions: { +// disableOfflineQueue: true +// }, +// disableClientSetup: true +// }); +}); diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 0b445042b5a..6dc9101644d 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -586,7 +586,7 @@ export default class RedisClusterSlots< await unsubscribe(client); if (!client.isPubSubActive) { - await client.disconnect(); + client.destroy(); this.pubSubNode = undefined; } } diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 8fb5564cd03..4448e70a1a6 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,5 +1,5 @@ import { ClientCommandOptions, RedisClientOptions } from '../client'; -import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, Flags, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; +import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; import { EventEmitter } from 'events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; @@ -53,10 +53,10 @@ export interface RedisClusterOptions< type WithCommands< RESP extends RespVersions, - FLAGS extends Flags, + TYPE_MAPPING extends TypeMapping, POLICIES extends CommandPolicies > = { - [P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, FLAGS, POLICIES>; + [P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING, POLICIES>; }; export type RedisClusterType< @@ -64,16 +64,16 @@ export type RedisClusterType< F extends RedisFunctions = {}, S extends RedisScripts = {}, RESP extends RespVersions = 2, - FLAGS extends Flags = {}, + TYPE_MAPPING extends TypeMapping = {}, POLICIES extends CommandPolicies = {} -> = RedisCluster & WithCommands; +> = RedisCluster & WithCommands; // & WithModules & WithFunctions & WithScripts export interface ClusterCommandOptions extends ClientCommandOptions { policies?: CommandPolicies; } -type ProxyCluster = RedisCluster & { commandOptions?: ClusterCommandOptions }; +type ProxyCluster = RedisCluster & { commandOptions?: ClusterCommandOptions }; type NamespaceProxyCluster = { self: ProxyCluster }; @@ -82,7 +82,7 @@ export default class RedisCluster< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - FLAGS extends Flags, + TYPE_MAPPING extends TypeMapping, POLICIES extends CommandPolicies > extends EventEmitter { static extractFirstKey( @@ -310,7 +310,7 @@ export default class RedisCluster< F, S, RESP, - T['flags'] extends Flags ? T['flags'] : {}, + T['typeMapping'] extends TypeMapping ? T['typeMapping'] : {}, T['policies'] extends CommandPolicies ? T['policies'] : {} >; } @@ -330,16 +330,16 @@ export default class RedisCluster< F, S, RESP, - K extends 'flags' ? V extends Flags ? V : {} : FLAGS, + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING, K extends 'policies' ? V extends CommandPolicies ? V : {} : POLICIES >; } /** - * Override the `flags` command option + * Override the `typeMapping` command option */ - withFlags(flags: FLAGS) { - return this._commandOptionsProxy('flags', flags); + withTypeMapping(typeMapping: TYPE_MAPPING) { + return this._commandOptionsProxy('typeMapping', typeMapping); } /** @@ -421,7 +421,7 @@ export default class RedisCluster< return client.executeMulti(commands); } - MULTI(routing?: RedisArgument): RedisClusterMultiCommandType<[], M, F, S, RESP, FLAGS> { + MULTI(routing?: RedisArgument): RedisClusterMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { return new (this as any).Multi( this, routing diff --git a/packages/client/package.json b/packages/client/package.json index 806c90af218..d0bc06792d6 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -8,35 +8,19 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "lint": "eslint ./*.ts ./lib/**/*.ts", - "documentation": "typedoc" + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "dependencies": { "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" + "generic-pool": "3.9.0" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "@types/sinon": "^10.0.14", - "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.1", - "@typescript-eslint/parser": "^5.59.1", - "eslint": "^8.39.0", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "sinon": "^15.0.4", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@types/sinon": "^10.0.15", + "sinon": "^15.1.0" }, "engines": { - "node": ">=14" + "node": ">=16" }, "repository": { "type": "git", diff --git a/packages/graph/package.json b/packages/graph/package.json index c37f956ffb2..17ae40d3b55 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -8,23 +8,12 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "documentation": "typedoc" - }, + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "repository": { "type": "git", diff --git a/packages/json/package.json b/packages/json/package.json index 6f30dc16779..c1fd188e1af 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -8,23 +8,13 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "documentation": "typedoc" + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "repository": { "type": "git", diff --git a/packages/redis/README.md b/packages/redis/README.md index 0d758d1088c..01bfd6df715 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -25,15 +25,13 @@ To install node-redis, simply: npm install redis ``` -> :warning: The new interface is clean and cool, but if you have an existing codebase, you'll want to read the [migration guide](./docs/v3-to-v4.md). - Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! ## Usage ### Basic Example -```typescript +```javascript import { createClient } from 'redis'; const client = createClient(); @@ -44,18 +42,18 @@ await client.connect(); await client.set('key', 'value'); const value = await client.get('key'); -await client.disconnect(); +client.destroy(); ``` 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 +```javascript 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). +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). To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). @@ -96,7 +94,7 @@ await client.hVals('key'); // ['value1', 'value2'] ```typescript await client.hSet('key', 'field', Buffer.from('value')); // 'OK' -await client.withFlags({ +await client.withTypeMapping({ [TYPES.BLOB_STRING]: Buffer }).hGetAll('key'); // { field: } ``` @@ -111,23 +109,11 @@ 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). +### Links +- [Multi](../../docs/multi.md). +- [Pub/Sub](../../docs/pub-sub.md). +- [Scan Iterators](../../docs/scan-iterators.md). +- [Programmability](../../docs/programmability.md). ### Blocking Commands @@ -148,150 +134,33 @@ 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 - -See the [Pub/Sub overview](./docs/pub-sub.md). - -### 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, value } 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 -}); -``` - -### [Programmability](https://redis.io/docs/manual/programmability/) - -Redis provides a programming interface allowing code execution on the redis server. - -#### [Functions](https://redis.io/docs/manual/programmability/functions-intro/) - -The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. - -```lua -#!lua name=library - -redis.register_function { - function_name = 'add', - callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end, - flags = { 'no-writes' } -} -``` - -Here is the same example, but in a format that can be pasted into the `redis-cli`. - -``` -FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" -``` - -Load the prior redis function on the _redis server_ before running the example below. - -```typescript -import { createClient } from 'redis'; - -const client = createClient({ - functions: { - library: { - add: { - NUMBER_OF_KEYS: 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.library.add('key', 2); // 3 -``` - -#### [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/) - -The following is an end-to-end example of the prior concept. - -```typescript -import { createClient, defineScript } from 'redis'; - -const client = createClient({ - scripts: { - add: defineScript({ - NUMBER_OF_KEYS: 1, - SCRIPT: - 'return redis.call("GET", KEYS[1]) + 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 -``` +To learn more about isolated execution, check out the [guide](../../docs/isolated-execution.md). ### 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. +There are two functions that disconnect a client from the Redis server. In most scenarios you should use `.close()` 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. +#### `.close()` ```typescript -const [ping, get, quit] = await Promise.all([ +const [ping, get] = await Promise.all([ client.ping(), client.get('key'), - client.quit() -]); // ['PONG', null, 'OK'] + client.close() +]); // ['PONG', null] try { await client.get('key'); } catch (err) { - // ClosedClient Error + // ClientClosedError } ``` -#### `.disconnect()` +> :warning: `.close` is just like `.quit()` which was depreacted in Redis 7.2. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information. -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. +#### `.destroy()` -```typescript -await client.disconnect(); -``` +Forcibly close a client's connection to Redis immediately. Calling `destroy` will not send further pending commands to the Redis server, or wait for or parse outstanding responses. ### Auto-Pipelining @@ -311,9 +180,25 @@ await Promise.all([ ]); ``` +### Aborting Commands + +If you want to abort a command, you can use the `AbortController` API: + +```typescript +const controller = new AbortController(); + +client.withAbortSignal(contoller.signal).get('key').catch(err => { + // AbortError +}); + +controller.abort(); +``` + +> :watning: commands can only be aborted before they are sent to Redis. Once a command is sent (written on the socket), it cannot be aborted. + ### Clustering -Check out the [Clustering Guide](./docs/clustering.md) when using Node Redis to connect to a Redis Cluster. +Check out the [Clustering Guide](../../docs/clustering.md) when using Node Redis to connect to a Redis Cluster. ### Events @@ -326,11 +211,11 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each | `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | *No arguments* | | `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` | | `reconnecting` | Client is trying to reconnect to the server | *No arguments* | -| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | +| `sharded-channel-moved` | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | > :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. -> The client will not emit [any other events](./docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. +> The client will not emit [any other events](../../docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. ## Supported Redis versions @@ -348,7 +233,7 @@ Node Redis is supported with the following versions of Redis: ## Contributing -If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md). +If you'd like to contribute, check out the [contributing guide](../../CONTRIBUTING.md). Thank you to all the people who already contributed to Node Redis! @@ -356,4 +241,4 @@ Thank you to all the people who already contributed to Node Redis! ## License -This repository is licensed under the "MIT" license. See [LICENSE](LICENSE). +This repository is licensed under the "MIT" license. See [LICENSE](../../LICENSE). diff --git a/packages/redis/package.json b/packages/redis/package.json index 35fc2eb028b..67abfcaed20 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -8,9 +8,6 @@ "files": [ "dist/" ], - "scripts": { - "build": "tsc" - }, "dependencies": { "@redis/bloom": "1.2.0", "@redis/client": "1.5.7", @@ -19,10 +16,6 @@ "@redis/search": "1.1.2", "@redis/time-series": "1.0.4" }, - "devDependencies": { - "release-it": "^15.9.3", - "typescript": "^5.0.2" - }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/search/package.json b/packages/search/package.json index 27e80335c95..d1562d58fae 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -8,23 +8,13 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "documentation": "typedoc" + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "repository": { "type": "git", diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index d750b7d5121..a6abde44953 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -1,7 +1,7 @@ import { createConnection } from 'net'; import { once } from 'events'; -import RedisClient from '@redis/client/dist/lib/client'; -import { promiseTimeout } from '@redis/client/dist/lib/utils'; +import { createClient } from '@redis/client'; +import { setTimeout } from 'timers/promises'; // import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; import * as path from 'path'; import { promisify } from 'util'; @@ -46,8 +46,8 @@ export interface RedisServerDocker { dockerId: string; } -// ".." cause it'll be in `./dist` -const DOCKER_FODLER_PATH = path.join(__dirname, '../docker'); +// extrea ".." 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, @@ -64,7 +64,7 @@ async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfi } while (await isPortAvailable(port)) { - await promiseTimeout(50); + await setTimeout(50); } return { @@ -139,7 +139,7 @@ async function spawnRedisClusterNodeDockers( await replica.client.clusterMeet('127.0.0.1', master.docker.port); while ((await replica.client.clusterSlots()).length === 0) { - await promiseTimeout(50); + await setTimeout(50); } await replica.client.clusterReplicate( @@ -162,13 +162,13 @@ async function spawnRedisClusterNodeDocker( serverArguments: Array ) { const docker = await spawnRedisServerDocker(dockersConfig, [ - ...serverArguments, - '--cluster-enabled', - 'yes', - '--cluster-node-timeout', - '5000' - ]), - client = RedisClient.create({ + ...serverArguments, + '--cluster-enabled', + 'yes', + '--cluster-node-timeout', + '5000' + ]), + client = createClient({ socket: { port: docker.port } @@ -220,10 +220,10 @@ async function spawnRedisClusterDockers( totalNodes(await client.clusterSlots()) !== nodes.length || !(await client.sendCommand(['CLUSTER', 'INFO'])).startsWith('cluster_state:ok') // TODO ) { - await promiseTimeout(50); + await setTimeout(50); } - return client.disconnect(); + client.destroy(); }) ); diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 0fb311bff8b..009f94a43e0 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -1,7 +1,3 @@ -// import { RedisModules, RedisFunctions, 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 { RedisSocketCommonOptions } from '@redis/client/lib/client/socket'; import { RedisModules, RedisFunctions, @@ -13,7 +9,7 @@ import { createCluster, RedisClusterOptions, RedisClusterType -} from '@redis/client/index'; +} from '@redis/client'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; @@ -136,10 +132,10 @@ export default class TestUtils { } testWithClient< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts, - RESP extends RespVersions + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 >( title: string, fn: (client: RedisClientType) => unknown, @@ -181,7 +177,7 @@ export default class TestUtils { } finally { if (client.isOpen) { await client.flushAll(); - await client.disconnect(); + client.destroy(); } } }); @@ -203,10 +199,10 @@ export default class TestUtils { } testWithCluster< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts, - RESP extends RespVersions + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 >( title: string, fn: (cluster: RedisClusterType) => unknown, @@ -254,10 +250,10 @@ export default class TestUtils { } testAll< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts, - RESP extends RespVersions + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2 >( title: string, fn: (client: RedisClientType | RedisClusterType) => unknown, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 0ebeea37a26..8da954f0f76 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,24 +1,13 @@ { "name": "@redis/test-utils", "private": true, - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "scripts": { - "build": "tsc" - }, + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.1", - "@types/node": "^18.16.1", "@types/yargs": "^17.0.24", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typescript": "^5.0.4", - "yargs": "^17.7.1" + "yargs": "^17.7.2" } } diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 095cc72e26b..20e666efe42 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -8,23 +8,13 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'", - "build": "tsc", - "documentation": "typedoc" + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "*" }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^18.16.1", - "nyc": "^15.1.0", - "release-it": "^15.10.1", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "repository": { "type": "git", diff --git a/tsconfig.base.json b/tsconfig.base.json index 5824c33a9e6..f674e2e5c0a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,10 +1,9 @@ { "extends": "@tsconfig/node16/tsconfig.json", "compilerOptions": { + "composite": true, "declaration": true, - "allowJs": true, - "useDefineForClassFields": true, - "esModuleInterop": false + "allowJs": true }, "ts-node": { "files": true diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000000..53bc24d8830 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "references": [{ + "path": "./packages/client" + }, { + "path": "./packages/test-utils" + }], + "todo": [{ + "path": "./packages/bloom" + }, { + "path": "./packages/graph" + }, { + "path": "./packages/json" + }, { + "path": "./packages/search" + }, { + "path": "./packages/time-series" + }, { + "path": "./packages/redis" + }], + "typedocOptions": { + "entryPoints": ["./packages/client"], + "entryPointStrategy": "packages", + "out": "./documentation" + } +} \ No newline at end of file From b01f17709fb379dd15fba9bea0fb9b67c59fdd97 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 7 Jun 2023 11:51:49 -0400 Subject: [PATCH 120/325] ref #2524 - clear `pingInterval` timeout on close --- packages/client/lib/client/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 25a0ddf6c41..85dfd9f5e92 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -825,6 +825,7 @@ export default class RedisClient< */ QUIT(): Promise { return this._socket.quit(async () => { + clearTimeout(this._pingTimer); const quitPromise = this._queue.addCommand(['QUIT']); this._tick(); return quitPromise; @@ -845,6 +846,7 @@ export default class RedisClient< */ close() { return new Promise(resolve => { + clearTimeout(this._pingTimer); this._socket.close(); if (this._queue.isEmpty()) { @@ -855,11 +857,11 @@ export default class RedisClient< const maybeClose = () => { if (!this._queue.isEmpty()) return; - this._socket.off('data', maybeClose); + this._socket.removeEventListener('data', maybeClose); this._socket.destroySocket(); resolve(); }; - this._socket.on('data', maybeClose); + this._socket.addEventListener('data', maybeClose); }); } @@ -867,6 +869,7 @@ export default class RedisClient< * Destroy the client. Rejects all commands immediately. */ destroy() { + clearTimeout(this._pingTimer); this._queue.flushAll(new DisconnectsClientError()); this._socket.destroy(); } From 0c6bbc99ef5a573e17b84dc37ad9d941f55bf834 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 7 Jun 2023 11:55:10 -0400 Subject: [PATCH 121/325] fix for b01f17709fb379dd15fba9bea0fb9b67c59fdd97 --- packages/client/lib/client/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 85dfd9f5e92..2b256e41e07 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -857,11 +857,11 @@ export default class RedisClient< const maybeClose = () => { if (!this._queue.isEmpty()) return; - this._socket.removeEventListener('data', maybeClose); + this._socket.off('data', maybeClose); this._socket.destroySocket(); resolve(); }; - this._socket.addEventListener('data', maybeClose); + this._socket.on('data', maybeClose); }); } From 97956903649d8d635e2cc21180e48254bcd412b9 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 8 Jun 2023 07:17:42 -0400 Subject: [PATCH 122/325] docs --- docs/RESP.md | 8 +++++-- docs/command-options.md | 51 +++++++++++++++++++++++++++++++++-------- docs/pub-sub.md | 2 ++ docs/v4-to-v5.md | 10 +------- 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/docs/RESP.md b/docs/RESP.md index 5d428497c9a..f31c395f8cc 100644 --- a/docs/RESP.md +++ b/docs/RESP.md @@ -1,4 +1,8 @@ -# RESP2 -> JS +# RESP + +## Type Mapping + +## RESP2 -> JS - Integer (`:`) => `number` - Simple String (`+`) => `string | Buffer` @@ -6,7 +10,7 @@ - Simple Error (`-`) => `ErrorReply` - Array (`*`) => `Array` -# RESP3 -> JS +## RESP3 -> JS - Null (`_`) => `null` - Boolean (`#`) => `boolean` diff --git a/docs/command-options.md b/docs/command-options.md index 0f2a27ec75f..926db1a7beb 100644 --- a/docs/command-options.md +++ b/docs/command-options.md @@ -2,13 +2,12 @@ > :warning: The command options API in v5 has breaking changes from the previous version. For more details, refer to the [v4-to-v5 guide](./v4-to-v5.md#command-options). -TODO: "proxy client" concept +TODO ## Type Mapping -TODO [RESP](./RESP.md) - -`withTypeMapping` +Some RESP types can be mapped to more than one JavaScript type. For example, "Blob String" can be mapped to `string` or `Buffer`. +You can override the default type mapping using the `withTypeMapping` function: ```javascript await client.get('key'); // `string | null` @@ -20,18 +19,52 @@ const proxyClient = client.withTypeMapping({ await proxyClient.get('key'); // `Buffer | null` ``` +See [RESP](./RESP.md) for a full list of types. + ## Abort Signal -TODO +Commands can be aborted using the [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) API: + +```javascript -`withAbortSignal` +const controller = new AbortController(); +controller.abort(); + +try { + await client.withAbortSignal(controller.signal).get('key'); +} catch (err) { + // AbortError +} +``` + +> NOTE: Commands that are already written to the socket cannot be aborted. ## ASAP -TODO +Commands that are executed in the "asap" mode are added to the top of the queue. This is useful to ensure that commands are executed before other commands that are already in the queue. -`asap` +```javascript +const asapClient = client.asap(); + +client.on('connect', () => { + asapClient.clientSetName('my-name') + .catch(err => console.error('CLIENT SETNAME error', err)); +}); +``` ## `withCommandOptions` -TODO +The `withCommandOptions` overrides all of the command options, without reusing any existing ones: + +```javascript +const bufferClient = client.withTypeMapping({ + [TYPES.BLOB_STRING]: Buffer +}); + +await bufferClient.get('key'); // `Buffer | null` + +// reset all command options +const defaultClient = client.withCommandOptions({}); + +await defaultClient.get('key'); // `string | null` +``` diff --git a/docs/pub-sub.md b/docs/pub-sub.md index 4b0e138d8ac..6d210e2fe14 100644 --- a/docs/pub-sub.md +++ b/docs/pub-sub.md @@ -39,6 +39,8 @@ await client.pSubscribe('channe*', listener); await client.sSubscribe('channel', listener); ``` +> NOTE: Subscribing to the same channel more than once will create multiple listeners which will each be called when a message is recieved. + ## Publishing ```javascript diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 6d24149ff7e..911309d98bf 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -30,15 +30,7 @@ const proxyClient = client.withCommandOptions({ await proxyClient.get('key'); // `Buffer | null` ``` -`withCommandOptions` can be used to override all of the command options, without reusing any existing ones. - -To override just a specific option, use the following functions: -- `withTypeMapping` - override `typeMapping` only. -- `withAbortSignal` - override `abortSignal` only. -- `asap` - override `asap` to `true`. -- `isolated` - override `isolated` to `true`. - -[TODO](./command-options.md) +for more information, see the [Command Options guide](./command-options.md). ## Quit VS Disconnect From 0b0273730aca100bb9fec9d42a3caad34bdddaec Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 12 Jun 2023 11:28:13 -0400 Subject: [PATCH 123/325] legacy mode --- .../client/lib/client/legacy-mode.spec.ts | 111 ++++++++++++++++++ packages/client/lib/client/legacy-mode.ts | 20 ++-- 2 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 packages/client/lib/client/legacy-mode.spec.ts diff --git a/packages/client/lib/client/legacy-mode.spec.ts b/packages/client/lib/client/legacy-mode.spec.ts new file mode 100644 index 00000000000..189ed072434 --- /dev/null +++ b/packages/client/lib/client/legacy-mode.spec.ts @@ -0,0 +1,111 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { promisify } from 'util'; +import { RedisLegacyClientType } from './legacy-mode'; +import { ErrorReply } from '../errors'; +import { RedisClientType } from '.'; +import { once } from 'events'; + +function testWithLegacyClient(title: string, fn: (legacy: RedisLegacyClientType, client: RedisClientType) => Promise) { + testUtils.testWithClient(title, client => fn(client.legacy(), client), GLOBAL.SERVERS.OPEN); +} + +describe.only('Legacy Mode', () => { + describe('client.sendCommand', () => { + testWithLegacyClient('resolve', async client => { + assert.equal( + await promisify(client.sendCommand).call(client, 'PING'), + 'PONG' + ); + }); + + testWithLegacyClient('reject', async client => { + await assert.rejects( + promisify(client.sendCommand).call(client, 'ERROR'), + ErrorReply + ); + }); + + testWithLegacyClient('reject without a callback', async (legacy, client) => { + legacy.sendCommand('ERROR'); + const [err] = await once(client, 'error'); + assert.ok(err instanceof ErrorReply); + }); + }); + + describe('hGetAll (TRANSFORM_LEGACY_REPLY)', () => { + testWithLegacyClient('resolve', async client => { + await promisify(client.hSet).call(client, 'key', 'field', 'value'); + assert.deepEqual( + await promisify(client.hGetAll).call(client, 'key'), + Object.create(null, { + field: { + value: 'value', + configurable: true, + enumerable: true + } + }) + ); + }); + + testWithLegacyClient('reject', async client => { + await assert.rejects( + promisify(client.hGetAll).call(client), + ErrorReply + ); + }); + }); + + describe('client.set', () => { + testWithLegacyClient('vardict', async client => { + assert.equal( + await promisify(client.set).call(client, 'a', 'b'), + 'OK' + ); + }); + + testWithLegacyClient('array', async client => { + assert.equal( + await promisify(client.set).call(client, ['a', 'b']), + 'OK' + ); + }); + + testWithLegacyClient('vardict & arrays', async client => { + assert.equal( + await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), + 'OK' + ); + }); + + testWithLegacyClient('reject without a callback', async (legacy, client) => { + legacy.set('ERROR'); + const [err] = await once(client, 'error'); + assert.ok(err instanceof ErrorReply); + }); + }); + + describe('client.multi', () => { + testWithLegacyClient('resolve', async client => { + const multi = client.multi().ping().sendCommand('PING'); + assert.deepEqual( + await promisify(multi.exec).call(multi), + ['PONG', 'PONG'] + ); + }); + + testWithLegacyClient('reject', async client => { + const multi = client.multi().sendCommand('ERROR'); + await assert.rejects( + promisify(multi.exec).call(multi), + ErrorReply + ); + }); + + testWithLegacyClient('reject without a callback', async (legacy, client) => { + legacy.multi().sendCommand('ERROR').exec(); + const [err] = await once(client, 'error'); + assert.ok(err instanceof ErrorReply); + }); + }); +}); diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 78793c5f800..576d73be967 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -91,7 +91,7 @@ export class RedisLegacyClient { this._Multi = LegacyMultiCommand.factory(RESP); } - sendCommand(...args: LegacyArguments) { + sendCommand(...args: LegacyCommandArguments) { const redisArgs: CommandArguments = [], callback = RedisLegacyClient._transformArguments(redisArgs, args), promise = this._client.sendCommand(redisArgs); @@ -115,15 +115,16 @@ type MultiWithCommands = { [P in keyof typeof COMMANDS]: (...args: LegacyCommandArguments) => RedisLegacyMultiType; }; -export type RedisLegacyMultiType = Omit & MultiWithCommands; +export type RedisLegacyMultiType = LegacyMultiCommand & MultiWithCommands; -class LegacyMultiCommand extends RedisMultiCommand { +class LegacyMultiCommand { private static _createCommand(name: string, command: Command, resp: RespVersions) { const transformReply = RedisLegacyClient.getTransformReply(command, resp); return function (this: LegacyMultiCommand, ...args: LegacyArguments) { const redisArgs = [name]; RedisLegacyClient.pushArguments(redisArgs, args); - return this.addCommand(redisArgs, transformReply); + this._multi.addCommand(redisArgs, transformReply); + return this; }; } @@ -144,21 +145,22 @@ class LegacyMultiCommand extends RedisMultiCommand { }; } - private _client: RedisClientType; + private readonly _multi = new RedisMultiCommand(); + private readonly _client: RedisClientType; constructor(client: RedisClientType) { - super(); this._client = client; } sendCommand(...args: LegacyArguments) { const redisArgs: CommandArguments = []; RedisLegacyClient.pushArguments(redisArgs, args); - return this.addCommand(redisArgs); + this._multi.addCommand(redisArgs); + return this; } exec(cb?: (err: ErrorReply | null, replies?: Array) => unknown) { - const promise = this._client.executeMulti(this.queue); + const promise = this._client.executeMulti(this._multi.queue); if (!cb) { promise.catch(err => this._client.emit('error', err)); @@ -166,7 +168,7 @@ class LegacyMultiCommand extends RedisMultiCommand { } promise - .then(results => cb(null, this.transformReplies(results))) + .then(results => cb(null, this._multi.transformReplies(results))) .catch(err => cb?.(err)); } } From 826296fbff0b4057fb80b6cf7ef92d3e3b468836 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 12 Jun 2023 11:28:32 -0400 Subject: [PATCH 124/325] remove .only --- packages/client/lib/client/legacy-mode.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/legacy-mode.spec.ts b/packages/client/lib/client/legacy-mode.spec.ts index 189ed072434..4a2936c9e5e 100644 --- a/packages/client/lib/client/legacy-mode.spec.ts +++ b/packages/client/lib/client/legacy-mode.spec.ts @@ -10,7 +10,7 @@ function testWithLegacyClient(title: string, fn: (legacy: RedisLegacyClientType, testUtils.testWithClient(title, client => fn(client.legacy(), client), GLOBAL.SERVERS.OPEN); } -describe.only('Legacy Mode', () => { +describe('Legacy Mode', () => { describe('client.sendCommand', () => { testWithLegacyClient('resolve', async client => { assert.equal( From c188a5c781c1c83c68a0d8083e926f0a6a878a20 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 14 Jun 2023 15:01:52 -0400 Subject: [PATCH 125/325] docs Co-authored-by: Guy Royse --- docs/FAQ.md | 2 +- docs/RESP.md | 18 +++-- ...ated-execution.md => blocking-commands.md} | 21 ++++++ docs/command-options.md | 46 ++++++------ docs/v4-to-v5.md | 53 ++++++++++--- docs/v5.md | 15 ++-- packages/redis/README.md | 74 +++++-------------- 7 files changed, 122 insertions(+), 107 deletions(-) rename docs/{isolated-execution.md => blocking-commands.md} (77%) diff --git a/docs/FAQ.md b/docs/FAQ.md index 4b7710df3fc..77402d4a723 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -10,7 +10,7 @@ If don't want to queue commands in memory until a new socket is established, set ## How are commands batched? -Commands are pipelined using [`queueMicrotask`](https://nodejs.org/api/globals.html#globals_queuemicrotask_callback). +Commands are pipelined using [`setImmediate`](https://nodejs.org/api/globals.html#setimmediatecallback-args). If `socket.write()` returns `false`—meaning that ["all or part of the data was queued in user memory"](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback:~:text=all%20or%20part%20of%20the%20data%20was%20queued%20in%20user%20memory)—the commands will stack in memory until the [`drain`](https://nodejs.org/api/net.html#net_event_drain) event is fired. diff --git a/docs/RESP.md b/docs/RESP.md index f31c395f8cc..5d634831e17 100644 --- a/docs/RESP.md +++ b/docs/RESP.md @@ -1,8 +1,10 @@ -# RESP +# Mapping RESP types -## Type Mapping +RESP, which stands for **R**edis **SE**rialization **P**rotocol, is the protocol used by Redis to communicate with clients. This document shows how RESP types can be mapped to JavaScript types. You can learn more about RESP itself in the [offical documentation](https://redis.io/docs/reference/protocol-spec/). -## RESP2 -> JS +By default, each type is mapped to the first option in the lists below. To change this, configure a [`typeMapping`](.). + +## RESP2 - Integer (`:`) => `number` - Simple String (`+`) => `string | Buffer` @@ -10,7 +12,9 @@ - Simple Error (`-`) => `ErrorReply` - Array (`*`) => `Array` -## RESP3 -> JS +> NOTE: the first type is the default type + +## RESP3 - Null (`_`) => `null` - Boolean (`#`) => `boolean` @@ -29,11 +33,11 @@ > NOTE: the first type is the default type -## Map keys and Set members +### Map keys and Set members -When decoding Map to `Map | object` or Set to `Set`, keys/members (respectively) of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring type mapping) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s. +When decoding a Map to `Map | object` or a Set to `Set`, keys and members of type "Simple String" or "Blob String" will be decoded as `string`s which enables lookups by value, ignoring type mapping. If you want them as `Buffer`s, decode them as `Array`s instead. -## Not Implemented +### Not Implemented These parts of RESP3 are not yet implemented in Redis itself (at the time of writing), so are not yet implemented in the Node-Redis client either: diff --git a/docs/isolated-execution.md b/docs/blocking-commands.md similarity index 77% rename from docs/isolated-execution.md rename to docs/blocking-commands.md index 7870a4680e7..639ab2b78ed 100644 --- a/docs/isolated-execution.md +++ b/docs/blocking-commands.md @@ -1,3 +1,24 @@ +### 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.isolated().blPop( + '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). + # Isolated Execution Sometimes you want to run your commands on an exclusive connection. There are a few reasons to do this: diff --git a/docs/command-options.md b/docs/command-options.md index 926db1a7beb..b246445ad74 100644 --- a/docs/command-options.md +++ b/docs/command-options.md @@ -2,12 +2,11 @@ > :warning: The command options API in v5 has breaking changes from the previous version. For more details, refer to the [v4-to-v5 guide](./v4-to-v5.md#command-options). -TODO +Command Options are used to create "proxy clients" that change the behavior of executed commands. See the sections below for details. ## Type Mapping -Some RESP types can be mapped to more than one JavaScript type. For example, "Blob String" can be mapped to `string` or `Buffer`. -You can override the default type mapping using the `withTypeMapping` function: +Some [RESP types](./RESP.md) can be mapped to more than one JavaScript type. For example, "Blob String" can be mapped to `string` or `Buffer`. You can override the default type mapping using the `withTypeMapping` function: ```javascript await client.get('key'); // `string | null` @@ -23,48 +22,47 @@ See [RESP](./RESP.md) for a full list of types. ## Abort Signal -Commands can be aborted using the [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) API: +The client [batches commands](./FAQ.md#how-are-commands-batched) before sending them to Redis. Commands that haven't been written to the socket yet can be aborted using the [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) API: ```javascript - -const controller = new AbortController(); -controller.abort(); +const controller = new AbortController(), + client = client.withAbortSignal(controller.signal); try { - await client.withAbortSignal(controller.signal).get('key'); + const promise = client.get('key'); + controller.abort(); + await promise; } catch (err) { // AbortError } ``` -> NOTE: Commands that are already written to the socket cannot be aborted. - ## ASAP -Commands that are executed in the "asap" mode are added to the top of the queue. This is useful to ensure that commands are executed before other commands that are already in the queue. +Commands that are executed in the "asap" mode are added to the beginning of the "to sent" queue. ```javascript const asapClient = client.asap(); - -client.on('connect', () => { - asapClient.clientSetName('my-name') - .catch(err => console.error('CLIENT SETNAME error', err)); -}); +await asapClient.ping(); ``` ## `withCommandOptions` -The `withCommandOptions` overrides all of the command options, without reusing any existing ones: +You can set all of the above command options in a single call with the `withCommandOptions` function: ```javascript -const bufferClient = client.withTypeMapping({ - [TYPES.BLOB_STRING]: Buffer +client.withCommandOptions({ + typeMapping: ..., + abortSignal: ..., + asap: ... }); +``` -await bufferClient.get('key'); // `Buffer | null` - -// reset all command options -const defaultClient = client.withCommandOptions({}); +If any of the above options are omitted, the default value will be used. For example, the following client would **not** be in ASAP mode: -await defaultClient.get('key'); // `string | null` +```javascript +client.asap().withCommandOptions({ + typeMapping: ..., + abortSignal: ... +}); ``` diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 911309d98bf..ad06eec97a5 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -61,16 +61,15 @@ for more information, see the [Scan Iterators guide](./scan-iterators.md). ## Legacy Mode -TODO +In the previous version, you could access "legacy" mode by creating a client and passing in `{ legacyMode: true }`. Now, you can create one off of an existing client by calling the `.legacy()` function. This allows easier access to both APIs and enables better TypeScript support. ```javascript -const client = createClient(), - legacyClient = client.legacy(); - -// use `client` for the new API +// use `client` for the current API +const client = createClient(); await client.set('key', 'value'); // use `legacyClient` for the "legacy" API +const legacyClient = client.legacy(); legacyClient.set('key', 'value', (err, reply) => { // ... }); @@ -79,14 +78,48 @@ legacyClient.set('key', 'value', (err, reply) => { ## Isolation Pool TODO -The `isolationPool` has been moved to it's on class `ClientPool`. You can create pool from a client using `client.createPool()`. -## Cluster MULTI +```javascript +await client.sendCommand(['GET', 'key']); +const pool = client.createPool({ + min: 0, + max: Infinity +}); +await pool.blPop('key'); +await pool.sendCommand(['GET', 'key']); +await pool.use(client => client.blPop()); + +await cluster.sendCommand('key', true, ['GET', 'key']); +const clusterPool = cluster.createPool({ + min: 0, + max: Infinity +}); +await clusterPool.blPop('key'); +await clusterPool.sendCommand('key', true, ['GET', 'key']); +await clusterPool.use(client => client.blPop()); +``` + +## Cluster `MULTI` -Cluster MULTI supports readonly/replicas -`cluster.multi.addCommand` now requires `isReadonly` as the second argument, to match `cluster.sendCommand` +In v4, `cluster.multi()` did not support executing commands on replicas, even if they were readonly. -TODO +```javascript +// this might execute on a replica, depending on configuration +await cluster.sendCommand('key', true, ['GET', 'key']); + +// this always executes on a master +await cluster.multi() + .addCommand('key', ['GET', 'key']) + .exec(); +``` + +To support executing commands on replicas, `cluster.multi().addCommand` now requires `isReadonly` as the second argument, which matches the signature of `cluster.sendCommand`: + +```javascript +await cluster.multi() + .addCommand('key', true, ['GET', 'key']) + .exec(); +``` ## Commands diff --git a/docs/v5.md b/docs/v5.md index 68fa4d6778e..3ac3f0611b3 100644 --- a/docs/v5.md +++ b/docs/v5.md @@ -1,23 +1,22 @@ # RESP3 Support -[RESP3](./RESP3.md) +TODO ```javascript const client = createClient({ RESP: 3 }); +``` -client.on('error', err => console.error(err)); - -await client.connect(); - -client.hGetAll('key'); // Record +```javascript +// by default +await client.hGetAll('key'); // Record -client.withTypeMapping({ +await client.withTypeMapping({ [TYPES.MAP]: Map }).hGetAll('key'); // Map -client.withTypeMapping({ +await client.withTypeMapping({ [TYPES.MAP]: Map, [TYPES.BLOB_STRING]: Buffer }).hGetAll('key'); // Map diff --git a/packages/redis/README.md b/packages/redis/README.md index 01bfd6df715..3a790cdd4b0 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -42,9 +42,11 @@ await client.connect(); await client.set('key', 'value'); const value = await client.get('key'); -client.destroy(); +await client.close(); ``` +> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. + 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]`: ```javascript @@ -83,21 +85,14 @@ await client.set('key', 'value', { }); ``` -Replies will be transformed into useful data structures: +Replies will be mapped to useful data structures: ```typescript await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } await client.hVals('key'); // ['value1', 'value2'] ``` -`Buffer`s are supported as well: - -```typescript -await client.hSet('key', 'field', Buffer.from('value')); // 'OK' -await client.withTypeMapping({ - [TYPES.BLOB_STRING]: Buffer -}).hGetAll('key'); // { field: } -``` +> NOTE: you can change the default type mapping. See the [Type Mapping](../../docs/command-options.md#type-mapping) documentation for more information. ### Unsupported Redis Commands @@ -109,37 +104,12 @@ await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] ``` -### Links -- [Multi](../../docs/multi.md). -- [Pub/Sub](../../docs/pub-sub.md). -- [Scan Iterators](../../docs/scan-iterators.md). -- [Programmability](../../docs/programmability.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.isolated().blPop( - '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). - ### Disconnecting There are two functions that disconnect a client from the Redis server. In most scenarios you should use `.close()` to ensure that pending commands are sent to Redis before closing a connection. +> :warning: The `.quit()` and `.disconnect()` methods have been deprecated in v5. For more details, refer to the [v4-to-v5 guide](../../docs/v4-to-v5.md#quit-vs-disconnect). + #### `.close()` ```typescript @@ -180,26 +150,6 @@ await Promise.all([ ]); ``` -### Aborting Commands - -If you want to abort a command, you can use the `AbortController` API: - -```typescript -const controller = new AbortController(); - -client.withAbortSignal(contoller.signal).get('key').catch(err => { - // AbortError -}); - -controller.abort(); -``` - -> :watning: commands can only be aborted before they are sent to Redis. Once a command is sent (written on the socket), it cannot be aborted. - -### Clustering - -Check out the [Clustering Guide](../../docs/clustering.md) when using Node Redis to connect to a Redis Cluster. - ### Events The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes: @@ -242,3 +192,13 @@ Thank you to all the people who already contributed to Node Redis! ## License This repository is licensed under the "MIT" license. See [LICENSE](../../LICENSE). + +### Links + +- [Multi](../../docs/multi.md). +- [Pub/Sub](../../docs/pub-sub.md). +- [Scan Iterators](../../docs/scan-iterators.md). +- [Programmability](../../docs/programmability.md). +- [Command Options](../../docs/command-options.md). +- [Blocking Commands](../../docs/blocking-commands.md). +- [Clustering](../../docs/clustering.md). From 91be6ac9d424a566ae95afc82b08474e4895ae86 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 14 Jun 2023 15:04:36 -0400 Subject: [PATCH 126/325] wip --- packages/client/lib/RESP/decoder.ts | 2 +- packages/client/lib/client/commands-queue.ts | 50 ++++--- packages/client/lib/client/index.ts | 147 ++++++++++--------- packages/client/lib/client/multi-command.ts | 11 +- packages/client/lib/client/socket.ts | 42 ++---- packages/client/lib/cluster/index.ts | 5 +- 6 files changed, 130 insertions(+), 127 deletions(-) diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index af312788b9e..c4e1296fc23 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -49,7 +49,7 @@ interface DecoderOptions { } export class Decoder { - private _config; + private readonly _config; private _cursor = 0; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 57b7999dfa3..9628097c28d 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -6,7 +6,7 @@ import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, Pu import { AbortError, ErrorReply } from '../errors'; import { EventEmitter } from 'stream'; -export interface QueueCommandOptions { +export interface CommandOptions { chainId?: symbol; asap?: boolean; abortSignal?: AbortSignal; @@ -149,7 +149,7 @@ export default class RedisCommandsQueue { }); } - addCommand(args: CommandArguments, options?: QueueCommandOptions): Promise { + addCommand(args: CommandArguments, options?: CommandOptions): Promise { if (this._maxLength && this._waitingToBeSent.length + this._waitingForReply.length >= this._maxLength) { return Promise.reject(new Error('The queue is full')); } else if (options?.abortSignal?.aborted) { @@ -256,30 +256,32 @@ export default class RedisCommandsQueue { }); } - getCommandToSend(): CommandArguments | undefined { - const toSend = this._waitingToBeSent.shift(); - if (!toSend) return; - - let encoded: CommandArguments; - try { - encoded = encodeCommand(toSend.args); - } catch (err) { - toSend.reject(err); - return; - } + *waitingToBeSent() { + let toSend = this._waitingToBeSent.shift(); + while (toSend) { + let encoded: CommandArguments; + try { + encoded = encodeCommand(toSend.args); + } catch (err) { + toSend.reject(err); + toSend = this._waitingToBeSent.shift(); + continue; + } - if (toSend.abort) { - RedisCommandsQueue._removeAbortListener(toSend); - toSend.abort = undefined; + if (toSend.abort) { + RedisCommandsQueue._removeAbortListener(toSend); + toSend.abort = undefined; + } + + // TODO reuse `toSend` or create new object? + (toSend as any).args = undefined; + (toSend as any).chainId = undefined; + + this._waitingForReply.push(toSend); + this._chainInExecution = toSend.chainId; + yield encoded; + toSend = this._waitingToBeSent.shift(); } - - // TODO reuse `toSend` or create new object? - (toSend as any).args = undefined; - (toSend as any).chainId = undefined; - - this._waitingForReply.push(toSend); - this._chainInExecution = toSend.chainId; - return encoded; } private _flushWaitingForReply(err: Error): void { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 2b256e41e07..4e6700d3fbd 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket'; -import RedisCommandsQueue, { QueueCommandOptions } from './commands-queue'; +import RedisCommandsQueue, { CommandOptions } from './commands-queue'; import { EventEmitter } from 'events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchError } from '../errors'; @@ -12,7 +12,7 @@ import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-co import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; import { ReplyWithTypeMapping, CommandReply } from '../RESP/types'; -import SCAN, { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; +import { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; // import { RedisClientPool } from './pool'; @@ -20,8 +20,9 @@ export interface RedisClientOptions< M extends RedisModules = RedisModules, F extends RedisFunctions = RedisFunctions, S extends RedisScripts = RedisScripts, - RESP extends RespVersions = RespVersions -> extends CommanderConfig { + RESP extends RespVersions = RespVersions, + TYPE_MAPPING extends TypeMapping = TypeMapping +> extends CommanderConfig, TypeMappingOption { /** * `redis[s]://[[username][:password]@][host][:port][/db-number]` * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details @@ -67,40 +68,60 @@ export interface RedisClientOptions< pingInterval?: number; } +interface TypeMappingOption { + /** + * Maps bettwen RESP types to JavaScript types + */ + typeMapping?: TYPE_MAPPING; +} + type WithCommands< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > = { - [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING>; - }; + [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING>; +}; type WithModules< M extends RedisModules, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > = { - [P in keyof M]: { - [C in keyof M[P]]: CommandSignature; - }; + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; }; +}; type WithFunctions< F extends RedisFunctions, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > = { - [L in keyof F]: { - [C in keyof F[L]]: CommandSignature; - }; + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; }; +}; type WithScripts< S extends RedisScripts, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > = { - [P in keyof S]: CommandSignature; - }; + [P in keyof S]: CommandSignature; +}; + +export type RedisClientExtensions< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} +> = ( + WithCommands & + WithModules & + WithFunctions & + WithScripts +); export type RedisClientType< M extends RedisModules = {}, @@ -109,18 +130,11 @@ export type RedisClientType< RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {} > = ( - RedisClient & - WithCommands & - WithModules & - WithFunctions & - WithScripts - ); - -export interface ClientCommandOptions extends QueueCommandOptions { - // isolated?: boolean; -} + RedisClient & + RedisClientExtensions +); -type ProxyClient = RedisClient<{}, {}, {}, RespVersions, TypeMapping> & { commandOptions?: ClientCommandOptions }; +type ProxyClient = RedisClient & { commandOptions?: CommandOptions }; type NamespaceProxyClient = { self: ProxyClient }; @@ -181,8 +195,8 @@ export default class RedisClient< reply = await this.sendCommand(redisArgs, this.commandOptions).catch((err: unknown) => { if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; - args[0] = 'EVAL'; - args[1] = script.SCRIPT; + redisArgs[0] = 'EVAL'; + redisArgs[1] = script.SCRIPT; return this.sendCommand(redisArgs, this.commandOptions); }); return transformReply ? @@ -195,8 +209,9 @@ export default class RedisClient< M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 - >(config?: CommanderConfig) { + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >(config?: CommanderConfig & TypeMappingOption) { const Client = attachConfig({ BaseClass: RedisClient, commands: COMMANDS, @@ -212,7 +227,7 @@ export default class RedisClient< return (options?: Omit>) => { // returning a proxy of the client to prevent the namespaces.self to leak between proxies // namespaces will be bootstraped on first access per proxy - return Object.create(new Client(options)) as RedisClientType; + return Object.create(new Client(options)) as RedisClientType; }; } @@ -220,8 +235,9 @@ export default class RedisClient< M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 - >(this: void, options?: RedisClientOptions) { + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >(this: void, options?: RedisClientOptions) { return RedisClient.factory(options)(options); } @@ -308,6 +324,12 @@ export default class RedisClient< this._selectedDB = options.database; } + if (options?.typeMapping) { + (this as unknown as ProxyClient).commandOptions = { + typeMapping: options.typeMapping + }; + } + return options; } @@ -390,7 +412,7 @@ export default class RedisClient< } if (promises.length) { - this._tick(true); + this._write(); await Promise.all(promises); } }; @@ -417,10 +439,10 @@ export default class RedisClient< .on('ready', () => { this.emit('ready'); this._setPingTimer(); - this._tick(); + this._scheduleWrite(); }) .on('reconnecting', () => this.emit('reconnecting')) - .on('drain', () => this._tick()) + .on('drain', () => this._scheduleWrite()) .on('end', () => this.emit('end')); } @@ -440,7 +462,7 @@ export default class RedisClient< }, this._options.pingInterval); } - withCommandOptions(options: T) { + withCommandOptions(options: T) { const proxy = Object.create(this.self); proxy.commandOptions = options; return proxy as RedisClientType< @@ -453,8 +475,8 @@ export default class RedisClient< } private _commandOptionsProxy< - K extends keyof ClientCommandOptions, - V extends ClientCommandOptions[K] + K extends keyof CommandOptions, + V extends CommandOptions[K] >( key: K, value: V @@ -523,7 +545,7 @@ export default class RedisClient< sendCommand( args: CommandArguments, - options?: ClientCommandOptions + options?: CommandOptions ): Promise { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); @@ -532,7 +554,7 @@ export default class RedisClient< } const promise = this._queue.addCommand(args, options); - this._tick(); + this._scheduleWrite(); return promise; } @@ -546,7 +568,7 @@ export default class RedisClient< private _pubSubCommand(promise: Promise | undefined) { if (promise === undefined) return Promise.resolve(); - this._tick(); + this._scheduleWrite(); return promise; } @@ -672,32 +694,19 @@ export default class RedisClient< ); } - private _tick(force = false): void { - if (this._socket.writableNeedDrain || (!force && !this._socket.isReady)) { - return; - } - - this._socket.cork(); + private _write() { + this._socket.write(this._queue.waitingToBeSent()); + } - do { - const args = this._queue.getCommandToSend(); - if (args === undefined) break; + private _scheduledWrite?: NodeJS.Immediate; - this._socket.writeCommand(args); - } while (!this._socket.writableNeedDrain); - } + private _scheduleWrite() { + if (!this.isReady || this._scheduledWrite) return; - private _addMultiCommands( - commands: Array, - chainId?: symbol, - typeMapping?: TypeMapping - ) { - return Promise.all( - commands.map(({ args }) => this._queue.addCommand(args, { - chainId, - typeMapping - })) - ); + this._scheduledWrite = setImmediate(() => { + this._write(); + this._scheduledWrite = undefined; + }); } /** @@ -713,7 +722,7 @@ export default class RedisClient< typeMapping: (this as ProxyClient).commandOptions?.typeMapping })) ); - this._tick(); + this._scheduleWrite(); return promise; } @@ -747,7 +756,7 @@ export default class RedisClient< this._queue.addCommand(['EXEC'], { chainId }) ); - this._tick(); + this._scheduleWrite(); const results = await Promise.all(promises), execResult = results[results.length - 1]; @@ -772,7 +781,7 @@ export default class RedisClient< async* scanIterator( this: RedisClientType, options?: ScanOptions & ScanIteratorOptions - ): AsyncIterable['keys'], TYPE_MAPPING>> { + ) { let cursor = options?.cursor ?? 0; do { const reply = await this.scan(cursor, options); @@ -827,7 +836,7 @@ export default class RedisClient< return this._socket.quit(async () => { clearTimeout(this._pingTimer); const quitPromise = this._queue.addCommand(['QUIT']); - this._tick(); + this._scheduleWrite(); return quitPromise; }); } @@ -842,7 +851,7 @@ export default class RedisClient< } /** - * Close the client. Wait for pending replies. + * Close the client. Wait for pending commands. */ close() { return new Promise(resolve => { diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 625e449da5b..cacb5429a5c 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -88,7 +88,7 @@ export default class RedisClientMultiCommand { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return function (this: RedisClientMultiCommand, ...args: Array) { - return this._multi.addCommand( + return this.addCommand( command.transformArguments(...args), transformReply ); @@ -98,7 +98,7 @@ export default class RedisClientMultiCommand { private static _createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return function (this: { self: RedisClientMultiCommand }, ...args: Array) { - return this.self._multi.addCommand( + return this.self.addCommand( command.transformArguments(...args), transformReply ); @@ -112,7 +112,7 @@ export default class RedisClientMultiCommand { const fnArgs = fn.transformArguments(...args), redisArgs: CommandArguments = prefix.concat(fnArgs); redisArgs.preserve = fnArgs.preserve; - return this.self._multi.addCommand( + return this.self.addCommand( redisArgs, transformReply ); @@ -164,6 +164,11 @@ export default class RedisClientMultiCommand { select = this.SELECT; + addCommand(args: CommandArguments, transformReply?: TransformReply) { + this._multi.addCommand(args, transformReply); + return this; + } + async exec(execAsPipeline = false): Promise> { if (execAsPipeline) return this.execAsPipeline(); diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 47c4616c191..e179613062a 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -82,14 +82,6 @@ export default class RedisSocket extends EventEmitter { return this._isReady; } - // `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used - // https://nodejs.org/api/stream.html#stream_writable_writableneeddrain - private _writableNeedDrain = false; - - get writableNeedDrain(): boolean { - return this._writableNeedDrain; - } - private _isSocketUnrefed = false; constructor(initiator: RedisSocketInitiator, options?: RedisSocketOptions) { @@ -149,7 +141,6 @@ export default class RedisSocket extends EventEmitter { do { try { this._socket = await this._createSocket(); - this._writableNeedDrain = false; this.emit('connect'); try { @@ -203,10 +194,7 @@ export default class RedisSocket extends EventEmitter { this._onSocketError(new SocketClosedUnexpectedlyError()); } }) - .on('drain', () => { - this._writableNeedDrain = false; - this.emit('drain'); - }) + .on('drain', () => this.emit('drain')) .on('data', data => this.emit('data', data)); resolve(socket); @@ -240,14 +228,20 @@ export default class RedisSocket extends EventEmitter { }); } - writeCommand(args: Array): void { + write(iterator: IterableIterator>): void { if (!this._socket) { throw new ClientClosedError(); } + + this._socket.cork(); + for (const args of iterator) { + for (const toWrite of args) { + this._socket.write(toWrite); + } - for (const toWrite of args) { - this._writableNeedDrain = !this._socket.write(toWrite); + if (this._socket.writableNeedDrain) break; } + this._socket.uncork(); } async quit(fn: () => Promise): Promise { @@ -289,20 +283,12 @@ export default class RedisSocket extends EventEmitter { this.emit('end'); } - private _isCorked = false; - cork(): void { - if (!this._socket || this._isCorked) { - return; - } - - this._socket.cork(); - this._isCorked = true; + this._socket?.cork(); + } - setImmediate(() => { - this._socket?.uncork(); - this._isCorked = false; - }); + uncork(): void { + this._socket?.uncork(); } ref(): void { diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 4448e70a1a6..17a3dc0904d 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,4 +1,5 @@ -import { ClientCommandOptions, RedisClientOptions } from '../client'; +import { RedisClientOptions } from '../client'; +import { CommandOptions } from '../client/commands-queue'; import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; import { EventEmitter } from 'events'; @@ -69,7 +70,7 @@ export type RedisClusterType< > = RedisCluster & WithCommands; // & WithModules & WithFunctions & WithScripts -export interface ClusterCommandOptions extends ClientCommandOptions { +export interface ClusterCommandOptions extends CommandOptions { policies?: CommandPolicies; } From 9c1f2a0f868a31b9fa92c8a645c5da7e53ce2ef4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 17:13:19 -0400 Subject: [PATCH 127/325] restore programmability docs --- README.md | 1 - docs/programmability.md | 76 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 docs/programmability.md diff --git a/README.md b/README.md index ec317d0d115..461bb198e89 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js. - ## Packages | Name | Description | diff --git a/docs/programmability.md b/docs/programmability.md new file mode 100644 index 00000000000..803ac689a60 --- /dev/null +++ b/docs/programmability.md @@ -0,0 +1,76 @@ +# [Programmability](https://redis.io/docs/manual/programmability/) + +Redis provides a programming interface allowing code execution on the redis server. + +## [Functions](https://redis.io/docs/manual/programmability/functions-intro/) + +The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. + +```lua +#!lua name=library + +redis.register_function { + function_name = 'add', + callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end, + flags = { 'no-writes' } +} +``` + +Here is the same example, but in a format that can be pasted into the `redis-cli`. + +``` +FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" +``` + +Load the prior redis function on the _redis server_ before running the example below. + +```typescript +import { createClient } from 'redis'; + +const client = createClient({ + functions: { + library: { + add: { + NUMBER_OF_KEYS: 1, + FIRST_KEY_INDEX: 1, + transformArguments(key: string, toAdd: number): Array { + return [key, toAdd.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply + } + } + } +}); + +await client.connect(); + +await client.set('key', '1'); +await client.library.add('key', 2); // 3 +``` + +## [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/) + +The following is an end-to-end example of the prior concept. + +```typescript +import { createClient, defineScript, NumberReply } from 'redis'; + +const client = createClient({ + scripts: { + add: defineScript({ + SCRIPT: 'return redis.call("GET", KEYS[1]) + ARGV[1];', + NUMBER_OF_KEYS: 1, + FIRST_KEY_INDEX: 1, + transformArguments(key: string, toAdd: number): Array { + return [key, toAdd.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply + }) + } +}); + +await client.connect(); + +await client.set('key', '1'); +await client.add('key', 2); // 3 +``` From f150e86f95fab7c41524646ff1d8394ec5d43189 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:04:31 -0400 Subject: [PATCH 128/325] wip --- packages/client/lib/client/commands-queue.ts | 13 +- packages/client/lib/client/index.spec.ts | 676 +++----- packages/client/lib/client/index.ts | 21 +- packages/client/lib/client/linked-list.ts | 10 + packages/client/lib/cluster/cluster-slots.ts | 8 +- .../lib/commands/CLIENT_GETNAME.spec.ts | 8 + .../client/lib/commands/CLIENT_KILL.spec.ts | 42 +- .../lib/commands/CLIENT_NO-EVICT.spec.ts | 42 +- .../client/lib/commands/CLIENT_PAUSE.spec.ts | 40 +- .../lib/commands/CLIENT_SETNAME.spec.ts | 23 +- .../client/lib/commands/CLUSTER_MYID.spec.ts | 30 +- packages/client/lib/commands/COMMAND.spec.ts | 30 +- .../client/lib/commands/COMMAND_COUNT.spec.ts | 34 +- .../lib/commands/COMMAND_GETKEYS.spec.ts | 34 +- .../commands/COMMAND_GETKEYSANDFLAGS.spec.ts | 42 +- .../client/lib/commands/COMMAND_INFO.spec.ts | 90 +- .../client/lib/commands/COMMAND_LIST.spec.ts | 100 +- .../client/lib/commands/CONFIG_GET.spec.ts | 14 +- .../lib/commands/CONFIG_RESETSTAT.spec.ts | 14 +- .../lib/commands/CONFIG_REWRITE.spec.ts | 14 +- .../client/lib/commands/CONFIG_SET.spec.ts | 36 +- packages/client/lib/commands/DISCARD.spec.ts | 14 +- packages/client/lib/commands/FAILOVER.spec.ts | 124 +- packages/client/lib/commands/FCALL.spec.ts | 42 +- packages/client/lib/commands/FCALL.ts | 20 +- packages/client/lib/commands/FCALL_RO.spec.ts | 42 +- packages/client/lib/commands/FCALL_RO.ts | 16 +- .../lib/commands/FUNCTION_DELETE.spec.ts | 32 +- .../client/lib/commands/FUNCTION_DELETE.ts | 2 +- .../client/lib/commands/FUNCTION_DUMP.spec.ts | 28 +- .../lib/commands/FUNCTION_FLUSH.spec.ts | 42 +- .../client/lib/commands/FUNCTION_FLUSH.ts | 4 +- .../client/lib/commands/FUNCTION_KILL.spec.ts | 16 +- .../client/lib/commands/FUNCTION_LIST.spec.ts | 64 +- packages/client/lib/commands/FUNCTION_LIST.ts | 53 +- .../commands/FUNCTION_LIST_WITHCODE.spec.ts | 68 +- .../lib/commands/FUNCTION_LIST_WITHCODE.ts | 54 +- .../client/lib/commands/FUNCTION_LOAD.spec.ts | 89 +- packages/client/lib/commands/FUNCTION_LOAD.ts | 34 +- .../lib/commands/FUNCTION_RESTORE.spec.ts | 57 +- .../client/lib/commands/FUNCTION_RESTORE.ts | 28 +- .../lib/commands/FUNCTION_STATS.spec.ts | 44 +- .../lib/commands/generic-transformers.spec.ts | 1370 ++++++++--------- .../lib/commands/generic-transformers.ts | 8 - packages/client/lib/commands/index.ts | 820 +++++++++- packages/test-utils/lib/dockers.ts | 2 +- packages/test-utils/lib/index.ts | 2 +- 47 files changed, 2544 insertions(+), 1852 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 9628097c28d..b3ede1ccd67 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -285,9 +285,10 @@ export default class RedisCommandsQueue { } private _flushWaitingForReply(err: Error): void { - while (this._waitingForReply.head) { - this._waitingForReply.shift()!.reject(err); + for (const node of this._waitingForReply) { + node.reject(err); } + this._waitingForReply.reset(); } private static _removeAbortListener(command: CommandWaitingToBeSent) { @@ -324,12 +325,10 @@ export default class RedisCommandsQueue { this.decoder.reset(); this._pubSub.reset(); this._flushWaitingForReply(err); - while (this._waitingToBeSent.head) { - RedisCommandsQueue._flushWaitingToBeSent( - this._waitingToBeSent.shift()!, - err - ); + for (const node of this._waitingToBeSent) { + RedisCommandsQueue._flushWaitingToBeSent(node, err); } + this._waitingToBeSent.reset(); } isEmpty() { diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 9ffcf815ed9..f1e88bb140b 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -3,12 +3,14 @@ import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; import RedisClient, { RedisClientType } from '.'; // import { RedisClientMultiCommandType } from './multi-command'; // import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; -// import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; +import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; // import { spy } from 'sinon'; -// import { once } from 'events'; +import { once } from 'events'; // import { ClientKillFilters } from '../commands/CLIENT_KILL'; // import { promisify } from 'util'; +import { MATH_FUNCTION, loadMathFunction } from '../commands/FUNCTION_LOAD.spec'; +import { RESP_TYPES } from '../RESP/decoder'; export const SQUARE_SCRIPT = defineScript({ SCRIPT: 'return ARGV[1] * ARGV[1];', @@ -113,470 +115,244 @@ describe('Client', () => { } }); -// describe('legacyMode', () => { -// testUtils.testWithClient('client.sendCommand should call the callback', async client => { -// assert.equal( -// await promisify(client.sendCommand).call(client, 'PING'), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.sendCommand should work without callback', async client => { -// client.sendCommand(['PING']); -// await client.v4.ping(); // make sure the first command was replied -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.sendCommand should reply with error', async client => { -// await assert.rejects( -// promisify(client.sendCommand).call(client, '1', '2') -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.hGetAll should reply with error', async client => { -// await assert.rejects( -// promisify(client.hGetAll).call(client) -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.v4.sendCommand should return a promise', async client => { -// assert.equal( -// await client.v4.sendCommand(['PING']), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.v4.{command} should return a promise', async client => { -// assert.equal( -// await client.v4.ping(), -// 'PONG' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.{command} should accept vardict arguments', async client => { -// assert.equal( -// await promisify(client.set).call(client, 'a', 'b'), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.{command} should accept arguments array', async client => { -// assert.equal( -// await promisify(client.set).call(client, ['a', 'b']), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.{command} should accept mix of arrays and arguments', async client => { -// assert.equal( -// await promisify(client.set).call(client, ['a'], 'b', ['EX', 1]), -// 'OK' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.hGetAll should return object', async client => { -// await client.v4.hSet('key', 'field', 'value'); - -// assert.deepEqual( -// await promisify(client.hGetAll).call(client, 'key'), -// Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// function multiExecAsync< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// >(multi: RedisClientMultiCommandType): Promise> { -// return new Promise((resolve, reject) => { -// (multi as any).exec((err: Error | undefined, replies: Array) => { -// if (err) return reject(err); - -// resolve(replies); -// }); -// }); -// } - -// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { -// assert.deepEqual( -// await multiExecAsync( -// client.multi().ping() -// ), -// ['PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.multi.ping.exec should call the callback', async client => { -// client.multi() -// .ping() -// .exec(); -// await client.v4.ping(); // make sure the first command was replied -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.multi.ping.v4.ping.v4.exec should return a promise', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .v4.ping() -// .v4.exec(), -// ['PONG', 'PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.{script} should return a promise', async client => { -// assert.equal( -// await client.square(2), -// 4 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true, -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); - -// testUtils.testWithClient('client.multi.{command}.exec should flatten array arguments', async client => { -// assert.deepEqual( -// await client.multi() -// .sAdd('a', ['b', 'c']) -// .v4.exec(), -// [2] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); - -// testUtils.testWithClient('client.multi.hGetAll should return object', async client => { -// assert.deepEqual( -// await multiExecAsync( -// client.multi() -// .hSet('key', 'field', 'value') -// .hGetAll('key') -// ), -// [ -// 1, -// Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// ] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// legacyMode: true -// } -// }); -// }); - -// describe('events', () => { -// testUtils.testWithClient('connect, ready, end', async client => { -// await Promise.all([ -// once(client, 'connect'), -// once(client, 'ready'), -// client.connect() -// ]); - -// await Promise.all([ -// once(client, 'end'), -// client.disconnect() -// ]); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); -// }); - -// describe('sendCommand', () => { -// testUtils.testWithClient('PING', async client => { -// assert.equal(await client.sendCommand(['PING']), 'PONG'); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('returnBuffers', async client => { -// assert.deepEqual( -// await client.sendCommand(['PING'], { -// returnBuffers: true -// }), -// Buffer.from('PONG') -// ); -// }, GLOBAL.SERVERS.OPEN); - -// describe('AbortController', () => { -// before(function () { -// if (!global.AbortController) { -// this.skip(); -// } -// }); - -// testUtils.testWithClient('success', async client => { -// await client.sendCommand(['PING'], { -// signal: new AbortController().signal -// }); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('AbortError', client => { -// const controller = new AbortController(); -// controller.abort(); - -// return assert.rejects( -// client.sendCommand(['PING'], { -// signal: controller.signal -// }), -// AbortError -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); - -// testUtils.testWithClient('undefined and null should not break the client', async client => { -// await assert.rejects( -// client.sendCommand([null as any, undefined as any]), -// TypeError -// ); + testUtils.testWithClient('connect, ready and end events', async client => { + await Promise.all([ + once(client, 'connect'), + once(client, 'ready'), + client.connect() + ]); + + const promise = once(client, 'end'); + console.log('listen to end', client.listeners('end')); + client.close(); + await promise; + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true + }); -// assert.equal( -// await client.ping(), -// 'PONG' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + describe('sendCommand', () => { + testUtils.testWithClient('PING', async client => { + assert.equal(await client.sendCommand(['PING']), 'PONG'); + }, GLOBAL.SERVERS.OPEN); -// describe('multi', () => { -// testUtils.testWithClient('simple', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .set('key', 'value') -// .get('key') -// .exec(), -// ['PONG', 'OK', 'value'] -// ); -// }, GLOBAL.SERVERS.OPEN); + describe('AbortController', () => { + before(function () { + if (!global.AbortController) { + this.skip(); + } + }); + + testUtils.testWithClient('success', async client => { + await client.sendCommand(['PING'], { + abortSignal: new AbortController().signal + }); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('AbortError', client => { + const controller = new AbortController(); + controller.abort(); + + return assert.rejects( + client.sendCommand(['PING'], { + abortSignal: controller.signal + }), + AbortError + ); + }, GLOBAL.SERVERS.OPEN); + }); -// testUtils.testWithClient('should reject the whole chain on error', client => { -// return assert.rejects( -// client.multi() -// .ping() -// .addCommand(['INVALID COMMAND']) -// .ping() -// .exec() -// ); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('undefined and null should not break the client', async client => { + await assert.rejects( + client.sendCommand([null as any, undefined as any]), + TypeError + ); -// testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { -// await client.disconnect(); + assert.equal( + await client.ping(), + 'PONG' + ); + }, GLOBAL.SERVERS.OPEN); + }); -// return assert.rejects( -// client.multi() -// .ping() -// .set('key', 'value') -// .get('key') -// .exec(), -// ClientClosedError -// ); -// }, GLOBAL.SERVERS.OPEN); + describe('multi', () => { + testUtils.testWithClient('simple', async client => { + assert.deepEqual( + await client.multi() + .ping() + .set('key', 'value') + .get('key') + .exec(), + ['PONG', 'OK', 'value'] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should reject the whole chain on error', client => { + return assert.rejects( + client.multi() + .ping() + .addCommand(['INVALID COMMAND']) + .ping() + .exec() + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should reject the whole chain upon client disconnect', async client => { + await client.close(); + + return assert.rejects( + client.multi() + .ping() + .set('key', 'value') + .get('key') + .exec(), + ClientClosedError + ); + }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('with script', async client => { -// assert.deepEqual( -// await client.multi() -// .square(2) -// .exec(), -// [4] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); + testUtils.testWithClient('with script', async client => { + assert.deepEqual( + await client.multi() + .square(2) + .exec(), + [4] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + scripts: { + square: SQUARE_SCRIPT + } + } + }); -// testUtils.testWithClient('WatchError', async client => { -// await client.watch('key'); + // testUtils.testWithClient('WatchError', async client => { + // await client.watch('key'); + + // await client.set( + // RedisClient.commandOptions({ + // isolated: true + // }), + // 'key', + // '1' + // ); + + // await assert.rejects( + // client.multi() + // .decr('key') + // .exec(), + // WatchError + // ); + // }, GLOBAL.SERVERS.OPEN); + + describe('execAsPipeline', () => { + testUtils.testWithClient('exec(true)', async client => { + assert.deepEqual( + await client.multi() + .ping() + .exec(true), + ['PONG'] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('empty execAsPipeline', async client => { + assert.deepEqual( + await client.multi().execAsPipeline(), + [] + ); + }, GLOBAL.SERVERS.OPEN); + }); -// await client.set( -// RedisClient.commandOptions({ -// isolated: true -// }), -// 'key', -// '1' -// ); + // testUtils.testWithClient('should remember selected db', async client => { + // await client.multi() + // .select(1) + // .exec(); + // await killClient(client); + // assert.equal( + // (await client.clientInfo()).db, + // 1 + // ); + // }, { + // ...GLOBAL.SERVERS.OPEN, + // minimumDockerVersion: [6, 2] // CLIENT INFO + // }); + }); -// await assert.rejects( -// client.multi() -// .decr('key') -// .exec(), -// WatchError -// ); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('scripts', async client => { + assert.equal( + await client.square(2), + 4 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + scripts: { + square: SQUARE_SCRIPT + } + } + }); -// describe('execAsPipeline', () => { -// testUtils.testWithClient('exec(true)', async client => { -// assert.deepEqual( -// await client.multi() -// .ping() -// .exec(true), -// ['PONG'] -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('empty execAsPipeline', async client => { -// assert.deepEqual( -// await client.multi().execAsPipeline(), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + const module = { + echo: { + transformArguments(message: string): Array { + return ['ECHO', message]; + }, + transformReply(reply: string): string { + return reply; + } + } + }; -// testUtils.testWithClient('should remember selected db', async client => { -// await client.multi() -// .select(1) -// .exec(); -// await killClient(client); -// assert.equal( -// (await client.clientInfo()).db, -// 1 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [6, 2] // CLIENT INFO -// }); -// }); + testUtils.testWithClient('modules', async client => { + assert.equal( + await client.module.echo('message'), + 'message' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + modules: { + module + } + } + }); -// testUtils.testWithClient('scripts', async client => { -// assert.equal( -// await client.square(2), -// 4 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); + testUtils.testWithClient('functions', async client => { + await loadMathFunction(client); -// const module = { -// echo: { -// transformArguments(message: string): Array { -// return ['ECHO', message]; -// }, -// transformReply(reply: string): string { -// return reply; -// } -// } -// }; + assert.equal( + await client.math.square(2), + 4 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [7, 0], + clientOptions: { + functions: { + math: MATH_FUNCTION.library + } + } + }); -// testUtils.testWithClient('modules', async client => { -// assert.equal( -// await client.module.echo('message'), -// 'message' -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// modules: { -// module -// } -// } -// }); + testUtils.testWithClient('duplicate should reuse command options', async client => { + const duplicate = client.withTypeMapping({ + [RESP_TYPES.SIMPLE_STRING]: Buffer + }).duplicate(); -// testUtils.testWithClient('functions', async client => { -// await loadMathFunction(client); + await duplicate.connect(); -// assert.equal( -// await client.math.square(2), -// 4 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [7, 0], -// clientOptions: { -// functions: { -// math: MATH_FUNCTION.library -// } -// } -// }); + try { + assert.deepEqual( + await duplicate.ping(), + Buffer.from('PONG') + ); + } finally { + duplicate.close(); + } + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true, + }); // describe('isolationPool', () => { // testUtils.testWithClient('executeIsolated', async client => { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 4e6700d3fbd..75f94333f70 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -68,7 +68,7 @@ export interface RedisClientOptions< pingInterval?: number; } -interface TypeMappingOption { +export interface TypeMappingOption { /** * Maps bettwen RESP types to JavaScript types */ @@ -532,11 +532,24 @@ export default class RedisClient< // ); // } - duplicate(overrides?: Partial>) { - return new (Object.getPrototypeOf(this).constructor)({ + duplicate< + _M extends RedisModules = M, + _F extends RedisFunctions = F, + _S extends RedisScripts = S, + _RESP extends RespVersions = RESP, + _TYPE_MAPPING extends TypeMapping = TYPE_MAPPING + >(overrides?: Partial>) { + const client = new (Object.getPrototypeOf(this).constructor)({ ...this._options, ...overrides - }) as RedisClientType; + }) as RedisClientType<_M, _F, _S, _RESP, _TYPE_MAPPING>; + + const { commandOptions } = this as ProxyClient; + if (commandOptions) { + return client.withCommandOptions(commandOptions); + } + + return client; } connect() { diff --git a/packages/client/lib/client/linked-list.ts b/packages/client/lib/client/linked-list.ts index ec59e672242..1a68e1c2f3a 100644 --- a/packages/client/lib/client/linked-list.ts +++ b/packages/client/lib/client/linked-list.ts @@ -91,6 +91,11 @@ export class DoublyLinkedList { node.next = undefined; } + reset() { + this._length = 0; + this._head = this._tail = undefined; + } + *[Symbol.iterator]() { let node = this._head; while (node !== undefined) { @@ -152,6 +157,11 @@ export class SinglyLinkedList { return node.value; } + reset() { + this._length = 0; + this._head = this._tail = undefined; + } + *[Symbol.iterator]() { let node = this._head; while (node !== undefined) { diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 6dc9101644d..39d463bad59 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -46,6 +46,7 @@ export interface ShardNode< S extends RedisScripts, RESP extends RespVersions > extends Node { + id: string; host: string; port: number; readonly: boolean; @@ -173,7 +174,6 @@ export default class RedisClusterSlots< promises: Array> = [], eagerConnect = this._options.minimizeConnections !== true; - type a = typeof shards; for (const { from, to, master, replicas } of shards) { const shard: Shard = { master: this._initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) @@ -294,19 +294,19 @@ export default class RedisClusterSlots< } private _initiateSlotNode( - slotAddress: NodeAddress, + shard: NodeAddress & { id: string; }, readonly: boolean, eagerConnent: boolean, addressesInUse: Set, promises: Array> ) { - const address = `${slotAddress.host}:${slotAddress.port}`; + const address = `${shard.host}:${shard.port}`; addressesInUse.add(address); let node = this.nodeByAddress.get(address); if (!node) { node = { - ...slotAddress, + ...shard, address, readonly, client: undefined diff --git a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts index cbd65768917..bb9c24cd6f5 100644 --- a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts +++ b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_GETNAME from './CLIENT_GETNAME'; describe('CLIENT GETNAME', () => { @@ -8,4 +9,11 @@ describe('CLIENT GETNAME', () => { ['CLIENT', 'GETNAME'] ); }); + + testUtils.testWithClient('client.clientGetName', async client => { + assert.equal( + await client.clientGetName(), + null + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_KILL.spec.ts b/packages/client/lib/commands/CLIENT_KILL.spec.ts index 4a64cb2c6e3..28be6e12727 100644 --- a/packages/client/lib/commands/CLIENT_KILL.spec.ts +++ b/packages/client/lib/commands/CLIENT_KILL.spec.ts @@ -1,12 +1,12 @@ import { strict as assert } from 'assert'; -import { ClientKillFilters, transformArguments } from './CLIENT_KILL'; +import CLIENT_KILL, { CLIENT_KILL_FILTERS } from './CLIENT_KILL'; describe('CLIENT KILL', () => { describe('transformArguments', () => { it('ADDRESS', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ADDRESS, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.ADDRESS, address: 'ip:6379' }), ['CLIENT', 'KILL', 'ADDR', 'ip:6379'] @@ -15,8 +15,8 @@ describe('CLIENT KILL', () => { it('LOCAL_ADDRESS', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.LOCAL_ADDRESS, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.LOCAL_ADDRESS, localAddress: 'ip:6379' }), ['CLIENT', 'KILL', 'LADDR', 'ip:6379'] @@ -26,8 +26,8 @@ describe('CLIENT KILL', () => { describe('ID', () => { it('string', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ID, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.ID, id: '1' }), ['CLIENT', 'KILL', 'ID', '1'] @@ -36,8 +36,8 @@ describe('CLIENT KILL', () => { it('number', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.ID, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.ID, id: 1 }), ['CLIENT', 'KILL', 'ID', '1'] @@ -47,8 +47,8 @@ describe('CLIENT KILL', () => { it('TYPE', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.TYPE, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.TYPE, type: 'master' }), ['CLIENT', 'KILL', 'TYPE', 'master'] @@ -57,8 +57,8 @@ describe('CLIENT KILL', () => { it('USER', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.USER, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.USER, username: 'username' }), ['CLIENT', 'KILL', 'USER', 'username'] @@ -68,15 +68,15 @@ describe('CLIENT KILL', () => { describe('SKIP_ME', () => { it('undefined', () => { assert.deepEqual( - transformArguments(ClientKillFilters.SKIP_ME), + CLIENT_KILL.transformArguments(CLIENT_KILL_FILTERS.SKIP_ME), ['CLIENT', 'KILL', 'SKIPME'] ); }); it('true', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.SKIP_ME, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.SKIP_ME, skipMe: true }), ['CLIENT', 'KILL', 'SKIPME', 'yes'] @@ -85,8 +85,8 @@ describe('CLIENT KILL', () => { it('false', () => { assert.deepEqual( - transformArguments({ - filter: ClientKillFilters.SKIP_ME, + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.SKIP_ME, skipMe: false }), ['CLIENT', 'KILL', 'SKIPME', 'no'] @@ -96,12 +96,12 @@ describe('CLIENT KILL', () => { it('TYPE & SKIP_ME', () => { assert.deepEqual( - transformArguments([ + CLIENT_KILL.transformArguments([ { - filter: ClientKillFilters.TYPE, + filter: CLIENT_KILL_FILTERS.TYPE, type: 'master' }, - ClientKillFilters.SKIP_ME + CLIENT_KILL_FILTERS.SKIP_ME ]), ['CLIENT', 'KILL', 'TYPE', 'master', 'SKIPME'] ); diff --git a/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts b/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts index df8903f0646..e87025a3b67 100644 --- a/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts +++ b/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_NO-EVICT'; +import CLIENT_NO_EVICT from './CLIENT_NO-EVICT'; describe('CLIENT NO-EVICT', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('true', () => { - assert.deepEqual( - transformArguments(true), - ['CLIENT', 'NO-EVICT', 'ON'] - ); - }); + describe('transformArguments', () => { + it('true', () => { + assert.deepEqual( + CLIENT_NO_EVICT.transformArguments(true), + ['CLIENT', 'NO-EVICT', 'ON'] + ); + }); - it('false', () => { - assert.deepEqual( - transformArguments(false), - ['CLIENT', 'NO-EVICT', 'OFF'] - ); - }); + it('false', () => { + assert.deepEqual( + CLIENT_NO_EVICT.transformArguments(false), + ['CLIENT', 'NO-EVICT', 'OFF'] + ); }); + }); - testUtils.testWithClient('client.clientNoEvict', async client => { - assert.equal( - await client.clientNoEvict(true), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientNoEvict', async client => { + assert.equal( + await client.clientNoEvict(true), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_PAUSE.spec.ts b/packages/client/lib/commands/CLIENT_PAUSE.spec.ts index 1376ff41eed..8cf414410fd 100644 --- a/packages/client/lib/commands/CLIENT_PAUSE.spec.ts +++ b/packages/client/lib/commands/CLIENT_PAUSE.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_PAUSE'; +import CLIENT_PAUSE from './CLIENT_PAUSE'; describe('CLIENT PAUSE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(0), - ['CLIENT', 'PAUSE', '0'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CLIENT_PAUSE.transformArguments(0), + ['CLIENT', 'PAUSE', '0'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments(0, 'ALL'), - ['CLIENT', 'PAUSE', '0', 'ALL'] - ); - }); + it('with mode', () => { + assert.deepEqual( + CLIENT_PAUSE.transformArguments(0, 'ALL'), + ['CLIENT', 'PAUSE', '0', 'ALL'] + ); }); + }); - testUtils.testWithClient('client.clientPause', async client => { - assert.equal( - await client.clientPause(0), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientPause', async client => { + assert.equal( + await client.clientPause(0), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_SETNAME.spec.ts b/packages/client/lib/commands/CLIENT_SETNAME.spec.ts index 96618f3f79f..d9af526bb46 100644 --- a/packages/client/lib/commands/CLIENT_SETNAME.spec.ts +++ b/packages/client/lib/commands/CLIENT_SETNAME.spec.ts @@ -1,11 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLIENT_SETNAME'; +import testUtils, { GLOBAL } from '../test-utils'; + +import CLIENT_SETNAME from './CLIENT_SETNAME'; describe('CLIENT SETNAME', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('name'), - ['CLIENT', 'SETNAME', 'name'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_SETNAME.transformArguments('name'), + ['CLIENT', 'SETNAME', 'name'] + ); + }); + + testUtils.testWithClient('client.clientSetName', async client => { + assert.equal( + await client.clientSetName('name'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_MYID.spec.ts b/packages/client/lib/commands/CLUSTER_MYID.spec.ts index f427d7058e2..01282fadd8b 100644 --- a/packages/client/lib/commands/CLUSTER_MYID.spec.ts +++ b/packages/client/lib/commands/CLUSTER_MYID.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_MYID'; +import CLUSTER_MYID from './CLUSTER_MYID'; describe('CLUSTER MYID', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'MYID'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_MYID.transformArguments(), + ['CLUSTER', 'MYID'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterMyId', async cluster => { - const [master] = cluster.masters, - client = await cluster.nodeClient(master); - assert.equal( - await client.clusterMyId(), - master.id - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterMyId', async cluster => { + const [master] = cluster.masters, + client = await cluster.nodeClient(master); + assert.equal( + await client.clusterMyId(), + master.id + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/COMMAND.spec.ts b/packages/client/lib/commands/COMMAND.spec.ts index baad79845ab..ed82d5c5ecb 100644 --- a/packages/client/lib/commands/COMMAND.spec.ts +++ b/packages/client/lib/commands/COMMAND.spec.ts @@ -1,17 +1,17 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './COMMAND'; -import { assertPingCommand } from './COMMAND_INFO.spec'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './COMMAND'; +// import { assertPingCommand } from './COMMAND_INFO.spec'; -describe('COMMAND', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['COMMAND'] - ); - }); +// describe('COMMAND', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(), +// ['COMMAND'] +// ); +// }); - testUtils.testWithClient('client.command', async client => { - assertPingCommand((await client.command()).find(command => command.name === 'ping')); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.command', async client => { +// assertPingCommand((await client.command()).find(command => command.name === 'ping')); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/COMMAND_COUNT.spec.ts b/packages/client/lib/commands/COMMAND_COUNT.spec.ts index 71482382f67..ca03e96ae8c 100644 --- a/packages/client/lib/commands/COMMAND_COUNT.spec.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './COMMAND_COUNT'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './COMMAND_COUNT'; -describe('COMMAND COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['COMMAND', 'COUNT'] - ); - }); +// describe('COMMAND COUNT', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(), +// ['COMMAND', 'COUNT'] +// ); +// }); - testUtils.testWithClient('client.commandCount', async client => { - assert.equal( - typeof await client.commandCount(), - 'number' - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.commandCount', async client => { +// assert.equal( +// typeof await client.commandCount(), +// 'number' +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts index a92d032c5d6..e17566e0dff 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts @@ -1,19 +1,19 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './COMMAND_GETKEYS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './COMMAND_GETKEYS'; -describe('COMMAND GETKEYS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['GET', 'key']), - ['COMMAND', 'GETKEYS', 'GET', 'key'] - ); - }); +// describe('COMMAND GETKEYS', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(['GET', 'key']), +// ['COMMAND', 'GETKEYS', 'GET', 'key'] +// ); +// }); - testUtils.testWithClient('client.commandGetKeys', async client => { - assert.deepEqual( - await client.commandGetKeys(['GET', 'key']), - ['key'] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.commandGetKeys', async client => { +// assert.deepEqual( +// await client.commandGetKeys(['GET', 'key']), +// ['key'] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts index d568ed0e508..8d16ad501c6 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts @@ -1,24 +1,24 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './COMMAND_GETKEYSANDFLAGS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './COMMAND_GETKEYSANDFLAGS'; -describe('COMMAND GETKEYSANDFLAGS', () => { - testUtils.isVersionGreaterThanHook([7]); +// describe('COMMAND GETKEYSANDFLAGS', () => { +// testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['GET', 'key']), - ['COMMAND', 'GETKEYSANDFLAGS', 'GET', 'key'] - ); - }); +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(['GET', 'key']), +// ['COMMAND', 'GETKEYSANDFLAGS', 'GET', 'key'] +// ); +// }); - testUtils.testWithClient('client.commandGetKeysAndFlags', async client => { - assert.deepEqual( - await client.commandGetKeysAndFlags(['GET', 'key']), - [{ - key: 'key', - flags: ['RO', 'access'] - }] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.commandGetKeysAndFlags', async client => { +// assert.deepEqual( +// await client.commandGetKeysAndFlags(['GET', 'key']), +// [{ +// key: 'key', +// flags: ['RO', 'access'] +// }] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/COMMAND_INFO.spec.ts b/packages/client/lib/commands/COMMAND_INFO.spec.ts index c54a5d0aeb3..fb9603ea96d 100644 --- a/packages/client/lib/commands/COMMAND_INFO.spec.ts +++ b/packages/client/lib/commands/COMMAND_INFO.spec.ts @@ -1,49 +1,49 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './COMMAND_INFO'; -import { CommandCategories, CommandFlags, CommandReply } from './generic-transformers'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './COMMAND_INFO'; +// import { CommandCategories, CommandFlags, CommandReply } from './generic-transformers'; -export function assertPingCommand(commandInfo: CommandReply | null | undefined): void { - assert.deepEqual( - commandInfo, - { - name: 'ping', - arity: -1, - flags: new Set( - testUtils.isVersionGreaterThan([7]) ? - [CommandFlags.FAST] : - [CommandFlags.STALE, CommandFlags.FAST] - ), - firstKeyIndex: 0, - lastKeyIndex: 0, - step: 0, - categories: new Set( - testUtils.isVersionGreaterThan([6]) ? - [CommandCategories.FAST, CommandCategories.CONNECTION] : - [] - ) - } - ); -} +// export function assertPingCommand(commandInfo: CommandReply | null | undefined): void { +// assert.deepEqual( +// commandInfo, +// { +// name: 'ping', +// arity: -1, +// flags: new Set( +// testUtils.isVersionGreaterThan([7]) ? +// [CommandFlags.FAST] : +// [CommandFlags.STALE, CommandFlags.FAST] +// ), +// firstKeyIndex: 0, +// lastKeyIndex: 0, +// step: 0, +// categories: new Set( +// testUtils.isVersionGreaterThan([6]) ? +// [CommandCategories.FAST, CommandCategories.CONNECTION] : +// [] +// ) +// } +// ); +// } -describe('COMMAND INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['PING']), - ['COMMAND', 'INFO', 'PING'] - ); - }); +// describe('COMMAND INFO', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(['PING']), +// ['COMMAND', 'INFO', 'PING'] +// ); +// }); - describe('client.commandInfo', () => { - testUtils.testWithClient('PING', async client => { - assertPingCommand((await client.commandInfo(['PING']))[0]); - }, GLOBAL.SERVERS.OPEN); +// describe('client.commandInfo', () => { +// testUtils.testWithClient('PING', async client => { +// assertPingCommand((await client.commandInfo(['PING']))[0]); +// }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('DOSE_NOT_EXISTS', async client => { - assert.deepEqual( - await client.commandInfo(['DOSE_NOT_EXISTS']), - [null] - ); - }, GLOBAL.SERVERS.OPEN); - }); -}); +// testUtils.testWithClient('DOSE_NOT_EXISTS', async client => { +// assert.deepEqual( +// await client.commandInfo(['DOSE_NOT_EXISTS']), +// [null] +// ); +// }, GLOBAL.SERVERS.OPEN); +// }); +// }); diff --git a/packages/client/lib/commands/COMMAND_LIST.spec.ts b/packages/client/lib/commands/COMMAND_LIST.spec.ts index eef747d9378..0cf0cd3b60d 100644 --- a/packages/client/lib/commands/COMMAND_LIST.spec.ts +++ b/packages/client/lib/commands/COMMAND_LIST.spec.ts @@ -1,56 +1,56 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, FilterBy } from './COMMAND_LIST'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments, FilterBy } from './COMMAND_LIST'; -describe('COMMAND LIST', () => { - testUtils.isVersionGreaterThanHook([7]); +// describe('COMMAND LIST', () => { +// testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['COMMAND', 'LIST'] - ); - }); +// describe('transformArguments', () => { +// it('simple', () => { +// assert.deepEqual( +// transformArguments(), +// ['COMMAND', 'LIST'] +// ); +// }); - describe('with FILTERBY', () => { - it('MODULE', () => { - assert.deepEqual( - transformArguments({ - filterBy: FilterBy.MODULE, - value: 'json' - }), - ['COMMAND', 'LIST', 'FILTERBY', 'MODULE', 'json'] - ); - }); +// describe('with FILTERBY', () => { +// it('MODULE', () => { +// assert.deepEqual( +// transformArguments({ +// filterBy: FilterBy.MODULE, +// value: 'json' +// }), +// ['COMMAND', 'LIST', 'FILTERBY', 'MODULE', 'json'] +// ); +// }); - it('ACLCAT', () => { - assert.deepEqual( - transformArguments({ - filterBy: FilterBy.ACLCAT, - value: 'admin' - }), - ['COMMAND', 'LIST', 'FILTERBY', 'ACLCAT', 'admin'] - ); - }); +// it('ACLCAT', () => { +// assert.deepEqual( +// transformArguments({ +// filterBy: FilterBy.ACLCAT, +// value: 'admin' +// }), +// ['COMMAND', 'LIST', 'FILTERBY', 'ACLCAT', 'admin'] +// ); +// }); - it('PATTERN', () => { - assert.deepEqual( - transformArguments({ - filterBy: FilterBy.PATTERN, - value: 'a*' - }), - ['COMMAND', 'LIST', 'FILTERBY', 'PATTERN', 'a*'] - ); - }); - }); - }); +// it('PATTERN', () => { +// assert.deepEqual( +// transformArguments({ +// filterBy: FilterBy.PATTERN, +// value: 'a*' +// }), +// ['COMMAND', 'LIST', 'FILTERBY', 'PATTERN', 'a*'] +// ); +// }); +// }); +// }); - testUtils.testWithClient('client.commandList', async client => { - const commandList = await client.commandList(); - assert.ok(Array.isArray(commandList)); - for (const command of commandList) { - assert.ok(typeof command === 'string'); - } - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.commandList', async client => { +// const commandList = await client.commandList(); +// assert.ok(Array.isArray(commandList)); +// for (const command of commandList) { +// assert.ok(typeof command === 'string'); +// } +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/CONFIG_GET.spec.ts b/packages/client/lib/commands/CONFIG_GET.spec.ts index 83b5c410cfb..8077a093d85 100644 --- a/packages/client/lib/commands/CONFIG_GET.spec.ts +++ b/packages/client/lib/commands/CONFIG_GET.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CONFIG_GET'; +import CONFIG_GET from './CONFIG_GET'; describe('CONFIG GET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('*'), - ['CONFIG', 'GET', '*'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CONFIG_GET.transformArguments('*'), + ['CONFIG', 'GET', '*'] + ); + }); }); diff --git a/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts index d3f3048b944..00336dcf515 100644 --- a/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts +++ b/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CONFIG_RESETSTAT'; +import CONFIG_RESETSTAT from './CONFIG_RESETSTAT'; describe('CONFIG RESETSTAT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CONFIG', 'RESETSTAT'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CONFIG_RESETSTAT.transformArguments(), + ['CONFIG', 'RESETSTAT'] + ); + }); }); diff --git a/packages/client/lib/commands/CONFIG_REWRITE.spec.ts b/packages/client/lib/commands/CONFIG_REWRITE.spec.ts index cbc3e5b59d8..a7a0af85e61 100644 --- a/packages/client/lib/commands/CONFIG_REWRITE.spec.ts +++ b/packages/client/lib/commands/CONFIG_REWRITE.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CONFIG_REWRITE'; +import CONFIG_REWRITE from './CONFIG_REWRITE'; describe('CONFIG REWRITE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CONFIG', 'REWRITE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CONFIG_REWRITE.transformArguments(), + ['CONFIG', 'REWRITE'] + ); + }); }); diff --git a/packages/client/lib/commands/CONFIG_SET.spec.ts b/packages/client/lib/commands/CONFIG_SET.spec.ts index 93a7a6ff25e..fac5e1dbe9f 100644 --- a/packages/client/lib/commands/CONFIG_SET.spec.ts +++ b/packages/client/lib/commands/CONFIG_SET.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CONFIG_SET'; +import CONFIG_SET from './CONFIG_SET'; describe('CONFIG SET', () => { - describe('transformArguments', () => { - it('set one parameter (old version)', () => { - assert.deepEqual( - transformArguments('parameter', 'value'), - ['CONFIG', 'SET', 'parameter', 'value'] - ); - }); + describe('transformArguments', () => { + it('set one parameter (old version)', () => { + assert.deepEqual( + CONFIG_SET.transformArguments('parameter', 'value'), + ['CONFIG', 'SET', 'parameter', 'value'] + ); + }); - it('set muiltiple parameters', () => { - assert.deepEqual( - transformArguments({ - 1: 'a', - 2: 'b', - 3: 'c' - }), - ['CONFIG', 'SET', '1', 'a', '2', 'b', '3', 'c'] - ); - }); + it('set muiltiple parameters', () => { + assert.deepEqual( + CONFIG_SET.transformArguments({ + 1: 'a', + 2: 'b', + 3: 'c' + }), + ['CONFIG', 'SET', '1', 'a', '2', 'b', '3', 'c'] + ); }); + }); }); diff --git a/packages/client/lib/commands/DISCARD.spec.ts b/packages/client/lib/commands/DISCARD.spec.ts index b01f9d650d9..b08daecea6a 100644 --- a/packages/client/lib/commands/DISCARD.spec.ts +++ b/packages/client/lib/commands/DISCARD.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './DISCARD'; +import DISCARD from './DISCARD'; describe('DISCARD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['DISCARD'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DISCARD.transformArguments(), + ['DISCARD'] + ); + }); }); diff --git a/packages/client/lib/commands/FAILOVER.spec.ts b/packages/client/lib/commands/FAILOVER.spec.ts index 16094a0dbc3..f97663e419b 100644 --- a/packages/client/lib/commands/FAILOVER.spec.ts +++ b/packages/client/lib/commands/FAILOVER.spec.ts @@ -1,72 +1,72 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './FAILOVER'; +import FAILOVER from './FAILOVER'; describe('FAILOVER', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['FAILOVER'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FAILOVER.transformArguments(), + ['FAILOVER'] + ); + }); - describe('with TO', () => { - it('simple', () => { - assert.deepEqual( - transformArguments({ - TO: { - host: 'host', - port: 6379 - } - }), - ['FAILOVER', 'TO', 'host', '6379'] - ); - }); + describe('with TO', () => { + it('simple', () => { + assert.deepEqual( + FAILOVER.transformArguments({ + TO: { + host: 'host', + port: 6379 + } + }), + ['FAILOVER', 'TO', 'host', '6379'] + ); + }); - it('with FORCE', () => { - assert.deepEqual( - transformArguments({ - TO: { - host: 'host', - port: 6379, - FORCE: true - } - }), - ['FAILOVER', 'TO', 'host', '6379', 'FORCE'] - ); - }); - }); + it('with FORCE', () => { + assert.deepEqual( + FAILOVER.transformArguments({ + TO: { + host: 'host', + port: 6379, + FORCE: true + } + }), + ['FAILOVER', 'TO', 'host', '6379', 'FORCE'] + ); + }); + }); - it('with ABORT', () => { - assert.deepEqual( - transformArguments({ - ABORT: true - }), - ['FAILOVER', 'ABORT'] - ); - }); + it('with ABORT', () => { + assert.deepEqual( + FAILOVER.transformArguments({ + ABORT: true + }), + ['FAILOVER', 'ABORT'] + ); + }); - it('with TIMEOUT', () => { - assert.deepEqual( - transformArguments({ - TIMEOUT: 1 - }), - ['FAILOVER', 'TIMEOUT', '1'] - ); - }); + it('with TIMEOUT', () => { + assert.deepEqual( + FAILOVER.transformArguments({ + TIMEOUT: 1 + }), + ['FAILOVER', 'TIMEOUT', '1'] + ); + }); - it('with TO, ABORT, TIMEOUT', () => { - assert.deepEqual( - transformArguments({ - TO: { - host: 'host', - port: 6379 - }, - ABORT: true, - TIMEOUT: 1 - }), - ['FAILOVER', 'TO', 'host', '6379', 'ABORT', 'TIMEOUT', '1'] - ); - }); + it('with TO, ABORT, TIMEOUT', () => { + assert.deepEqual( + FAILOVER.transformArguments({ + TO: { + host: 'host', + port: 6379 + }, + ABORT: true, + TIMEOUT: 1 + }), + ['FAILOVER', 'TO', 'host', '6379', 'ABORT', 'TIMEOUT', '1'] + ); }); + }); }); diff --git a/packages/client/lib/commands/FCALL.spec.ts b/packages/client/lib/commands/FCALL.spec.ts index fd29f07527d..45016e2702d 100644 --- a/packages/client/lib/commands/FCALL.spec.ts +++ b/packages/client/lib/commands/FCALL.spec.ts @@ -1,29 +1,29 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { MATH_FUNCTION, loadMathFunction } from '../client/index.spec'; -import { transformArguments } from './FCALL'; +import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; +import FCALL from './FCALL'; describe('FCALL', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('function', { - keys: ['key'], - arguments: ['argument'] - }), - ['FCALL', 'function', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + FCALL.transformArguments('function', { + keys: ['key'], + arguments: ['argument'] + }), + ['FCALL', 'function', '1', 'key', 'argument'] + ); + }); - testUtils.testWithClient('client.fCall', async client => { - await loadMathFunction(client); + testUtils.testWithClient('client.fCall', async client => { + await loadMathFunction(client); - assert.equal( - await client.fCall(MATH_FUNCTION.library.square.NAME, { - arguments: ['2'] - }), - 4 - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.fCall(MATH_FUNCTION.library.square.NAME, { + arguments: ['2'] + }), + 4 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FCALL.ts b/packages/client/lib/commands/FCALL.ts index a2411f62dc2..57b9f652319 100644 --- a/packages/client/lib/commands/FCALL.ts +++ b/packages/client/lib/commands/FCALL.ts @@ -1,19 +1,9 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; - -export const FIRST_KEY_INDEX = evalFirstKeyIndex; - -export function transformArguments(fn: string, options?: EvalOptions): Array { - return pushEvalArguments(['FCALL', fn], options); -} - -import { SimpleStringReply, Command } from '../RESP/types'; +import { Command } from '../RESP/types'; +import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, IS_READ_ONLY: false, - transformArguments() { - return ['FCALL']; - }, - transformReply: undefined as unknown as () => SimpleStringReply + transformArguments: transformEvalArguments.bind(undefined, 'FCALL'), + transformReply: EVAL.transformReply } as const satisfies Command; - diff --git a/packages/client/lib/commands/FCALL_RO.spec.ts b/packages/client/lib/commands/FCALL_RO.spec.ts index 18665f92aa6..ec43a97c6c5 100644 --- a/packages/client/lib/commands/FCALL_RO.spec.ts +++ b/packages/client/lib/commands/FCALL_RO.spec.ts @@ -1,29 +1,29 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { MATH_FUNCTION, loadMathFunction } from '../client/index.spec'; -import { transformArguments } from './FCALL_RO'; +import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; +import FCALL_RO from './FCALL_RO'; describe('FCALL_RO', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('function', { - keys: ['key'], - arguments: ['argument'] - }), - ['FCALL_RO', 'function', '1', 'key', 'argument'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + FCALL_RO.transformArguments('function', { + keys: ['key'], + arguments: ['argument'] + }), + ['FCALL_RO', 'function', '1', 'key', 'argument'] + ); + }); - testUtils.testWithClient('client.fCallRo', async client => { - await loadMathFunction(client); + testUtils.testWithClient('client.fCallRo', async client => { + await loadMathFunction(client); - assert.equal( - await client.fCallRo(MATH_FUNCTION.library.square.NAME, { - arguments: ['2'] - }), - 4 - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.fCallRo(MATH_FUNCTION.library.square.NAME, { + arguments: ['2'] + }), + 4 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FCALL_RO.ts b/packages/client/lib/commands/FCALL_RO.ts index 66b79aa8833..700b25e5f7b 100644 --- a/packages/client/lib/commands/FCALL_RO.ts +++ b/packages/client/lib/commands/FCALL_RO.ts @@ -1,9 +1,9 @@ -import { evalFirstKeyIndex, EvalOptions, pushEvalArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; -export const FIRST_KEY_INDEX = evalFirstKeyIndex; - -export const IS_READ_ONLY = true; - -export function transformArguments(fn: string, options?: EvalOptions): Array { - return pushEvalArguments(['FCALL_RO', fn], options); -} +export default { + FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, + IS_READ_ONLY: false, + transformArguments: transformEvalArguments.bind(undefined, 'FCALL_RO'), + transformReply: EVAL.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_DELETE.spec.ts b/packages/client/lib/commands/FUNCTION_DELETE.spec.ts index 563b9aa0a58..a763686d15b 100644 --- a/packages/client/lib/commands/FUNCTION_DELETE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_DELETE.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; -import { MATH_FUNCTION, loadMathFunction } from '../client/index.spec'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FUNCTION_DELETE'; +import FUNCTION_DELETE from './FUNCTION_DELETE'; +import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; describe('FUNCTION DELETE', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('library'), - ['FUNCTION', 'DELETE', 'library'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + FUNCTION_DELETE.transformArguments('library'), + ['FUNCTION', 'DELETE', 'library'] + ); + }); - testUtils.testWithClient('client.functionDelete', async client => { - await loadMathFunction(client); + testUtils.testWithClient('client.functionDelete', async client => { + await loadMathFunction(client); - assert.equal( - await client.functionDelete(MATH_FUNCTION.name), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.functionDelete(MATH_FUNCTION.name), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_DELETE.ts b/packages/client/lib/commands/FUNCTION_DELETE.ts index c0f8794d980..1061cded17c 100644 --- a/packages/client/lib/commands/FUNCTION_DELETE.ts +++ b/packages/client/lib/commands/FUNCTION_DELETE.ts @@ -2,7 +2,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, + IS_READ_ONLY: false, transformArguments(library: RedisArgument) { return ['FUNCTION', 'DELETE', library]; }, diff --git a/packages/client/lib/commands/FUNCTION_DUMP.spec.ts b/packages/client/lib/commands/FUNCTION_DUMP.spec.ts index 360ec6b7453..fe6a44c6769 100644 --- a/packages/client/lib/commands/FUNCTION_DUMP.spec.ts +++ b/packages/client/lib/commands/FUNCTION_DUMP.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FUNCTION_DUMP'; +import FUNCTION_DUMP from './FUNCTION_DUMP'; describe('FUNCTION DUMP', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'DUMP'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + FUNCTION_DUMP.transformArguments(), + ['FUNCTION', 'DUMP'] + ); + }); - testUtils.testWithClient('client.functionDump', async client => { - assert.equal( - typeof await client.functionDump(), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.functionDump', async client => { + assert.equal( + typeof await client.functionDump(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts b/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts index 12009d03363..0f3c64cf7cc 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FUNCTION_FLUSH'; +import FUNCTION_FLUSH from './FUNCTION_FLUSH'; describe('FUNCTION FLUSH', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'FLUSH'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FUNCTION_FLUSH.transformArguments(), + ['FUNCTION', 'FLUSH'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments('SYNC'), - ['FUNCTION', 'FLUSH', 'SYNC'] - ); - }); + it('with mode', () => { + assert.deepEqual( + FUNCTION_FLUSH.transformArguments('SYNC'), + ['FUNCTION', 'FLUSH', 'SYNC'] + ); }); + }); - testUtils.testWithClient('client.functionFlush', async client => { - assert.equal( - await client.functionFlush(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.functionFlush', async client => { + assert.equal( + await client.functionFlush(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.ts b/packages/client/lib/commands/FUNCTION_FLUSH.ts index ab238a5eb5e..010e9b81087 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.ts @@ -3,7 +3,7 @@ import { RedisFlushModes } from './FLUSHALL'; export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, + IS_READ_ONLY: false, transformArguments(mode?: RedisFlushModes) { const args = ['FUNCTION', 'FLUSH']; @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_KILL.spec.ts b/packages/client/lib/commands/FUNCTION_KILL.spec.ts index df4848fc82e..a79ae9515cf 100644 --- a/packages/client/lib/commands/FUNCTION_KILL.spec.ts +++ b/packages/client/lib/commands/FUNCTION_KILL.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './FUNCTION_KILL'; +import FUNCTION_KILL from './FUNCTION_KILL'; describe('FUNCTION KILL', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'KILL'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + FUNCTION_KILL.transformArguments(), + ['FUNCTION', 'KILL'] + ); + }); }); diff --git a/packages/client/lib/commands/FUNCTION_LIST.spec.ts b/packages/client/lib/commands/FUNCTION_LIST.spec.ts index 80723d070de..c630b3aa52d 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.spec.ts @@ -1,41 +1,43 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { MATH_FUNCTION, loadMathFunction } from '../client/index.spec'; -import { transformArguments } from './FUNCTION_LIST'; +import FUNCTION_LIST from './FUNCTION_LIST'; +import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; describe('FUNCTION LIST', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'LIST'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FUNCTION_LIST.transformArguments(), + ['FUNCTION', 'LIST'] + ); + }); - it('with pattern', () => { - assert.deepEqual( - transformArguments('patter*'), - ['FUNCTION', 'LIST', 'patter*'] - ); - }); + it('with LIBRARYNAME', () => { + assert.deepEqual( + FUNCTION_LIST.transformArguments({ + LIBRARYNAME: 'patter*' + }), + ['FUNCTION', 'LIST', 'LIBRARYNAME', 'patter*'] + ); }); + }); - testUtils.testWithClient('client.functionList', async client => { - await loadMathFunction(client); + testUtils.testWithClient('client.functionList', async client => { + await loadMathFunction(client); - assert.deepEqual( - await client.functionList(), - [{ - libraryName: MATH_FUNCTION.name, - engine: MATH_FUNCTION.engine, - functions: [{ - name: MATH_FUNCTION.library.square.NAME, - description: null, - flags: ['no-writes'] - }] - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + await client.functionList(), + [{ + library_name: MATH_FUNCTION.name, + engine: MATH_FUNCTION.engine, + functions: [{ + name: MATH_FUNCTION.library.square.NAME, + description: null, + flags: ['no-writes'] + }] + }] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LIST.ts b/packages/client/lib/commands/FUNCTION_LIST.ts index c6075139156..7150499e6de 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.ts @@ -1,16 +1,45 @@ -// import { RedisCommandArguments } from '.'; -// import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, Resp2Reply, CommandArguments, Command } from '../RESP/types'; -// export function transformArguments(pattern?: string): RedisCommandArguments { -// const args = ['FUNCTION', 'LIST']; +export interface FunctionListOptions { + LIBRARYNAME?: RedisArgument; +} -// if (pattern) { -// args.push(pattern); -// } +export type FunctionListReplyItem = [ + [BlobStringReply<'library_name'>, BlobStringReply], + [BlobStringReply<'engine'>, BlobStringReply], + [BlobStringReply<'functions'>, ArrayReply, BlobStringReply], + [BlobStringReply<'description'>, BlobStringReply | NullReply], + [BlobStringReply<'flags'>, SetReply], + ]>>] +] -// return args; -// } +export type FunctionListReply = ArrayReply>; -// export function transformReply(reply: Array): Array { -// return reply.map(transformFunctionListItemReply); -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(options?: FunctionListOptions) { + const args: CommandArguments = ['FUNCTION', 'LIST']; + + if (options?.LIBRARYNAME) { + args.push('LIBRARYNAME', options.LIBRARYNAME); + } + + return args; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply.map(library => ({ + library_name: library[1], + engine: library[3], + functions: library[5].map(fn => ({ + name: fn[1], + description: fn[3], + flags: fn[5] + })) + })); + }, + 3: undefined as unknown as () => FunctionListReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts index 56e6102a4b4..3c8342ab50c 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts @@ -1,42 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { MATH_FUNCTION, loadMathFunction } from '../client/index.spec'; -import { transformArguments } from './FUNCTION_LIST_WITHCODE'; +import FUNCTION_LIST_WITHCODE from './FUNCTION_LIST_WITHCODE'; +import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; describe('FUNCTION LIST WITHCODE', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'LIST', 'WITHCODE'] - ); - }); - - it('with pattern', () => { - assert.deepEqual( - transformArguments('patter*'), - ['FUNCTION', 'LIST', 'patter*', 'WITHCODE'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FUNCTION_LIST_WITHCODE.transformArguments(), + ['FUNCTION', 'LIST', 'WITHCODE'] + ); }); - testUtils.testWithClient('client.functionListWithCode', async client => { - await loadMathFunction(client); + it('with LIBRARYNAME', () => { + assert.deepEqual( + FUNCTION_LIST_WITHCODE.transformArguments({ + LIBRARYNAME: 'patter*' + }), + ['FUNCTION', 'LIST', 'LIBRARYNAME', 'patter*', 'WITHCODE'] + ); + }); + }); - assert.deepEqual( - await client.functionListWithCode(), - [{ - libraryName: MATH_FUNCTION.name, - engine: MATH_FUNCTION.engine, - functions: [{ - name: MATH_FUNCTION.library.square.NAME, - description: null, - flags: ['no-writes'] - }], - libraryCode: MATH_FUNCTION.code - }] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.functionListWithCode', async client => { + await loadMathFunction(client); + + assert.deepEqual( + await client.functionListWithCode(), + [{ + library_name: MATH_FUNCTION.name, + engine: MATH_FUNCTION.engine, + functions: [{ + name: MATH_FUNCTION.library.square.NAME, + description: null, + flags: ['no-writes'] + }], + library_code: MATH_FUNCTION.code + }] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts index 41fdae90ad4..6aa83d1d6a8 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts @@ -1,26 +1,32 @@ -// import { RedisCommandArguments } from '.'; -// import { transformArguments as transformFunctionListArguments } from './FUNCTION_LIST'; -// import { FunctionListItemReply, FunctionListRawItemReply, transformFunctionListItemReply } from './generic-transformers'; +import { TuplesToMapReply, BlobStringReply, ArrayReply, Command, Resp2Reply } from '../RESP/types'; +import FUNCTION_LIST, { FunctionListReplyItem } from './FUNCTION_LIST'; -// export function transformArguments(pattern?: string): RedisCommandArguments { -// const args = transformFunctionListArguments(pattern); -// args.push('WITHCODE'); -// return args; -// } +export type FunctionListWithCodeReply = ArrayReply, BlobStringReply], +]>>; -// type FunctionListWithCodeRawItemReply = [ -// ...FunctionListRawItemReply, -// 'library_code', -// string -// ]; - -// interface FunctionListWithCodeItemReply extends FunctionListItemReply { -// libraryCode: string; -// } - -// export function transformReply(reply: Array): Array { -// return reply.map(library => ({ -// ...transformFunctionListItemReply(library as unknown as FunctionListRawItemReply), -// libraryCode: library[7] -// })); -// } +export default { + FIRST_KEY_INDEX: FUNCTION_LIST.FIRST_KEY_INDEX, + IS_READ_ONLY: FUNCTION_LIST.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = FUNCTION_LIST.transformArguments(...args); + redisArgs.push('WITHCODE'); + return redisArgs; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply.map((library: any) => ({ + library_name: library[1], + engine: library[3], + functions: library[5].map((fn: any) => ({ + name: fn[1], + description: fn[3], + flags: fn[5] + })), + library_code: library[7] + })) as unknown as number; + }, + 3: undefined as unknown as () => FunctionListWithCodeReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts index 7be371c6b9c..fbda1630673 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts @@ -1,36 +1,71 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { MATH_FUNCTION } from '../client/index.spec'; -import { transformArguments } from './FUNCTION_LOAD'; +import FUNCTION_LOAD from './FUNCTION_LOAD'; +import { RedisClientType } from '../client'; +import { NumberReply, RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; + +export const MATH_FUNCTION = { + name: 'math', + engine: 'LUA', + code: + `#!LUA name=math + redis.register_function{ + function_name = "square", + callback = function(keys, args) return args[1] * args[1] end, + flags = { "no-writes" } + }`, + library: { + square: { + NAME: 'square', + IS_READ_ONLY: true, + NUMBER_OF_KEYS: 0, + transformArguments(number: number) { + return [number.toString()]; + }, + transformReply: undefined as unknown as () => NumberReply + } + } +}; + +export function loadMathFunction< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions +>( + client: RedisClientType +) { + return client.functionLoad( + MATH_FUNCTION.code, + { REPLACE: true } + ); +} describe('FUNCTION LOAD', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments( 'code'), - ['FUNCTION', 'LOAD', 'code'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FUNCTION_LOAD.transformArguments('code'), + ['FUNCTION', 'LOAD', 'code'] + ); + }); - it('with REPLACE', () => { - assert.deepEqual( - transformArguments('code', { - REPLACE: true - }), - ['FUNCTION', 'LOAD', 'REPLACE', 'code'] - ); - }); + it('with REPLACE', () => { + assert.deepEqual( + FUNCTION_LOAD.transformArguments('code', { + REPLACE: true + }), + ['FUNCTION', 'LOAD', 'REPLACE', 'code'] + ); }); + }); - testUtils.testWithClient('client.functionLoad', async client => { - assert.equal( - await client.functionLoad( - MATH_FUNCTION.code, - { REPLACE: true } - ), - MATH_FUNCTION.name - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.functionLoad', async client => { + assert.equal( + await loadMathFunction(client), + MATH_FUNCTION.name + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LOAD.ts b/packages/client/lib/commands/FUNCTION_LOAD.ts index c24ee0e9f81..32b030909ad 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.ts @@ -1,22 +1,22 @@ -// import { RedisCommandArguments } from '.'; +import { RedisArgument, CommandArguments, BlobStringReply, Command } from '../RESP/types'; -// interface FunctionLoadOptions { -// REPLACE?: boolean; -// } +export interface FunctionLoadOptions { + REPLACE?: boolean; +} -// export function transformArguments( -// code: string, -// options?: FunctionLoadOptions -// ): RedisCommandArguments { -// const args = ['FUNCTION', 'LOAD']; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(code: RedisArgument, options?: FunctionLoadOptions) { + const args: CommandArguments = ['FUNCTION', 'LOAD']; -// if (options?.REPLACE) { -// args.push('REPLACE'); -// } + if (options?.REPLACE) { + args.push('REPLACE'); + } -// args.push(code); + args.push(code); -// return args; -// } - -// export declare function transformReply(): string; + return args; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts index a5c2e2dcc72..546bc4a3636 100644 --- a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts @@ -1,37 +1,38 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FUNCTION_RESTORE'; +import FUNCTION_RESTORE from './FUNCTION_RESTORE'; +import { RESP_TYPES } from '../RESP/decoder'; describe('FUNCTION RESTORE', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('dump'), - ['FUNCTION', 'RESTORE', 'dump'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + FUNCTION_RESTORE.transformArguments('dump'), + ['FUNCTION', 'RESTORE', 'dump'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments('dump', 'APPEND'), - ['FUNCTION', 'RESTORE', 'dump', 'APPEND'] - ); - }); + it('with mode', () => { + assert.deepEqual( + FUNCTION_RESTORE.transformArguments('dump', { + mode: 'APPEND' + }), + ['FUNCTION', 'RESTORE', 'dump', 'APPEND'] + ); }); + }); - testUtils.testWithClient('client.functionRestore', async client => { - assert.equal( - await client.functionRestore( - await client.functionDump( - client.commandOptions({ - returnBuffers: true - }) - ), - 'FLUSH' - ), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.functionRestore', async client => { + assert.equal( + await client.functionRestore( + await client.withTypeMapping({ + [RESP_TYPES.BLOB_STRING]: Buffer + }).functionDump(), + 'FLUSH' + ), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_RESTORE.ts b/packages/client/lib/commands/FUNCTION_RESTORE.ts index 92f87288c38..8c875530562 100644 --- a/packages/client/lib/commands/FUNCTION_RESTORE.ts +++ b/packages/client/lib/commands/FUNCTION_RESTORE.ts @@ -1,16 +1,20 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SimpleStringReply, Command, RedisArgument } from '../RESP/types'; -// export function transformArguments( -// dump: RedisCommandArgument, -// mode?: 'FLUSH' | 'APPEND' | 'REPLACE' -// ): RedisCommandArguments { -// const args = ['FUNCTION', 'RESTORE', dump]; +export interface FunctionRestoreOptions { + mode?: 'FLUSH' | 'APPEND' | 'REPLACE'; +} -// if (mode) { -// args.push(mode); -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(dump: RedisArgument, options?: FunctionRestoreOptions) { + const args = ['FUNCTION', 'RESTORE', dump]; -// return args; -// } + if (options?.mode) { + args.push(options.mode); + } -// export declare function transformReply(): 'OK'; + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_STATS.spec.ts b/packages/client/lib/commands/FUNCTION_STATS.spec.ts index a5e26b5fecc..c67175a6222 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.spec.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.spec.ts @@ -1,25 +1,25 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FUNCTION_STATS'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../test-utils'; +// import { transformArguments } from './FUNCTION_STATS'; -describe('FUNCTION STATS', () => { - testUtils.isVersionGreaterThanHook([7]); +// describe('FUNCTION STATS', () => { +// testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['FUNCTION', 'STATS'] - ); - }); +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(), +// ['FUNCTION', 'STATS'] +// ); +// }); - testUtils.testWithClient('client.functionStats', async client => { - const stats = await client.functionStats(); - assert.equal(stats.runningScript, null); - assert.equal(typeof stats.engines, 'object'); - for (const [engine, { librariesCount, functionsCount }] of Object.entries(stats.engines)) { - assert.equal(typeof engine, 'string'); - assert.equal(typeof librariesCount, 'number'); - assert.equal(typeof functionsCount, 'number'); - } - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.functionStats', async client => { +// const stats = await client.functionStats(); +// assert.equal(stats.runningScript, null); +// assert.equal(typeof stats.engines, 'object'); +// for (const [engine, { librariesCount, functionsCount }] of Object.entries(stats.engines)) { +// assert.equal(typeof engine, 'string'); +// assert.equal(typeof librariesCount, 'number'); +// assert.equal(typeof functionsCount, 'number'); +// } +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/generic-transformers.spec.ts b/packages/client/lib/commands/generic-transformers.spec.ts index 0c64a2175fd..6bd1bcc8012 100644 --- a/packages/client/lib/commands/generic-transformers.spec.ts +++ b/packages/client/lib/commands/generic-transformers.spec.ts @@ -1,685 +1,685 @@ -import { strict as assert } from 'assert'; -import { - transformBooleanReply, - transformBooleanArrayReply, - pushScanArguments, - transformNumberInfinityReply, - transformNumberInfinityNullReply, - transformNumberInfinityArgument, - transformStringNumberInfinityArgument, - transformTuplesReply, - transformStreamMessagesReply, - transformStreamsMessagesReply, - transformSortedSetWithScoresReply, - pushGeoCountArgument, - pushGeoSearchArguments, - GeoReplyWith, - transformGeoMembersWithReply, - transformEXAT, - transformPXAT, - pushEvalArguments, - pushVariadicArguments, - pushVariadicNumberArguments, - pushVariadicArgument, - pushOptionalVariadicArgument, - transformCommandReply, - CommandFlags, - CommandCategories, - pushSlotRangesArguments -} from './generic-transformers'; - -describe('Generic Transformers', () => { - describe('transformBooleanReply', () => { - it('0', () => { - assert.equal( - transformBooleanReply(0), - false - ); - }); - - it('1', () => { - assert.equal( - transformBooleanReply(1), - true - ); - }); - }); - - describe('transformBooleanArrayReply', () => { - it('empty array', () => { - assert.deepEqual( - transformBooleanArrayReply([]), - [] - ); - }); - - it('0, 1', () => { - assert.deepEqual( - transformBooleanArrayReply([0, 1]), - [false, true] - ); - }); - }); - - describe('pushScanArguments', () => { - it('cusror only', () => { - assert.deepEqual( - pushScanArguments([], 0), - ['0'] - ); - }); - - it('with MATCH', () => { - assert.deepEqual( - pushScanArguments([], 0, { - MATCH: 'pattern' - }), - ['0', 'MATCH', 'pattern'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - pushScanArguments([], 0, { - COUNT: 1 - }), - ['0', 'COUNT', '1'] - ); - }); - - it('with MATCH & COUNT', () => { - assert.deepEqual( - pushScanArguments([], 0, { - MATCH: 'pattern', - COUNT: 1 - }), - ['0', 'MATCH', 'pattern', 'COUNT', '1'] - ); - }); - }); - - describe('transformNumberInfinityReply', () => { - it('0.5', () => { - assert.equal( - transformNumberInfinityReply('0.5'), - 0.5 - ); - }); - - it('+inf', () => { - assert.equal( - transformNumberInfinityReply('+inf'), - Infinity - ); - }); - - it('-inf', () => { - assert.equal( - transformNumberInfinityReply('-inf'), - -Infinity - ); - }); - }); - - describe('transformNumberInfinityNullReply', () => { - it('null', () => { - assert.equal( - transformNumberInfinityNullReply(null), - null - ); - }); - - it('1', () => { - assert.equal( - transformNumberInfinityNullReply('1'), - 1 - ); - }); - }); - - describe('transformNumberInfinityArgument', () => { - it('0.5', () => { - assert.equal( - transformNumberInfinityArgument(0.5), - '0.5' - ); - }); - - it('Infinity', () => { - assert.equal( - transformNumberInfinityArgument(Infinity), - '+inf' - ); - }); - - it('-Infinity', () => { - assert.equal( - transformNumberInfinityArgument(-Infinity), - '-inf' - ); - }); - }); - - describe('transformStringNumberInfinityArgument', () => { - it("'0.5'", () => { - assert.equal( - transformStringNumberInfinityArgument('0.5'), - '0.5' - ); - }); - - it('0.5', () => { - assert.equal( - transformStringNumberInfinityArgument(0.5), - '0.5' - ); - }); - }); - - it('transformTuplesReply', () => { - assert.deepEqual( - transformTuplesReply(['key1', 'value1', 'key2', 'value2']), - Object.create(null, { - key1: { - value: 'value1', - configurable: true, - enumerable: true - }, - key2: { - value: 'value2', - configurable: true, - enumerable: true - } - }) - ); - }); - - it('transformStreamMessagesReply', () => { - assert.deepEqual( - transformStreamMessagesReply([['0-0', ['0key', '0value']], ['1-0', ['1key', '1value']]]), - [{ - id: '0-0', - message: Object.create(null, { - '0key': { - value: '0value', - configurable: true, - enumerable: true - } - }) - }, { - id: '1-0', - message: Object.create(null, { - '1key': { - value: '1value', - configurable: true, - enumerable: true - } - }) - }] - ); - }); - - describe('transformStreamsMessagesReply', () => { - it('null', () => { - assert.equal( - transformStreamsMessagesReply(null), - null - ); - }); - - it('with messages', () => { - assert.deepEqual( - transformStreamsMessagesReply([['stream1', [['0-1', ['11key', '11value']], ['1-1', ['12key', '12value']]]], ['stream2', [['0-2', ['2key1', '2value1', '2key2', '2value2']]]]]), - [{ - name: 'stream1', - messages: [{ - id: '0-1', - message: Object.create(null, { - '11key': { - value: '11value', - configurable: true, - enumerable: true - } - }) - }, { - id: '1-1', - message: Object.create(null, { - '12key': { - value: '12value', - configurable: true, - enumerable: true - } - }) - }] - }, { - name: 'stream2', - messages: [{ - id: '0-2', - message: Object.create(null, { - '2key1': { - value: '2value1', - configurable: true, - enumerable: true - }, - '2key2': { - value: '2value2', - configurable: true, - enumerable: true - } - }) - }] - }] - ); - }); - }); - - it('transformSortedSetWithScoresReply', () => { - assert.deepEqual( - transformSortedSetWithScoresReply(['member1', '0.5', 'member2', '+inf', 'member3', '-inf']), - [{ - value: 'member1', - score: 0.5 - }, { - value: 'member2', - score: Infinity - }, { - value: 'member3', - score: -Infinity - }] - ); - }); - - describe('pushGeoCountArgument', () => { - it('undefined', () => { - assert.deepEqual( - pushGeoCountArgument([], undefined), - [] - ); - }); - - it('number', () => { - assert.deepEqual( - pushGeoCountArgument([], 1), - ['COUNT', '1'] - ); - }); - - describe('with COUNT', () => { - it('number', () => { - assert.deepEqual( - pushGeoCountArgument([], 1), - ['COUNT', '1'] - ); - }); - - describe('object', () => { - it('value', () => { - assert.deepEqual( - pushGeoCountArgument([], { value: 1 }), - ['COUNT', '1'] - ); - }); - - it('value, ANY', () => { - assert.deepEqual( - pushGeoCountArgument([], { - value: 1, - ANY: true - }), - ['COUNT', '1', 'ANY'] - ); - }); - }); - }); - }); - - describe('pushGeoSearchArguments', () => { - it('FROMMEMBER, BYRADIUS', () => { - assert.deepEqual( - pushGeoSearchArguments([], 'key', 'member', { - radius: 1, - unit: 'm' - }), - ['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] - ); - }); - - it('FROMLONLAT, BYBOX', () => { - assert.deepEqual( - pushGeoSearchArguments([], 'key', { - longitude: 1, - latitude: 2 - }, { - width: 1, - height: 2, - unit: 'm' - }), - ['key', 'FROMLONLAT', '1', '2', 'BYBOX', '1', '2', 'm'] - ); - }); - - it('with SORT', () => { - assert.deepEqual( - pushGeoSearchArguments([], 'key', 'member', { - radius: 1, - unit: 'm' - }, { - SORT: 'ASC' - }), - ['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC'] - ); - }); - }); - - describe('transformGeoMembersWithReply', () => { - it('DISTANCE', () => { - assert.deepEqual( - transformGeoMembersWithReply([ - [ - '1', - '2' - ], - [ - '3', - '4' - ] - ], [GeoReplyWith.DISTANCE]), - [{ - member: '1', - distance: '2' - }, { - member: '3', - distance: '4' - }] - ); - }); - - it('HASH', () => { - assert.deepEqual( - transformGeoMembersWithReply([ - [ - '1', - 2 - ], - [ - '3', - 4 - ] - ], [GeoReplyWith.HASH]), - [{ - member: '1', - hash: 2 - }, { - member: '3', - hash: 4 - }] - ); - }); - - it('COORDINATES', () => { - assert.deepEqual( - transformGeoMembersWithReply([ - [ - '1', - [ - '2', - '3' - ] - ], - [ - '4', - [ - '5', - '6' - ] - ] - ], [GeoReplyWith.COORDINATES]), - [{ - member: '1', - coordinates: { - longitude: '2', - latitude: '3' - } - }, { - member: '4', - coordinates: { - longitude: '5', - latitude: '6' - } - }] - ); - }); - - it('DISTANCE, HASH, COORDINATES', () => { - assert.deepEqual( - transformGeoMembersWithReply([ - [ - '1', - '2', - 3, - [ - '4', - '5' - ] - ], - [ - '6', - '7', - 8, - [ - '9', - '10' - ] - ] - ], [GeoReplyWith.DISTANCE, GeoReplyWith.HASH, GeoReplyWith.COORDINATES]), - [{ - member: '1', - distance: '2', - hash: 3, - coordinates: { - longitude: '4', - latitude: '5' - } - }, { - member: '6', - distance: '7', - hash: 8, - coordinates: { - longitude: '9', - latitude: '10' - } - }] - ); - }); - }); - - describe('transformEXAT', () => { - it('number', () => { - assert.equal( - transformEXAT(1), - '1' - ); - }); - - it('date', () => { - const d = new Date(); - assert.equal( - transformEXAT(d), - Math.floor(d.getTime() / 1000).toString() - ); - }); - }); - - describe('transformPXAT', () => { - it('number', () => { - assert.equal( - transformPXAT(1), - '1' - ); - }); - - it('date', () => { - const d = new Date(); - assert.equal( - transformPXAT(d), - d.getTime().toString() - ); - }); - }); - - describe('pushEvalArguments', () => { - it('empty', () => { - assert.deepEqual( - pushEvalArguments([]), - ['0'] - ); - }); - - it('with keys', () => { - assert.deepEqual( - pushEvalArguments([], { - keys: ['key'] - }), - ['1', 'key'] - ); - }); - - it('with arguments', () => { - assert.deepEqual( - pushEvalArguments([], { - arguments: ['argument'] - }), - ['0', 'argument'] - ); - }); - - it('with keys and arguments', () => { - assert.deepEqual( - pushEvalArguments([], { - keys: ['key'], - arguments: ['argument'] - }), - ['1', 'key', 'argument'] - ); - }); - }); - - describe('pushVariadicArguments', () => { - it('string', () => { - assert.deepEqual( - pushVariadicArguments([], 'string'), - ['string'] - ); - }); - - it('array', () => { - assert.deepEqual( - pushVariadicArguments([], ['1', '2']), - ['1', '2'] - ); - }); - }); - - describe('pushVariadicNumberArguments', () => { - it('number', () => { - assert.deepEqual( - pushVariadicNumberArguments([], 0), - ['0'] - ); - }); - - it('array', () => { - assert.deepEqual( - pushVariadicNumberArguments([], [0, 1]), - ['0', '1'] - ); - }); - }); - - describe('pushVariadicArgument', () => { - it('string', () => { - assert.deepEqual( - pushVariadicArgument([], 'string'), - ['1', 'string'] - ); - }); - - it('array', () => { - assert.deepEqual( - pushVariadicArgument([], ['1', '2']), - ['2', '1', '2'] - ); - }); - }); - - describe('pushOptionalVariadicArgument', () => { - it('undefined', () => { - assert.deepEqual( - pushOptionalVariadicArgument([], 'name', undefined), - [] - ); - }); - - it('string', () => { - assert.deepEqual( - pushOptionalVariadicArgument([], 'name', 'string'), - ['name', '1', 'string'] - ); - }); - - it('array', () => { - assert.deepEqual( - pushOptionalVariadicArgument([], 'name', ['1', '2']), - ['name', '2', '1', '2'] - ); - }); - }); - - it('transformCommandReply', () => { - assert.deepEqual( - transformCommandReply([ - 'ping', - -1, - [CommandFlags.STALE, CommandFlags.FAST], - 0, - 0, - 0, - [CommandCategories.FAST, CommandCategories.CONNECTION] - ]), - { - name: 'ping', - arity: -1, - flags: new Set([CommandFlags.STALE, CommandFlags.FAST]), - firstKeyIndex: 0, - lastKeyIndex: 0, - step: 0, - categories: new Set([CommandCategories.FAST, CommandCategories.CONNECTION]) - } - ); - }); - - describe('pushSlotRangesArguments', () => { - it('single range', () => { - assert.deepEqual( - pushSlotRangesArguments([], { - start: 0, - end: 1 - }), - ['0', '1'] - ); - }); - - it('multiple ranges', () => { - assert.deepEqual( - pushSlotRangesArguments([], [{ - start: 0, - end: 1 - }, { - start: 2, - end: 3 - }]), - ['0', '1', '2', '3'] - ); - }); - }); -}); +// import { strict as assert } from 'assert'; +// import { +// transformBooleanReply, +// transformBooleanArrayReply, +// pushScanArguments, +// transformNumberInfinityReply, +// transformNumberInfinityNullReply, +// transformNumberInfinityArgument, +// transformStringNumberInfinityArgument, +// transformTuplesReply, +// transformStreamMessagesReply, +// transformStreamsMessagesReply, +// transformSortedSetWithScoresReply, +// pushGeoCountArgument, +// pushGeoSearchArguments, +// GeoReplyWith, +// transformGeoMembersWithReply, +// transformEXAT, +// transformPXAT, +// pushEvalArguments, +// pushVariadicArguments, +// pushVariadicNumberArguments, +// pushVariadicArgument, +// pushOptionalVariadicArgument, +// transformCommandReply, +// CommandFlags, +// CommandCategories, +// pushSlotRangesArguments +// } from './generic-transformers'; + +// describe('Generic Transformers', () => { +// describe('transformBooleanReply', () => { +// it('0', () => { +// assert.equal( +// transformBooleanReply(0), +// false +// ); +// }); + +// it('1', () => { +// assert.equal( +// transformBooleanReply(1), +// true +// ); +// }); +// }); + +// describe('transformBooleanArrayReply', () => { +// it('empty array', () => { +// assert.deepEqual( +// transformBooleanArrayReply([]), +// [] +// ); +// }); + +// it('0, 1', () => { +// assert.deepEqual( +// transformBooleanArrayReply([0, 1]), +// [false, true] +// ); +// }); +// }); + +// describe('pushScanArguments', () => { +// it('cusror only', () => { +// assert.deepEqual( +// pushScanArguments([], 0), +// ['0'] +// ); +// }); + +// it('with MATCH', () => { +// assert.deepEqual( +// pushScanArguments([], 0, { +// MATCH: 'pattern' +// }), +// ['0', 'MATCH', 'pattern'] +// ); +// }); + +// it('with COUNT', () => { +// assert.deepEqual( +// pushScanArguments([], 0, { +// COUNT: 1 +// }), +// ['0', 'COUNT', '1'] +// ); +// }); + +// it('with MATCH & COUNT', () => { +// assert.deepEqual( +// pushScanArguments([], 0, { +// MATCH: 'pattern', +// COUNT: 1 +// }), +// ['0', 'MATCH', 'pattern', 'COUNT', '1'] +// ); +// }); +// }); + +// describe('transformNumberInfinityReply', () => { +// it('0.5', () => { +// assert.equal( +// transformNumberInfinityReply('0.5'), +// 0.5 +// ); +// }); + +// it('+inf', () => { +// assert.equal( +// transformNumberInfinityReply('+inf'), +// Infinity +// ); +// }); + +// it('-inf', () => { +// assert.equal( +// transformNumberInfinityReply('-inf'), +// -Infinity +// ); +// }); +// }); + +// describe('transformNumberInfinityNullReply', () => { +// it('null', () => { +// assert.equal( +// transformNumberInfinityNullReply(null), +// null +// ); +// }); + +// it('1', () => { +// assert.equal( +// transformNumberInfinityNullReply('1'), +// 1 +// ); +// }); +// }); + +// describe('transformNumberInfinityArgument', () => { +// it('0.5', () => { +// assert.equal( +// transformNumberInfinityArgument(0.5), +// '0.5' +// ); +// }); + +// it('Infinity', () => { +// assert.equal( +// transformNumberInfinityArgument(Infinity), +// '+inf' +// ); +// }); + +// it('-Infinity', () => { +// assert.equal( +// transformNumberInfinityArgument(-Infinity), +// '-inf' +// ); +// }); +// }); + +// describe('transformStringNumberInfinityArgument', () => { +// it("'0.5'", () => { +// assert.equal( +// transformStringNumberInfinityArgument('0.5'), +// '0.5' +// ); +// }); + +// it('0.5', () => { +// assert.equal( +// transformStringNumberInfinityArgument(0.5), +// '0.5' +// ); +// }); +// }); + +// it('transformTuplesReply', () => { +// assert.deepEqual( +// transformTuplesReply(['key1', 'value1', 'key2', 'value2']), +// Object.create(null, { +// key1: { +// value: 'value1', +// configurable: true, +// enumerable: true +// }, +// key2: { +// value: 'value2', +// configurable: true, +// enumerable: true +// } +// }) +// ); +// }); + +// it('transformStreamMessagesReply', () => { +// assert.deepEqual( +// transformStreamMessagesReply([['0-0', ['0key', '0value']], ['1-0', ['1key', '1value']]]), +// [{ +// id: '0-0', +// message: Object.create(null, { +// '0key': { +// value: '0value', +// configurable: true, +// enumerable: true +// } +// }) +// }, { +// id: '1-0', +// message: Object.create(null, { +// '1key': { +// value: '1value', +// configurable: true, +// enumerable: true +// } +// }) +// }] +// ); +// }); + +// describe('transformStreamsMessagesReply', () => { +// it('null', () => { +// assert.equal( +// transformStreamsMessagesReply(null), +// null +// ); +// }); + +// it('with messages', () => { +// assert.deepEqual( +// transformStreamsMessagesReply([['stream1', [['0-1', ['11key', '11value']], ['1-1', ['12key', '12value']]]], ['stream2', [['0-2', ['2key1', '2value1', '2key2', '2value2']]]]]), +// [{ +// name: 'stream1', +// messages: [{ +// id: '0-1', +// message: Object.create(null, { +// '11key': { +// value: '11value', +// configurable: true, +// enumerable: true +// } +// }) +// }, { +// id: '1-1', +// message: Object.create(null, { +// '12key': { +// value: '12value', +// configurable: true, +// enumerable: true +// } +// }) +// }] +// }, { +// name: 'stream2', +// messages: [{ +// id: '0-2', +// message: Object.create(null, { +// '2key1': { +// value: '2value1', +// configurable: true, +// enumerable: true +// }, +// '2key2': { +// value: '2value2', +// configurable: true, +// enumerable: true +// } +// }) +// }] +// }] +// ); +// }); +// }); + +// it('transformSortedSetWithScoresReply', () => { +// assert.deepEqual( +// transformSortedSetWithScoresReply(['member1', '0.5', 'member2', '+inf', 'member3', '-inf']), +// [{ +// value: 'member1', +// score: 0.5 +// }, { +// value: 'member2', +// score: Infinity +// }, { +// value: 'member3', +// score: -Infinity +// }] +// ); +// }); + +// describe('pushGeoCountArgument', () => { +// it('undefined', () => { +// assert.deepEqual( +// pushGeoCountArgument([], undefined), +// [] +// ); +// }); + +// it('number', () => { +// assert.deepEqual( +// pushGeoCountArgument([], 1), +// ['COUNT', '1'] +// ); +// }); + +// describe('with COUNT', () => { +// it('number', () => { +// assert.deepEqual( +// pushGeoCountArgument([], 1), +// ['COUNT', '1'] +// ); +// }); + +// describe('object', () => { +// it('value', () => { +// assert.deepEqual( +// pushGeoCountArgument([], { value: 1 }), +// ['COUNT', '1'] +// ); +// }); + +// it('value, ANY', () => { +// assert.deepEqual( +// pushGeoCountArgument([], { +// value: 1, +// ANY: true +// }), +// ['COUNT', '1', 'ANY'] +// ); +// }); +// }); +// }); +// }); + +// describe('pushGeoSearchArguments', () => { +// it('FROMMEMBER, BYRADIUS', () => { +// assert.deepEqual( +// pushGeoSearchArguments([], 'key', 'member', { +// radius: 1, +// unit: 'm' +// }), +// ['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] +// ); +// }); + +// it('FROMLONLAT, BYBOX', () => { +// assert.deepEqual( +// pushGeoSearchArguments([], 'key', { +// longitude: 1, +// latitude: 2 +// }, { +// width: 1, +// height: 2, +// unit: 'm' +// }), +// ['key', 'FROMLONLAT', '1', '2', 'BYBOX', '1', '2', 'm'] +// ); +// }); + +// it('with SORT', () => { +// assert.deepEqual( +// pushGeoSearchArguments([], 'key', 'member', { +// radius: 1, +// unit: 'm' +// }, { +// SORT: 'ASC' +// }), +// ['key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC'] +// ); +// }); +// }); + +// describe('transformGeoMembersWithReply', () => { +// it('DISTANCE', () => { +// assert.deepEqual( +// transformGeoMembersWithReply([ +// [ +// '1', +// '2' +// ], +// [ +// '3', +// '4' +// ] +// ], [GeoReplyWith.DISTANCE]), +// [{ +// member: '1', +// distance: '2' +// }, { +// member: '3', +// distance: '4' +// }] +// ); +// }); + +// it('HASH', () => { +// assert.deepEqual( +// transformGeoMembersWithReply([ +// [ +// '1', +// 2 +// ], +// [ +// '3', +// 4 +// ] +// ], [GeoReplyWith.HASH]), +// [{ +// member: '1', +// hash: 2 +// }, { +// member: '3', +// hash: 4 +// }] +// ); +// }); + +// it('COORDINATES', () => { +// assert.deepEqual( +// transformGeoMembersWithReply([ +// [ +// '1', +// [ +// '2', +// '3' +// ] +// ], +// [ +// '4', +// [ +// '5', +// '6' +// ] +// ] +// ], [GeoReplyWith.COORDINATES]), +// [{ +// member: '1', +// coordinates: { +// longitude: '2', +// latitude: '3' +// } +// }, { +// member: '4', +// coordinates: { +// longitude: '5', +// latitude: '6' +// } +// }] +// ); +// }); + +// it('DISTANCE, HASH, COORDINATES', () => { +// assert.deepEqual( +// transformGeoMembersWithReply([ +// [ +// '1', +// '2', +// 3, +// [ +// '4', +// '5' +// ] +// ], +// [ +// '6', +// '7', +// 8, +// [ +// '9', +// '10' +// ] +// ] +// ], [GeoReplyWith.DISTANCE, GeoReplyWith.HASH, GeoReplyWith.COORDINATES]), +// [{ +// member: '1', +// distance: '2', +// hash: 3, +// coordinates: { +// longitude: '4', +// latitude: '5' +// } +// }, { +// member: '6', +// distance: '7', +// hash: 8, +// coordinates: { +// longitude: '9', +// latitude: '10' +// } +// }] +// ); +// }); +// }); + +// describe('transformEXAT', () => { +// it('number', () => { +// assert.equal( +// transformEXAT(1), +// '1' +// ); +// }); + +// it('date', () => { +// const d = new Date(); +// assert.equal( +// transformEXAT(d), +// Math.floor(d.getTime() / 1000).toString() +// ); +// }); +// }); + +// describe('transformPXAT', () => { +// it('number', () => { +// assert.equal( +// transformPXAT(1), +// '1' +// ); +// }); + +// it('date', () => { +// const d = new Date(); +// assert.equal( +// transformPXAT(d), +// d.getTime().toString() +// ); +// }); +// }); + +// describe('pushEvalArguments', () => { +// it('empty', () => { +// assert.deepEqual( +// pushEvalArguments([]), +// ['0'] +// ); +// }); + +// it('with keys', () => { +// assert.deepEqual( +// pushEvalArguments([], { +// keys: ['key'] +// }), +// ['1', 'key'] +// ); +// }); + +// it('with arguments', () => { +// assert.deepEqual( +// pushEvalArguments([], { +// arguments: ['argument'] +// }), +// ['0', 'argument'] +// ); +// }); + +// it('with keys and arguments', () => { +// assert.deepEqual( +// pushEvalArguments([], { +// keys: ['key'], +// arguments: ['argument'] +// }), +// ['1', 'key', 'argument'] +// ); +// }); +// }); + +// describe('pushVariadicArguments', () => { +// it('string', () => { +// assert.deepEqual( +// pushVariadicArguments([], 'string'), +// ['string'] +// ); +// }); + +// it('array', () => { +// assert.deepEqual( +// pushVariadicArguments([], ['1', '2']), +// ['1', '2'] +// ); +// }); +// }); + +// describe('pushVariadicNumberArguments', () => { +// it('number', () => { +// assert.deepEqual( +// pushVariadicNumberArguments([], 0), +// ['0'] +// ); +// }); + +// it('array', () => { +// assert.deepEqual( +// pushVariadicNumberArguments([], [0, 1]), +// ['0', '1'] +// ); +// }); +// }); + +// describe('pushVariadicArgument', () => { +// it('string', () => { +// assert.deepEqual( +// pushVariadicArgument([], 'string'), +// ['1', 'string'] +// ); +// }); + +// it('array', () => { +// assert.deepEqual( +// pushVariadicArgument([], ['1', '2']), +// ['2', '1', '2'] +// ); +// }); +// }); + +// describe('pushOptionalVariadicArgument', () => { +// it('undefined', () => { +// assert.deepEqual( +// pushOptionalVariadicArgument([], 'name', undefined), +// [] +// ); +// }); + +// it('string', () => { +// assert.deepEqual( +// pushOptionalVariadicArgument([], 'name', 'string'), +// ['name', '1', 'string'] +// ); +// }); + +// it('array', () => { +// assert.deepEqual( +// pushOptionalVariadicArgument([], 'name', ['1', '2']), +// ['name', '2', '1', '2'] +// ); +// }); +// }); + +// it('transformCommandReply', () => { +// assert.deepEqual( +// transformCommandReply([ +// 'ping', +// -1, +// [CommandFlags.STALE, CommandFlags.FAST], +// 0, +// 0, +// 0, +// [CommandCategories.FAST, CommandCategories.CONNECTION] +// ]), +// { +// name: 'ping', +// arity: -1, +// flags: new Set([CommandFlags.STALE, CommandFlags.FAST]), +// firstKeyIndex: 0, +// lastKeyIndex: 0, +// step: 0, +// categories: new Set([CommandCategories.FAST, CommandCategories.CONNECTION]) +// } +// ); +// }); + +// describe('pushSlotRangesArguments', () => { +// it('single range', () => { +// assert.deepEqual( +// pushSlotRangesArguments([], { +// start: 0, +// end: 1 +// }), +// ['0', '1'] +// ); +// }); + +// it('multiple ranges', () => { +// assert.deepEqual( +// pushSlotRangesArguments([], [{ +// start: 0, +// end: 1 +// }, { +// start: 2, +// end: 3 +// }]), +// ['0', '1', '2', '3'] +// ); +// }); +// }); +// }); diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index ee72bb00041..25b602c8441 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,13 +1,5 @@ import { ArrayReply, BlobStringReply, CommandArguments, DoubleReply, NullReply, RedisArgument, Resp2Reply } from '../RESP/types'; -// export function transformBooleanReply(reply: number): boolean { -// return reply === 1; -// } - -// export function transformBooleanArrayReply(reply: Array): Array { -// return reply.map(transformBooleanReply); -// } - export type BitValue = 0 | 1; export function transformDoubleReply(reply: BlobStringReply): number { diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 4e41be07c1b..299b805905e 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -41,6 +41,7 @@ import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; import COPY from './COPY'; +import DBSIZE from './DBSIZE'; import DECR from './DECR'; import DECRBY from './DECRBY'; import DEL from './DEL'; @@ -79,6 +80,17 @@ import EXPIREAT from './EXPIREAT'; import EXPIRETIME from './EXPIRETIME'; import FLUSHALL from './FLUSHALL'; import FLUSHDB from './FLUSHDB'; +import FCALL from './FCALL'; +import FCALL_RO from './FCALL_RO'; +import FUNCTION_DELETE from './FUNCTION_DELETE'; +import FUNCTION_DUMP from './FUNCTION_DUMP'; +import FUNCTION_FLUSH from './FUNCTION_FLUSH'; +import FUNCTION_KILL from './FUNCTION_KILL'; +import FUNCTION_LIST_WITHCODE from './FUNCTION_LIST_WITHCODE'; +import FUNCTION_LIST from './FUNCTION_LIST'; +import FUNCTION_LOAD from './FUNCTION_LOAD'; +// import FUNCTION_RESTORE from './FUNCTION_RESTORE'; +// import FUNCTION_STATS from './FUNCTION_STATS'; import HDEL from './HDEL'; import HELLO from './HELLO'; import HEXISTS from './HEXISTS'; @@ -246,6 +258,786 @@ import ZUNION from './ZUNION'; import ZUNIONSTORE from './ZUNIONSTORE'; import { Command } from '../RESP/types'; +type ACL_CAT = typeof import('./ACL_CAT').default; +type ACL_DRYRUN = typeof import('./ACL_DRYRUN').default; +type ACL_GENPASS = typeof import('./ACL_GENPASS').default; +type ACL_GETUSER = typeof import('./ACL_GETUSER').default; +type ACL_LIST = typeof import('./ACL_LIST').default; +type ACL_LOAD = typeof import('./ACL_LOAD').default; +type ACL_LOG_RESET = typeof import('./ACL_LOG_RESET').default; +type ACL_LOG = typeof import('./ACL_LOG').default; +type ACL_SAVE = typeof import('./ACL_SAVE').default; +type ACL_SETUSER = typeof import('./ACL_SETUSER').default; +type ACL_USERS = typeof import('./ACL_USERS').default; +type ACL_WHOAMI = typeof import('./ACL_WHOAMI').default; +type APPEND = typeof import('./APPEND').default; +type ASKING = typeof import('./ASKING').default; +type AUTH = typeof import('./AUTH').default; +type BGREWRITEAOF = typeof import('./BGREWRITEAOF').default; +type BGSAVE = typeof import('./BGSAVE').default; +type BITCOUNT = typeof import('./BITCOUNT').default; +type BITFIELD_RO = typeof import('./BITFIELD_RO').default; +type BITFIELD = typeof import('./BITFIELD').default; +type BITOP = typeof import('./BITOP').default; +type BITPOS = typeof import('./BITPOS').default; +type BLMOVE = typeof import('./BLMOVE').default; +type BLMPOP = typeof import('./BLMPOP').default; +type BLPOP = typeof import('./BLPOP').default; +type BRPOP = typeof import('./BRPOP').default; +type BRPOPLPUSH = typeof import('./BRPOPLPUSH').default; +type CLIENT_CACHING = typeof import('./CLIENT_CACHING').default; +type CLIENT_GETNAME = typeof import('./CLIENT_GETNAME').default; +type CLIENT_GETREDIR = typeof import('./CLIENT_GETREDIR').default; +type CLIENT_ID = typeof import('./CLIENT_ID').default; +type CLIENT_INFO = typeof import('./CLIENT_INFO').default; +type CLIENT_KILL = typeof import('./CLIENT_KILL').default; +type CLIENT_LIST = typeof import('./CLIENT_LIST').default; +type CLIENT_NO_EVICT = typeof import('./CLIENT_NO-EVICT').default; +type CLIENT_PAUSE = typeof import('./CLIENT_PAUSE').default; +type CLIENT_SETNAME = typeof import('./CLIENT_SETNAME').default; +type CLUSTER_ADDSLOTS = typeof import('./CLUSTER_ADDSLOTS').default; +type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; +type CLUSTER_MEET = typeof import('./CLUSTER_MEET').default; +type CLUSTER_MYID = typeof import('./CLUSTER_MYID').default; +type CLUSTER_REPLICATE = typeof import('./CLUSTER_REPLICATE').default; +type COPY = typeof import('./COPY').default; +type DBSIZE = typeof DBSIZE; +type DECR = typeof import('./DECR').default; +type DECRBY = typeof import('./DECRBY').default; +type DEL = typeof import('./DEL').default; +type DUMP = typeof import('./DUMP').default; +type ECHO = typeof import('./ECHO').default; +type EVAL_RO = typeof import('./EVAL_RO').default; +type EVAL = typeof import('./EVAL').default; +type EVALSHA_RO = typeof import('./EVALSHA_RO').default; +type EVALSHA = typeof import('./EVALSHA').default; +type GEOADD = typeof import('./GEOADD').default; +type GEODIST = typeof import('./GEODIST').default; +type GEOHASH = typeof import('./GEOHASH').default; +type GEOPOS = typeof import('./GEOPOS').default; +type GEORADIUS_RO_WITH = typeof import('./GEORADIUS_RO_WITH').default; +type GEORADIUS_RO = typeof import('./GEORADIUS_RO').default; +type GEORADIUS_STORE = typeof import('./GEORADIUS_STORE').default; +type GEORADIUS_WITH = typeof import('./GEORADIUS_WITH').default; +type GEORADIUS = typeof import('./GEORADIUS').default; +type GEORADIUSBYMEMBER_RO_WITH = typeof import('./GEORADIUSBYMEMBER_RO_WITH').default; +type GEORADIUSBYMEMBER_RO = typeof import('./GEORADIUSBYMEMBER_RO').default; +type GEORADIUSBYMEMBER_STORE = typeof import('./GEORADIUSBYMEMBER_STORE').default; +type GEORADIUSBYMEMBER_WITH = typeof import('./GEORADIUSBYMEMBER_WITH').default; +type GEORADIUSBYMEMBER = typeof import('./GEORADIUSBYMEMBER').default; +type GEOSEARCH_WITH = typeof import('./GEOSEARCH_WITH').default; +type GEOSEARCH = typeof import('./GEOSEARCH').default; +type GEOSEARCHSTORE = typeof import('./GEOSEARCHSTORE').default; +type GET = typeof import('./GET').default; +type GETBIT = typeof import('./GETBIT').default; +type GETDEL = typeof import('./GETDEL').default; +type GETEX = typeof import('./GETEX').default; +type GETRANGE = typeof import('./GETRANGE').default; +type GETSET = typeof import('./GETSET').default; +type EXISTS = typeof import('./EXISTS').default; +type EXPIRE = typeof import('./EXPIRE').default; +type EXPIREAT = typeof import('./EXPIREAT').default; +type EXPIRETIME = typeof import('./EXPIRETIME').default; +type FLUSHALL = typeof import('./FLUSHALL').default; +type FLUSHDB = typeof import('./FLUSHDB').default; +type FCALL = typeof import('./FCALL').default; +type FCALL_RO = typeof import('./FCALL_RO').default; +type FUNCTION_DELETE = typeof import('./FUNCTION_DELETE').default; +type FUNCTION_DUMP = typeof import('./FUNCTION_DUMP').default; +type FUNCTION_FLUSH = typeof import('./FUNCTION_FLUSH').default; +type FUNCTION_KILL = typeof import('./FUNCTION_KILL').default; +type FUNCTION_LIST_WITHCODE = typeof import('./FUNCTION_LIST_WITHCODE').default; +type FUNCTION_LIST = typeof import('./FUNCTION_LIST').default; +type FUNCTION_LOAD = typeof import('./FUNCTION_LOAD').default; +// type FUNCTION_RESTORE = typeof import('./FUNCTION_RESTORE').default; +// type FUNCTION_STATS = typeof import('./FUNCTION_STATS').default; +type HDEL = typeof import('./HDEL').default; +type HELLO = typeof import('./HELLO').default; +type HEXISTS = typeof import('./HEXISTS').default; +type HGET = typeof import('./HGET').default; +type HGETALL = typeof import('./HGETALL').default; +type HINCRBY = typeof import('./HINCRBY').default; +type HINCRBYFLOAT = typeof import('./HINCRBYFLOAT').default; +type HKEYS = typeof import('./HKEYS').default; +type HLEN = typeof import('./HLEN').default; +type HMGET = typeof import('./HMGET').default; +type HRANDFIELD_COUNT_WITHVALUES = typeof import('./HRANDFIELD_COUNT_WITHVALUES').default; +type HRANDFIELD_COUNT = typeof import('./HRANDFIELD_COUNT').default; +type HRANDFIELD = typeof import('./HRANDFIELD').default; +type HSCAN = typeof import('./HSCAN').default; +type HSET = typeof import('./HSET').default; +type HSETNX = typeof import('./HSETNX').default; +type HSTRLEN = typeof import('./HSTRLEN').default; +type HVALS = typeof import('./HVALS').default; +type INCR = typeof import('./INCR').default; +type INCRBY = typeof import('./INCRBY').default; +type INCRBYFLOAT = typeof import('./INCRBYFLOAT').default; +type INFO = typeof import('./INFO').default; +type KEYS = typeof import('./KEYS').default; +type LASTSAVE = typeof import('./LASTSAVE').default; +type LCS_IDX_WITHMATCHLEN = typeof import('./LCS_IDX_WITHMATCHLEN').default; +type LCS_IDX = typeof import('./LCS_IDX').default; +type LCS_LEN = typeof import('./LCS_LEN').default; +type LCS = typeof import('./LCS').default; +type LINDEX = typeof import('./LINDEX').default; +type LINSERT = typeof import('./LINSERT').default; +type LLEN = typeof import('./LLEN').default; +type LMOVE = typeof import('./LMOVE').default; +type LMPOP = typeof import('./LMPOP').default; +type LOLWUT = typeof import('./LOLWUT').default; +type LPOP_COUNT = typeof import('./LPOP_COUNT').default; +type LPOP = typeof import('./LPOP').default; +type LPOS_COUNT = typeof import('./LPOS_COUNT').default; +type LPOS = typeof import('./LPOS').default; +type LPUSH = typeof import('./LPUSH').default; +type LPUSHX = typeof import('./LPUSHX').default; +type LRANGE = typeof import('./LRANGE').default; +type LREM = typeof import('./LREM').default; +type LSET = typeof import('./LSET').default; +type LTRIM = typeof import('./LTRIM').default; +type MEMORY_DOCTOR = typeof import('./MEMORY_DOCTOR').default; +type MEMORY_MALLOC_STATS = typeof import('./MEMORY_MALLOC-STATS').default; +type MEMORY_PURGE = typeof import('./MEMORY_PURGE').default; +// type MEMORY_STATS = typeof import('./MEMORY_STATS').default; +type MEMORY_USAGE = typeof import('./MEMORY_USAGE').default; +type MGET = typeof import('./MGET').default; +type MODULE_LIST = typeof import('./MODULE_LIST').default; +type MODULE_LOAD = typeof import('./MODULE_LOAD').default; +type MODULE_UNLOAD = typeof import('./MODULE_UNLOAD').default; +type MOVE = typeof import('./MOVE').default; +type MSET = typeof import('./MSET').default; +type MSETNX = typeof import('./MSETNX').default; +type OBJECT_ENCODING = typeof import('./OBJECT_ENCODING').default; +type OBJECT_FREQ = typeof import('./OBJECT_FREQ').default; +type OBJECT_IDLETIME = typeof import('./OBJECT_IDLETIME').default; +type OBJECT_REFCOUNT = typeof import('./OBJECT_REFCOUNT').default; +type PERSIST = typeof import('./PERSIST').default; +type PEXPIRE = typeof import('./PEXPIRE').default; +type PEXPIREAT = typeof import('./PEXPIREAT').default; +type PEXPIRETIME = typeof import('./PEXPIRETIME').default; +type PFADD = typeof import('./PFADD').default; +type PFCOUNT = typeof import('./PFCOUNT').default; +type PFMERGE = typeof import('./PFMERGE').default; +type PING = typeof import('./PING').default; +type PSETEX = typeof import('./PSETEX').default; +type PTTL = typeof import('./PTTL').default; +type PUBLISH = typeof import('./PUBLISH').default; +type PUBSUB_CHANNELS = typeof import('./PUBSUB_CHANNELS').default; +type PUBSUB_NUMPAT = typeof import('./PUBSUB_NUMPAT').default; +type PUBSUB_NUMSUB = typeof import('./PUBSUB_NUMSUB').default; +type PUBSUB_SHARDCHANNELS = typeof import('./PUBSUB_SHARDCHANNELS').default; +type RANDOMKEY = typeof import('./RANDOMKEY').default; +type READONLY = typeof import('./READONLY').default; +type RENAME = typeof import('./RENAME').default; +type RENAMENX = typeof import('./RENAMENX').default; +type RPOP_COUNT = typeof import('./RPOP_COUNT').default; +type RPOP = typeof import('./RPOP').default; +type RPOPLPUSH = typeof import('./RPOPLPUSH').default; +type RPUSH = typeof import('./RPUSH').default; +type RPUSHX = typeof import('./RPUSHX').default; +type SADD = typeof import('./SADD').default; +type SCAN = typeof import('./SCAN').default; +type SCARD = typeof import('./SCARD').default; +type SCRIPT_DEBUG = typeof import('./SCRIPT_DEBUG').default; +type SCRIPT_EXISTS = typeof import('./SCRIPT_EXISTS').default; +type SCRIPT_FLUSH = typeof import('./SCRIPT_FLUSH').default; +type SCRIPT_KILL = typeof import('./SCRIPT_KILL').default; +type SCRIPT_LOAD = typeof import('./SCRIPT_LOAD').default; +type SDIFF = typeof import('./SDIFF').default; +type SDIFFSTORE = typeof import('./SDIFFSTORE').default; +type SET = typeof import('./SET').default; +type SETBIT = typeof import('./SETBIT').default; +type SETEX = typeof import('./SETEX').default; +type SETNX = typeof import('./SETNX').default; +type SETRANGE = typeof import('./SETRANGE').default; +type SINTER = typeof import('./SINTER').default; +type SINTERCARD = typeof import('./SINTERCARD').default; +type SINTERSTORE = typeof import('./SINTERSTORE').default; +type SISMEMBER = typeof import('./SISMEMBER').default; +type SMEMBERS = typeof import('./SMEMBERS').default; +type SMISMEMBER = typeof import('./SMISMEMBER').default; +type SMOVE = typeof import('./SMOVE').default; +type SORT_RO = typeof import('./SORT_RO').default; +type SORT_STORE = typeof import('./SORT_STORE').default; +type SORT = typeof import('./SORT').default; +type SPOP_COUNT = typeof import('./SPOP_COUNT').default; +type SPOP = typeof import('./SPOP').default; +type SPUBLISH = typeof import('./SPUBLISH').default; +type SRANDMEMBER_COUNT = typeof import('./SRANDMEMBER_COUNT').default; +type SRANDMEMBER = typeof import('./SRANDMEMBER').default; +type SREM = typeof import('./SREM').default; +type SSCAN = typeof import('./SSCAN').default; +type STRLEN = typeof import('./STRLEN').default; +type SUNION = typeof import('./SUNION').default; +type SUNIONSTORE = typeof import('./SUNIONSTORE').default; +type TOUCH = typeof import('./TOUCH').default; +type TTL = typeof import('./TTL').default; +type TYPE = typeof import('./TYPE').default; +type UNLINK = typeof import('./UNLINK').default; +type UNWATCH = typeof import('./UNWATCH').default; +type WAIT = typeof import('./WAIT').default; +type WATCH = typeof import('./WATCH').default; +type XACK = typeof import('./XACK').default; +type XADD_NOMKSTREAM = typeof import('./XADD_NOMKSTREAM').default; +type XADD = typeof import('./XADD').default; +type XDEL = typeof import('./XDEL').default; +type XSETID = typeof import('./XSETID').default; +type XTRIM = typeof import('./XTRIM').default; +type XLEN = typeof import('./XLEN').default; +type ZADD_INCR = typeof import('./ZADD_INCR').default; +type ZADD = typeof import('./ZADD').default; +type ZCARD = typeof import('./ZCARD').default; +type ZCOUNT = typeof import('./ZCOUNT').default; +type ZDIFF_WITHSCORES = typeof import('./ZDIFF_WITHSCORES').default; +type ZDIFF = typeof import('./ZDIFF').default; +type ZDIFFSTORE = typeof import('./ZDIFFSTORE').default; +type ZINCRBY = typeof import('./ZINCRBY').default; +type ZINTER_WITHSCORES = typeof import('./ZINTER_WITHSCORES').default; +type ZINTER = typeof import('./ZINTER').default; +type ZINTERCARD = typeof import('./ZINTERCARD').default; +type ZINTERSTORE = typeof import('./ZINTERSTORE').default; +type ZLEXCOUNT = typeof import('./ZLEXCOUNT').default; +type ZMSCORE = typeof import('./ZMSCORE').default; +type ZRANDMEMBER_COUNT_WITHSCORES = typeof import('./ZRANDMEMBER_COUNT_WITHSCORES').default; +type ZRANDMEMBER_COUNT = typeof import('./ZRANDMEMBER_COUNT').default; +type ZRANDMEMBER = typeof import('./ZRANDMEMBER').default; +type ZRANGE = typeof import('./ZRANGE').default; +type ZRANGEBYLEX = typeof import('./ZRANGEBYLEX').default; +type ZRANGEBYSCORE_WITHSCORES = typeof import('./ZRANGEBYSCORE_WITHSCORES').default; +type ZRANGEBYSCORE = typeof import('./ZRANGEBYSCORE').default; +type ZREMRANGEBYSCORE = typeof import('./ZREMRANGEBYSCORE').default; +type ZRANK = typeof import('./ZRANK').default; +type ZREM = typeof import('./ZREM').default; +type ZREMRANGEBYLEX = typeof import('./ZREMRANGEBYLEX').default; +type ZREMRANGEBYRANK = typeof import('./ZREMRANGEBYRANK').default; +type ZREVRANK = typeof import('./ZREVRANK').default; +type ZSCAN = typeof import('./ZSCAN').default; +type ZSCORE = typeof import('./ZSCORE').default; +type ZUNION_WITHSCORES = typeof import('./ZUNION_WITHSCORES').default; +type ZUNION = typeof import('./ZUNION').default; +type ZUNIONSTORE = typeof import('./ZUNIONSTORE').default; + +type Commands = { + ACL_CAT: ACL_CAT; + aclCat: ACL_CAT; + ACL_DRYRUN: ACL_DRYRUN; + aclDryRun: ACL_DRYRUN; + ACL_GENPASS: ACL_GENPASS; + aclGenPass: ACL_GENPASS; + ACL_GETUSER: ACL_GETUSER; + aclGetUser: ACL_GETUSER; + ACL_LIST: ACL_LIST; + aclList: ACL_LIST; + ACL_LOAD: ACL_LOAD; + aclLoad: ACL_LOAD; + ACL_LOG_RESET: ACL_LOG_RESET; + aclLogReset: ACL_LOG_RESET; + ACL_LOG: ACL_LOG; + aclLog: ACL_LOG; + ACL_SAVE: ACL_SAVE; + aclSave: ACL_SAVE; + ACL_SETUSER: ACL_SETUSER; + aclSetUser: ACL_SETUSER; + ACL_USERS: ACL_USERS; + aclUsers: ACL_USERS; + ACL_WHOAMI: ACL_WHOAMI; + aclWhoAmI: ACL_WHOAMI; + APPEND: APPEND; + append: APPEND; + ASKING: ASKING; + asking: ASKING; + AUTH: AUTH; + auth: AUTH; + BGREWRITEAOF: BGREWRITEAOF; + bgRewriteAof: BGREWRITEAOF; + BGSAVE: BGSAVE; + bgSave: BGSAVE; + BITCOUNT: BITCOUNT; + bitCount: BITCOUNT; + BITFIELD_RO: BITFIELD_RO; + bitFieldRo: BITFIELD_RO; + BITFIELD: BITFIELD; + bitField: BITFIELD; + BITOP: BITOP; + bitOp: BITOP; + BITPOS: BITPOS; + bitPos: BITPOS; + BLMOVE: BLMOVE; + blMove: BLMOVE; + BLMPOP: BLMPOP; + blmPop: BLMPOP; + BLPOP: BLPOP; + blPop: BLPOP; + BRPOP: BRPOP; + brPop: BRPOP; + BRPOPLPUSH: BRPOPLPUSH; + brPopLPush: BRPOPLPUSH; + CLIENT_CACHING: CLIENT_CACHING; + clientCaching: CLIENT_CACHING; + CLIENT_GETNAME: CLIENT_GETNAME; + clientGetName: CLIENT_GETNAME; + CLIENT_GETREDIR: CLIENT_GETREDIR; + clientGetRedir: CLIENT_GETREDIR; + CLIENT_ID: CLIENT_ID; + clientId: CLIENT_ID; + CLIENT_INFO: CLIENT_INFO; + clientInfo: CLIENT_INFO; + CLIENT_KILL: CLIENT_KILL; + clientKill: CLIENT_KILL; + CLIENT_LIST: CLIENT_LIST; + clientList: CLIENT_LIST; + 'CLIENT_NO-EVICT': CLIENT_NO_EVICT; + clientNoEvict: CLIENT_NO_EVICT; + CLIENT_PAUSE: CLIENT_PAUSE; + clientPause: CLIENT_PAUSE; + CLIENT_SETNAME: CLIENT_SETNAME; + clientSetName: CLIENT_SETNAME; + CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS; + clusterAddSlots: CLUSTER_ADDSLOTS; + CLUSTER_SLOTS: CLUSTER_SLOTS; + clusterSlots: CLUSTER_SLOTS; + CLUSTER_MEET: CLUSTER_MEET; + clusterMeet: CLUSTER_MEET; + CLUSTER_MYID: CLUSTER_MYID; + clusterMyId: CLUSTER_MYID; + CLUSTER_REPLICATE: CLUSTER_REPLICATE; + clusterReplicate: CLUSTER_REPLICATE; + COPY: COPY; + copy: COPY; + DBSIZE: DBSIZE; + dbSize: DBSIZE; + DECR: DECR; + decr: DECR; + DECRBY: DECRBY; + decrBy: DECRBY; + DEL: DEL; + del: DEL; + DUMP: DUMP; + dump: DUMP; + ECHO: ECHO; + echo: ECHO; + EVAL_RO: EVAL_RO; + evalRo: EVAL_RO; + EVAL: EVAL; + eval: EVAL; + EVALSHA_RO: EVALSHA_RO; + evalShaRo: EVALSHA_RO; + EVALSHA: EVALSHA; + evalSha: EVALSHA; + EXISTS: EXISTS; + exists: EXISTS; + EXPIRE: EXPIRE; + expire: EXPIRE; + EXPIREAT: EXPIREAT; + expireAt: EXPIREAT; + EXPIRETIME: EXPIRETIME; + expireTime: EXPIRETIME; + FLUSHALL: FLUSHALL; + flushAll: FLUSHALL; + FLUSHDB: FLUSHDB; + flushDb: FLUSHDB; + FCALL: FCALL; + fCall: FCALL; + FCALL_RO: FCALL_RO; + fCallRo: FCALL_RO; + FUNCTION_DELETE: FUNCTION_DELETE; + functionDelete: FUNCTION_DELETE; + FUNCTION_DUMP: FUNCTION_DUMP; + functionDump: FUNCTION_DUMP; + FUNCTION_FLUSH: FUNCTION_FLUSH; + functionFlush: FUNCTION_FLUSH; + FUNCTION_KILL: FUNCTION_KILL; + functionKill: FUNCTION_KILL; + FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE; + functionListWithCode: FUNCTION_LIST_WITHCODE; + FUNCTION_LIST: FUNCTION_LIST; + functionList: FUNCTION_LIST; + FUNCTION_LOAD: FUNCTION_LOAD; + functionLoad: FUNCTION_LOAD; + // FUNCTION_RESTORE: FUNCTION_RESTORE; + // functionRestore: FUNCTION_RESTORE; + // FUNCTION_STATS: FUNCTION_STATS; + // functionStats: FUNCTION_STATS; + GEOADD: GEOADD; + geoAdd: GEOADD; + GEODIST: GEODIST; + geoDist: GEODIST; + GEOHASH: GEOHASH; + geoHash: GEOHASH; + GEOPOS: GEOPOS; + geoPos: GEOPOS; + GEORADIUS_RO_WITH: GEORADIUS_RO_WITH; + geoRadiusRoWith: GEORADIUS_RO_WITH; + GEORADIUS_RO: GEORADIUS_RO; + geoRadiusRo: GEORADIUS_RO + GEORADIUS_STORE: GEORADIUS_STORE; + geoRadiusStore: GEORADIUS_STORE; + GEORADIUS_WITH: GEORADIUS_WITH; + geoRadiusWith: GEORADIUS_WITH; + GEORADIUS: GEORADIUS; + geoRadius: GEORADIUS; + GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH; + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH; + GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO; + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO; + GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE; + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE; + GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH; + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH; + GEORADIUSBYMEMBER: GEORADIUSBYMEMBER; + geoRadiusByMember: GEORADIUSBYMEMBER; + GEOSEARCH_WITH: GEOSEARCH_WITH; + geoSearchWith: GEOSEARCH_WITH; + GEOSEARCH: GEOSEARCH; + geoSearch: GEOSEARCH; + GEOSEARCHSTORE: GEOSEARCHSTORE; + geoSearchStore: GEOSEARCHSTORE; + GET: GET; + get: GET; + GETBIT: GETBIT; + getBit: GETBIT; + GETDEL: GETDEL; + getDel: GETDEL; + GETEX: GETEX; + getEx: GETEX; + GETRANGE: GETRANGE; + getRange: GETRANGE; + GETSET: GETSET; + getSet: GETSET; + HDEL: HDEL; + hDel: HDEL; + HELLO: HELLO; + hello: HELLO; + HEXISTS: HEXISTS; + hExists: HEXISTS; + HGET: HGET; + hGet: HGET; + HGETALL: HGETALL; + hGetAll: HGETALL; + HINCRBY: HINCRBY; + hIncrBy: HINCRBY; + HINCRBYFLOAT: HINCRBYFLOAT; + hIncrByFloat: HINCRBYFLOAT; + HKEYS: HKEYS; + hKeys: HKEYS; + HLEN: HLEN; + hLen: HLEN; + HMGET: HMGET; + hmGet: HMGET; + HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES; + hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES; + HRANDFIELD_COUNT: HRANDFIELD_COUNT; + hRandFieldCount: HRANDFIELD_COUNT; + HRANDFIELD: HRANDFIELD; + hRandField: HRANDFIELD; + HSCAN: HSCAN; + hScan: HSCAN; + HSET: HSET; + hSet: HSET; + HSETNX: HSETNX; + hSetNX: HSETNX; + HSTRLEN: HSTRLEN; + hStrLen: HSTRLEN; + HVALS: HVALS; + hVals: HVALS; + INCR: INCR; + incr: INCR; + INCRBY: INCRBY; + incrBy: INCRBY; + INCRBYFLOAT: INCRBYFLOAT; + incrByFloat: INCRBYFLOAT; + INFO: INFO; + info: INFO; + KEYS: KEYS; + keys: KEYS; + LASTSAVE: LASTSAVE; + lastSave: LASTSAVE; + LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN; + lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN; + LCS_IDX: LCS_IDX; + lcsIdx: LCS_IDX; + LCS_LEN: LCS_LEN; + lcsLen: LCS_LEN; + LCS: LCS; + lcs: LCS; + LINDEX: LINDEX; + lIndex: LINDEX; + LINSERT: LINSERT; + lInsert: LINSERT; + LLEN: LLEN; + lLen: LLEN; + LMOVE: LMOVE; + lMove: LMOVE; + LMPOP: LMPOP; + lmPop: LMPOP; + LOLWUT: LOLWUT; + LPOP_COUNT: LPOP_COUNT; + lPopCount: LPOP_COUNT; + LPOP: LPOP; + lPop: LPOP; + LPOS_COUNT: LPOS_COUNT; + lPosCount: LPOS_COUNT; + LPOS: LPOS; + lPos: LPOS; + LPUSH: LPUSH; + lPush: LPUSH; + LPUSHX: LPUSHX; + lPushX: LPUSHX; + LRANGE: LRANGE; + lRange: LRANGE; + LREM: LREM; + lRem: LREM; + LSET: LSET; + lSet: LSET; + LTRIM: LTRIM; + lTrim: LTRIM; + MEMORY_DOCTOR: MEMORY_DOCTOR; + memoryDoctor: MEMORY_DOCTOR; + 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS; + memoryMallocStats: MEMORY_MALLOC_STATS; + MEMORY_PURGE: MEMORY_PURGE; + memoryPurge: MEMORY_PURGE; + // MEMORY_STATS: MEMORY_STATS; + // memoryStats: MEMORY_STATS; + MEMORY_USAGE: MEMORY_USAGE; + memoryUsage: MEMORY_USAGE; + MGET: MGET; + mGet: MGET; + MODULE_LIST: MODULE_LIST; + moduleList: MODULE_LIST; + MODULE_LOAD: MODULE_LOAD; + moduleLoad: MODULE_LOAD; + MODULE_UNLOAD: MODULE_UNLOAD; + moduleUnload: MODULE_UNLOAD; + MOVE: MOVE; + move: MOVE; + MSET: MSET; + mSet: MSET; + MSETNX: MSETNX; + mSetNX: MSETNX; + OBJECT_ENCODING: OBJECT_ENCODING; + objectEncoding: OBJECT_ENCODING; + OBJECT_FREQ: OBJECT_FREQ; + objectFreq: OBJECT_FREQ; + OBJECT_IDLETIME: OBJECT_IDLETIME; + objectIdleTime: OBJECT_IDLETIME; + OBJECT_REFCOUNT: OBJECT_REFCOUNT + objectRefCount: OBJECT_REFCOUNT; + PERSIST: PERSIST; + persist: PERSIST; + PEXPIRE: PEXPIRE; + pExpire: PEXPIRE; + PEXPIREAT: PEXPIREAT; + pExpireAt: PEXPIREAT; + PEXPIRETIME: PEXPIRETIME; + pExpireTime: PEXPIRETIME; + PFADD: PFADD; + pfAdd: PFADD; + PFCOUNT: PFCOUNT; + pfCount: PFCOUNT; + PFMERGE: PFMERGE; + pfMerge: PFMERGE; + PING: PING; + /** + * ping jsdoc + */ + ping: PING; + PSETEX: PSETEX; + pSetEx: PSETEX; + PTTL: PTTL; + pTTL: PTTL; + PUBLISH: PUBLISH; + publish: PUBLISH; + PUBSUB_CHANNELS: PUBSUB_CHANNELS; + pubSubChannels: PUBSUB_CHANNELS; + PUBSUB_NUMPAT: PUBSUB_NUMPAT; + pubSubNumPat: PUBSUB_NUMPAT; + PUBSUB_NUMSUB: PUBSUB_NUMSUB; + pubSubNumSub: PUBSUB_NUMSUB; + PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS; + pubSubShardChannels: PUBSUB_SHARDCHANNELS; + RANDOMKEY: RANDOMKEY; + randomKey: RANDOMKEY; + READONLY: READONLY; + readonly: READONLY; + RENAME: RENAME; + rename: RENAME; + RENAMENX: RENAMENX; + renameNX: RENAMENX; + RPOP_COUNT: RPOP_COUNT; + rPopCount: RPOP_COUNT; + RPOP: RPOP; + rPop: RPOP; + RPOPLPUSH: RPOPLPUSH; + rPopLPush: RPOPLPUSH; + RPUSH: RPUSH; + rPush: RPUSH; + RPUSHX: RPUSHX; + rPushX: RPUSHX; + SADD: SADD; + sAdd: SADD; + SCAN: SCAN; + scan: SCAN; + SCARD: SCARD; + sCard: SCARD; + SCRIPT_DEBUG: SCRIPT_DEBUG; + scriptDebug: SCRIPT_DEBUG; + SCRIPT_EXISTS: SCRIPT_EXISTS; + scriptExists: SCRIPT_EXISTS; + SCRIPT_FLUSH: SCRIPT_FLUSH; + scriptFlush: SCRIPT_FLUSH; + SCRIPT_KILL: SCRIPT_KILL; + scriptKill: SCRIPT_KILL; + SCRIPT_LOAD: SCRIPT_LOAD; + scriptLoad: SCRIPT_LOAD; + SDIFF: SDIFF; + sDiff: SDIFF; + SDIFFSTORE: SDIFFSTORE; + sDiffStore: SDIFFSTORE; + SET: SET; + set: SET; + SETBIT: SETBIT; + setBit: SETBIT; + SETEX: SETEX; + setEx: SETEX; + SETNX: SETNX; + setNX: SETNX; + SETRANGE: SETRANGE; + setRange: SETRANGE; + SINTER: SINTER; + sInter: SINTER; + SINTERCARD: SINTERCARD; + sInterCard: SINTERCARD; + SINTERSTORE: SINTERSTORE; + sInterStore: SINTERSTORE; + SISMEMBER: SISMEMBER; + sIsMember: SISMEMBER; + SMEMBERS: SMEMBERS; + sMembers: SMEMBERS; + SMISMEMBER: SMISMEMBER; + smIsMember: SMISMEMBER; + SMOVE: SMOVE; + sMove: SMOVE; + SORT_RO: SORT_RO; + sortRo: SORT_RO; + SORT_STORE: SORT_STORE; + sortStore: SORT_STORE; + SORT: SORT; + sort: SORT; + SPOP_COUNT: SPOP_COUNT; + sPopCount: SPOP_COUNT; + SPOP: SPOP; + sPop: SPOP; + SPUBLISH: SPUBLISH; + sPublish: SPUBLISH; + SRANDMEMBER_COUNT: SRANDMEMBER_COUNT; + sRandMemberCount: SRANDMEMBER_COUNT; + SRANDMEMBER: SRANDMEMBER; + sRandMember: SRANDMEMBER; + SREM: SREM; + sRem: SREM; + SSCAN: SSCAN; + sScan: SSCAN; + STRLEN: STRLEN; + strLen: STRLEN; + SUNION: SUNION; + sUnion: SUNION; + SUNIONSTORE: SUNIONSTORE; + sUnionStore: SUNIONSTORE; + TOUCH: TOUCH; + touch: TOUCH; + TTL: TTL; + ttl: TTL; + TYPE: TYPE; + type: TYPE; + UNLINK: UNLINK; + unlink: UNLINK; + UNWATCH: UNWATCH; + unwatch: UNWATCH; + WAIT: WAIT; + wait: WAIT; + WATCH: WATCH; + watch: WATCH; + XACK: XACK; + xAck: XACK; + XADD_NOMKSTREAM: XADD_NOMKSTREAM; + xAddNoMkStream: XADD_NOMKSTREAM; + XADD: XADD; + xAdd: XADD; + XDEL: XDEL; + xDel: XDEL; + XSETID: XSETID; + xSetId: XSETID; + XTRIM: XTRIM; + xTrim: XTRIM; + XLEN: XLEN; + xLen: XLEN; + ZADD_INCR: ZADD_INCR; + zAddIncr: ZADD_INCR; + ZADD: ZADD; + zAdd: ZADD; + ZCARD: ZCARD; + zCard: ZCARD; + ZCOUNT: ZCOUNT; + zCount: ZCOUNT; + ZDIFF_WITHSCORES: ZDIFF_WITHSCORES; + zDiffWithScores: ZDIFF_WITHSCORES; + ZDIFF: ZDIFF; + zDiff: ZDIFF; + ZDIFFSTORE: ZDIFFSTORE; + zDiffStore: ZDIFFSTORE; + ZINCRBY: ZINCRBY; + zIncrBy: ZINCRBY; + ZINTER_WITHSCORES: ZINTER_WITHSCORES; + zInterWithScores: ZINTER_WITHSCORES; + ZINTER: ZINTER; + zInter: ZINTER; + ZINTERCARD: ZINTERCARD; + zInterCard: ZINTERCARD; + ZINTERSTORE: ZINTERSTORE; + zInterStore: ZINTERSTORE; + ZLEXCOUNT: ZLEXCOUNT; + zLexCount: ZLEXCOUNT; + ZMSCORE: ZMSCORE; + zmScore: ZMSCORE; + ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES; + zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES; + ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT; + zRandMemberCount: ZRANDMEMBER_COUNT; + ZRANDMEMBER: ZRANDMEMBER; + zRandMember: ZRANDMEMBER; + ZRANGE: ZRANGE; + zRange: ZRANGE; + ZRANGEBYLEX: ZRANGEBYLEX; + zRangeByLex: ZRANGEBYLEX; + ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES; + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES; + ZRANGEBYSCORE: ZRANGEBYSCORE; + zRangeByScore: ZRANGEBYSCORE; + ZRANK: ZRANK; + zRank: ZRANK; + ZREM: ZREM; + zRem: ZREM; + ZREMRANGEBYLEX: ZREMRANGEBYLEX; + zRemRangeByLex: ZREMRANGEBYLEX; + ZREMRANGEBYRANK: ZREMRANGEBYRANK; + zRemRangeByRank: ZREMRANGEBYRANK; + ZREMRANGEBYSCORE: ZREMRANGEBYSCORE; + zRemRangeByScore: ZREMRANGEBYSCORE; + ZREVRANK: ZREVRANK; + zRevRank: ZREVRANK; + ZSCAN: ZSCAN; + zScan: ZSCAN; + ZSCORE: ZSCORE; + zScore: ZSCORE; + ZUNION_WITHSCORES: ZUNION_WITHSCORES; + zUnionWithScores: ZUNION_WITHSCORES; + ZUNION: ZUNION; + zUnion: ZUNION; + ZUNIONSTORE: ZUNIONSTORE; + zUnionStore: ZUNIONSTORE; +}; + export default { ACL_CAT, aclCat: ACL_CAT, @@ -333,6 +1125,8 @@ export default { clusterReplicate: CLUSTER_REPLICATE, COPY, copy: COPY, + DBSIZE, + dbSize: DBSIZE, DECR, decr: DECR, DECRBY, @@ -363,6 +1157,28 @@ export default { flushAll: FLUSHALL, FLUSHDB, flushDb: FLUSHDB, + FCALL, + fCall: FCALL, + FCALL_RO, + fCallRo: FCALL_RO, + FUNCTION_DELETE, + functionDelete: FUNCTION_DELETE, + FUNCTION_DUMP, + functionDump: FUNCTION_DUMP, + FUNCTION_FLUSH, + functionFlush: FUNCTION_FLUSH, + FUNCTION_KILL, + functionKill: FUNCTION_KILL, + FUNCTION_LIST_WITHCODE, + functionListWithCode: FUNCTION_LIST_WITHCODE, + FUNCTION_LIST, + functionList: FUNCTION_LIST, + FUNCTION_LOAD, + functionLoad: FUNCTION_LOAD, + // FUNCTION_RESTORE, + // functionRestore: FUNCTION_RESTORE, + // FUNCTION_STATS, + // functionStats: FUNCTION_STATS, GEOADD, geoAdd: GEOADD, GEODIST, @@ -740,5 +1556,5 @@ export default { ZUNION, zUnion: ZUNION, ZUNIONSTORE, - zUnionStore: ZUNIONSTORE, -} as const satisfies Record; + zUnionStore: ZUNIONSTORE +} as const satisfies Record as Commands; diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index a6abde44953..917bd2992ef 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -1,6 +1,6 @@ import { createConnection } from 'net'; import { once } from 'events'; -import { createClient } from '@redis/client'; +import { createClient } from '@redis/client/index'; import { setTimeout } from 'timers/promises'; // import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; import * as path from 'path'; diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 009f94a43e0..f424535297b 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -9,7 +9,7 @@ import { createCluster, RedisClusterOptions, RedisClusterType -} from '@redis/client'; +} from '@redis/client/index'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; From 03059f785c18fdc6db882de72154003115b0428f Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:13:05 -0400 Subject: [PATCH 129/325] wip --- package-lock.json | 1413 +++++++++++++++------------------------------ 1 file changed, 458 insertions(+), 955 deletions(-) diff --git a/package-lock.json b/package-lock.json index 064e8729c27..1be40d48bab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -38,9 +37,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -50,18 +48,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", @@ -89,18 +85,16 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", @@ -113,9 +107,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.0", "@babel/helper-validator-option": "^7.21.0", @@ -132,27 +125,24 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.20.7", "@babel/types": "^7.21.0" @@ -163,9 +153,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -175,9 +164,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.21.4" }, @@ -187,9 +175,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-module-imports": "^7.21.4", @@ -206,9 +193,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.21.5" }, @@ -218,9 +204,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.18.6" }, @@ -230,36 +215,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.21.9", "@babel/traverse": "^7.22.1", @@ -271,9 +252,8 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -285,9 +265,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -297,9 +276,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -311,42 +289,37 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -356,9 +329,8 @@ }, "node_modules/@babel/parser": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz", - "integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -368,9 +340,8 @@ }, "node_modules/@babel/template": { "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", "@babel/parser": "^7.21.9", @@ -382,9 +353,8 @@ }, "node_modules/@babel/traverse": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz", - "integrity": "sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", "@babel/generator": "^7.22.3", @@ -403,18 +373,16 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.4.tgz", - "integrity": "sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", @@ -426,9 +394,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -438,9 +405,8 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -448,33 +414,8 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -487,27 +428,21 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.5.2", - "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -524,9 +459,8 @@ }, "node_modules/@eslint/js": { "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -534,9 +468,8 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -549,9 +482,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "peer": true, "engines": { "node": ">=12.22" @@ -563,16 +495,14 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true, + "license": "BSD-3-Clause", "peer": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -586,18 +516,16 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -608,9 +536,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -621,9 +548,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -633,9 +559,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -648,9 +573,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -660,18 +584,16 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", - "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2" }, @@ -684,18 +606,16 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -707,33 +627,29 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -741,15 +657,13 @@ }, "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -760,18 +674,16 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -810,33 +722,24 @@ }, "node_modules/@sinonjs/commons": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "lodash.get": "^4.4.2", @@ -845,112 +748,88 @@ }, "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true + "dev": true, + "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mocha": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@types/semver": { "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/sinon": { "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", - "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", - "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", - "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.59.9", @@ -982,9 +861,8 @@ }, "node_modules/@typescript-eslint/parser": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "5.59.9", "@typescript-eslint/types": "5.59.9", @@ -1009,9 +887,8 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.9", "@typescript-eslint/visitor-keys": "5.59.9" @@ -1026,9 +903,8 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "5.59.9", "@typescript-eslint/utils": "5.59.9", @@ -1053,9 +929,8 @@ }, "node_modules/@typescript-eslint/types": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1066,9 +941,8 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.59.9", "@typescript-eslint/visitor-keys": "5.59.9", @@ -1093,11 +967,9 @@ }, "node_modules/@typescript-eslint/utils": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", @@ -1120,9 +992,8 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.9", "eslint-visitor-keys": "^3.3.0" @@ -1137,9 +1008,8 @@ }, "node_modules/acorn": { "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1149,9 +1019,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -1159,18 +1028,16 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1181,9 +1048,8 @@ }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -1198,33 +1064,29 @@ }, "node_modules/ansi-colors": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "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==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-sequence-parser": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", - "dev": true + "dev": true, + "license": "MIT" }, "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==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1237,9 +1099,8 @@ }, "node_modules/anymatch": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1250,9 +1111,8 @@ }, "node_modules/append-transform": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, + "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -1262,66 +1122,57 @@ }, "node_modules/archy": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/async": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1329,9 +1180,8 @@ }, "node_modules/braces": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1341,14 +1191,11 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserslist": { "version": "4.21.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.7.tgz", - "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", "dev": true, "funding": [ { @@ -1364,6 +1211,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001489", "electron-to-chromium": "^1.4.411", @@ -1379,15 +1227,13 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/caching-transform": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, + "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1400,9 +1246,8 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -1410,17 +1255,14 @@ }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { "version": "1.0.30001495", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz", - "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==", "dev": true, "funding": [ { @@ -1435,13 +1277,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1455,8 +1297,6 @@ }, "node_modules/chokidar": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -1464,6 +1304,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1482,9 +1323,8 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1494,18 +1334,16 @@ }, "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cliui": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -1514,17 +1352,15 @@ }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1534,45 +1370,38 @@ }, "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commondir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1584,9 +1413,8 @@ }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -1601,25 +1429,22 @@ }, "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/default-require-extensions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, + "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -1632,18 +1457,16 @@ }, "node_modules/diff": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1653,9 +1476,8 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "esutils": "^2.0.2" @@ -1666,42 +1488,36 @@ }, "node_modules/electron-to-chromium": { "version": "1.4.423", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.423.tgz", - "integrity": "sha512-y4A7YfQcDGPAeSWM1IuoWzXpg9RY1nwHzHSwRtCSQFp9FgAVDgdWlFf0RbdWfLWQ2WUI+bddUgk5RgTjqRE6FQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/email-addresses": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", - "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", - "dev": true + "dev": true, + "license": "MIT" }, "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/es6-error": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1711,9 +1527,8 @@ }, "node_modules/eslint": { "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -1733,10 +1548,6 @@ "eslint-visitor-keys": "^3.4.1", "espree": "^9.5.2", "esquery": "^1.4.2", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -1744,7 +1555,6 @@ "glob-parent": "^6.0.2", "globals": "^13.19.0", "graphemer": "^1.4.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -1773,9 +1583,8 @@ }, "node_modules/eslint-scope": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -1786,9 +1595,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1798,12 +1606,8 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1812,18 +1616,14 @@ "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" - }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1831,18 +1631,13 @@ }, "node_modules/espree": { "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" - "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1853,9 +1648,8 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -1866,9 +1660,8 @@ }, "node_modules/esquery": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "peer": true, "dependencies": { "estraverse": "^5.1.0" @@ -1879,9 +1672,8 @@ }, "node_modules/esquery/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1889,9 +1681,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1901,27 +1692,24 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -1929,16 +1717,14 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fast-glob": { "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1952,9 +1738,8 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1964,32 +1749,28 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fastq": { "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "flat-cache": "^3.0.4" @@ -2000,18 +1781,16 @@ }, "node_modules/filename-reserved-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/filenamify": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, + "license": "MIT", "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -2026,9 +1805,8 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2038,9 +1816,8 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -2055,9 +1832,8 @@ }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2071,18 +1847,16 @@ }, "node_modules/flat": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "flatted": "^3.1.0", @@ -2094,16 +1868,14 @@ }, "node_modules/flatted": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/foreground-child": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -2114,8 +1886,6 @@ }, "node_modules/fromentries": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { @@ -2130,13 +1900,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/fs-extra": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -2148,64 +1918,44 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "dev": true, + "license": "ISC" }, "node_modules/generic-pool": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/gh-pages": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", - "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", "dev": true, + "license": "MIT", "dependencies": { "async": "^3.2.4", "commander": "^2.18.0", @@ -2225,9 +1975,8 @@ }, "node_modules/gh-pages/node_modules/array-union": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, + "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -2237,9 +1986,8 @@ }, "node_modules/gh-pages/node_modules/globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -2253,9 +2001,8 @@ }, "node_modules/glob": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2273,9 +2020,8 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -2286,9 +2032,8 @@ }, "node_modules/globals": { "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "type-fest": "^0.20.2" @@ -2302,9 +2047,8 @@ }, "node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -2322,37 +2066,32 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/grapheme-splitter": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/hasha": { "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, + "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -2366,42 +2105,37 @@ }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/html-escaper": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ignore": { "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "parent-module": "^1.0.0", @@ -2416,27 +2150,24 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2444,15 +2175,13 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/is-binary-path": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2462,27 +2191,24 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2492,18 +2218,16 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-inside": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -2511,18 +2235,16 @@ }, "node_modules/is-plain-obj": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2532,15 +2254,13 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2550,55 +2270,34 @@ }, "node_modules/is-windows": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/isarray": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/issue-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", - "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", "dev": true, - "dependencies": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - }, - "engines": { - "node": ">=10.13" - } + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -2608,9 +2307,8 @@ }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -2623,18 +2321,16 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, + "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -2649,9 +2345,8 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -2663,9 +2358,8 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -2677,9 +2371,8 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -2690,15 +2383,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2708,9 +2399,8 @@ }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -2720,23 +2410,20 @@ }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -2746,30 +2433,26 @@ }, "node_modules/jsonc-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/just-extend": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -2781,9 +2464,8 @@ }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2796,40 +2478,24 @@ }, "node_modules/lodash.flattendeep": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.get": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/log-symbols": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -2843,24 +2509,21 @@ }, "node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/lunr": { "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -2873,27 +2536,21 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/marked": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -2903,18 +2560,16 @@ }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -2925,9 +2580,8 @@ }, "node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2937,9 +2591,8 @@ }, "node_modules/mocha": { "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -2977,18 +2630,16 @@ }, "node_modules/mocha/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2998,15 +2649,13 @@ }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3019,15 +2668,13 @@ }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3037,22 +2684,19 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nise": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "@sinonjs/fake-timers": "^10.0.2", @@ -3063,18 +2707,16 @@ }, "node_modules/nise/node_modules/@sinonjs/commons": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/node-preload": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, + "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -3084,24 +2726,21 @@ }, "node_modules/node-releases": { "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/nyc": { "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -3140,9 +2779,8 @@ }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -3151,9 +2789,8 @@ }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3164,9 +2801,8 @@ }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -3176,9 +2812,8 @@ }, "node_modules/nyc/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -3191,9 +2826,8 @@ }, "node_modules/nyc/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -3203,18 +2837,16 @@ }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3226,15 +2858,13 @@ }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -3254,9 +2884,8 @@ }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -3267,27 +2896,24 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/optionator": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "deep-is": "^0.1.3", @@ -3303,9 +2929,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3318,9 +2943,8 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -3333,9 +2957,8 @@ }, "node_modules/p-map": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -3345,18 +2968,16 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/package-hash": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, + "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -3369,9 +2990,8 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "callsites": "^3.0.0" @@ -3382,60 +3002,53 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-to-regexp": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, + "license": "MIT", "dependencies": { "isarray": "0.0.1" } }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3445,27 +3058,24 @@ }, "node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, + "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -3475,9 +3085,8 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -3487,9 +3096,8 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3500,9 +3108,8 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -3512,9 +3119,8 @@ }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -3527,9 +3133,8 @@ }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -3539,9 +3144,8 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8.0" @@ -3549,9 +3153,8 @@ }, "node_modules/process-on-spawn": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, + "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -3561,9 +3164,8 @@ }, "node_modules/punycode": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -3571,8 +3173,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -3587,22 +3187,21 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -3616,9 +3215,8 @@ }, "node_modules/release-zalgo": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, + "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -3628,24 +3226,21 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -3653,9 +3248,8 @@ }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -3663,9 +3257,8 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -3678,8 +3271,6 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -3695,14 +3286,13 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -3717,13 +3307,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/semver": { "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3736,9 +3326,8 @@ }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3748,30 +3337,26 @@ }, "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serialize-javascript": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3781,18 +3366,16 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shiki": { "version": "0.14.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", - "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -3802,24 +3385,14 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sinon": { "version": "15.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz", - "integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==", - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz", - "integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.2.0", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.4", "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^10.2.0", "@sinonjs/samsam": "^8.0.0", @@ -3834,36 +3407,32 @@ }, "node_modules/sinon/node_modules/diff": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3871,9 +3440,8 @@ }, "node_modules/spawn-wrap": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -3888,15 +3456,13 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "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==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3908,9 +3474,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==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3920,18 +3485,16 @@ }, "node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3941,9 +3504,8 @@ }, "node_modules/strip-outer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -3953,18 +3515,16 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3974,9 +3534,8 @@ }, "node_modules/test-exclude": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -3988,25 +3547,22 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4016,9 +3572,8 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -4028,18 +3583,16 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -4080,24 +3633,21 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -4110,9 +3660,8 @@ }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -4123,25 +3672,19 @@ }, "node_modules/type-detect": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "peer": true, "engines": { "node": ">=10" - "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4149,24 +3692,20 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, + "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", "minimatch": "^9.0.0", - "marked": "^4.3.0", - "minimatch": "^9.0.0", "shiki": "^0.14.1" }, "bin": { @@ -4181,27 +3720,21 @@ }, "node_modules/typedoc/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" - "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4209,9 +3742,8 @@ }, "node_modules/typescript": { "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4222,17 +3754,14 @@ }, "node_modules/universalify": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/update-browserslist-db": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -4248,6 +3777,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -4261,9 +3791,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "punycode": "^2.1.0" @@ -4271,36 +3800,31 @@ }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vscode-oniguruma": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vscode-textmate": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4313,15 +3837,13 @@ }, "node_modules/which-module": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/word-wrap": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -4329,15 +3851,13 @@ }, "node_modules/workerpool": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4352,15 +3872,13 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -4370,24 +3888,21 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -4403,18 +3918,16 @@ }, "node_modules/yargs-parser": { "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -4427,9 +3940,8 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4439,9 +3951,8 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4451,18 +3962,16 @@ }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4471,6 +3980,7 @@ } }, "packages/bloom": { + "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { @@ -4481,6 +3991,7 @@ } }, "packages/client": { + "name": "@redis/client", "version": "2.0.0-next.1", "license": "MIT", "dependencies": { @@ -4497,6 +4008,7 @@ } }, "packages/graph": { + "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { @@ -4507,6 +4019,7 @@ } }, "packages/json": { + "name": "@redis/json", "version": "1.0.4", "license": "MIT", "devDependencies": { @@ -4530,8 +4043,7 @@ }, "packages/redis/node_modules/@redis/client": { "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz", - "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==", + "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -4541,13 +4053,21 @@ "node": ">=14" } }, + "packages/redis/node_modules/@redis/search": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz", + "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, "packages/redis/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "packages/search": { - "version": "1.1.2", + "name": "@redis/search", + "version": "1.1.3", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -4557,6 +4077,7 @@ } }, "packages/test-utils": { + "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.24", "yargs": "^17.7.2" @@ -4567,9 +4088,8 @@ }, "packages/test-utils/node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4581,12 +4101,8 @@ }, "packages/test-utils/node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -4602,14 +4118,14 @@ }, "packages/test-utils/node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "packages/time-series": { + "name": "@redis/time-series", "version": "1.0.4", "license": "MIT", "devDependencies": { @@ -4618,19 +4134,6 @@ "peerDependencies": { "@redis/client": "*" } - }, - "packages/time-series/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } } } } From b0126c179a203408c7008f054d0400ed4348d4a5 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:13:45 -0400 Subject: [PATCH 130/325] npm update --- package-lock.json | 1491 ++++++++++++++++++++++++++++----------------- 1 file changed, 936 insertions(+), 555 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1be40d48bab..5aa0f84c9d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,8 +25,9 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -36,39 +37,42 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.3", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", + "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.1", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", "dev": true, - "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-compilation-targets": "^7.22.1", - "@babel/helper-module-transforms": "^7.22.1", - "@babel/helpers": "^7.22.0", - "@babel/parser": "^7.22.0", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -85,18 +89,20 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.22.3", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", + "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.22.3", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -106,12 +112,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.1", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", + "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.0", - "@babel/helper-validator-option": "^7.21.0", + "@babel/compat-data": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -125,137 +132,150 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.1", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.1", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", + "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", + "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.3", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", + "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.3" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -265,8 +285,9 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -276,8 +297,9 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -289,37 +311,42 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -328,9 +355,10 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.4", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", + "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -339,31 +367,33 @@ } }, "node_modules/@babel/template": { - "version": "7.21.9", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.3", - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.22.4", - "@babel/types": "^7.22.4", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", + "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -373,19 +403,21 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.22.4", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -394,8 +426,9 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -405,8 +438,9 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -414,8 +448,9 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -428,16 +463,18 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "ajv": "^6.12.4", @@ -458,9 +495,10 @@ } }, "node_modules/@eslint/js": { - "version": "8.42.0", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", + "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -468,8 +506,9 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -482,8 +521,9 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "peer": true, "engines": { "node": ">=12.22" @@ -495,14 +535,16 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true, - "license": "BSD-3-Clause", "peer": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -516,16 +558,18 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -536,8 +580,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -548,8 +593,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -559,8 +605,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -573,8 +620,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -584,16 +632,18 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", + "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2" }, @@ -606,16 +656,18 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -627,29 +679,33 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -657,13 +713,15 @@ }, "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -674,16 +732,18 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -722,24 +782,27 @@ }, "node_modules/@sinonjs/commons": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.2.0", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.1.0.tgz", + "integrity": "sha512-w1qd368vtrwttm1PRJWPW1QHlbmHrVDGs1eBH/jZvRPUFS4MNXV9Q33EQdjOdeAxZ7O8+3wM7zxztm2nfUSyKw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "lodash.get": "^4.4.2", @@ -748,93 +811,108 @@ }, "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.12", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true }, "node_modules/@types/mocha": { "version": "10.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true }, "node_modules/@types/node": { - "version": "20.2.5", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/@types/semver": { "version": "7.5.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true }, "node_modules/@types/sinon": { "version": "10.0.15", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", + "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "dev": true }, "node_modules/@types/yargs": { "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, - "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", + "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/type-utils": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -860,13 +938,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", + "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "debug": "^4.3.4" }, "engines": { @@ -886,12 +965,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", + "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -902,12 +982,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", + "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/utils": "5.60.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -928,9 +1009,10 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", + "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -940,12 +1022,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", + "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/visitor-keys": "5.60.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -966,16 +1049,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", + "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.0", + "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -991,11 +1075,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.9", + "version": "5.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", + "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/types": "5.60.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1007,9 +1092,10 @@ } }, "node_modules/acorn": { - "version": "8.8.2", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1019,8 +1105,9 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -1028,16 +1115,18 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, - "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1048,8 +1137,9 @@ }, "node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -1064,29 +1154,33 @@ }, "node_modules/ansi-colors": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-sequence-parser": { "version": "1.1.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "dev": true }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1099,8 +1193,9 @@ }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1111,8 +1206,9 @@ }, "node_modules/append-transform": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, - "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -1122,57 +1218,66 @@ }, "node_modules/archy": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true }, "node_modules/arg": { "version": "4.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/array-uniq": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/async": { "version": "3.2.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true }, "node_modules/balanced-match": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1180,8 +1285,9 @@ }, "node_modules/braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1191,11 +1297,14 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, "node_modules/browserslist": { - "version": "4.21.7", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "dev": true, "funding": [ { @@ -1211,10 +1320,9 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001489", - "electron-to-chromium": "^1.4.411", + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", "node-releases": "^2.0.12", "update-browserslist-db": "^1.0.11" }, @@ -1227,13 +1335,15 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/caching-transform": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, - "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1246,8 +1356,9 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -1255,14 +1366,17 @@ }, "node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001495", + "version": "1.0.30001504", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001504.tgz", + "integrity": "sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==", "dev": true, "funding": [ { @@ -1277,13 +1391,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1297,6 +1411,8 @@ }, "node_modules/chokidar": { "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -1304,7 +1420,6 @@ "url": "https://paulmillr.com/funding/" } ], - "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1323,8 +1438,9 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1334,16 +1450,18 @@ }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -1352,15 +1470,17 @@ }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1370,38 +1490,45 @@ }, "node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/commander": { "version": "2.20.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/commondir": { "version": "1.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/convert-source-map": { "version": "1.9.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/create-require": { "version": "1.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1413,8 +1540,9 @@ }, "node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -1429,22 +1557,25 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/default-require-extensions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, - "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -1457,16 +1588,18 @@ }, "node_modules/diff": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/dir-glob": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1476,8 +1609,9 @@ }, "node_modules/doctrine": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { "esutils": "^2.0.2" @@ -1487,37 +1621,43 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.423", - "dev": true, - "license": "ISC" + "version": "1.4.434", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.434.tgz", + "integrity": "sha512-5Gvm09UZTQRaWrimRtWRO5rvaX6Kpk5WHAPKDa7A4Gj6NIPuJ8w8WNpnxCXdd+CJJt6RBU6tUw0KyULoW6XuHw==", + "dev": true }, "node_modules/email-addresses": { "version": "5.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/es6-error": { "version": "4.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true }, "node_modules/escalade": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -1526,15 +1666,16 @@ } }, "node_modules/eslint": { - "version": "8.42.0", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", + "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", + "@eslint/js": "8.43.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1583,8 +1724,9 @@ }, "node_modules/eslint-scope": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -1595,8 +1737,9 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1606,8 +1749,9 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1622,8 +1766,9 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1631,8 +1776,9 @@ }, "node_modules/espree": { "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "acorn": "^8.8.0", @@ -1648,8 +1794,9 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -1660,8 +1807,9 @@ }, "node_modules/esquery": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "license": "BSD-3-Clause", "peer": true, "dependencies": { "estraverse": "^5.1.0" @@ -1672,8 +1820,9 @@ }, "node_modules/esquery/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1681,8 +1830,9 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1692,24 +1842,27 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -1717,14 +1870,16 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fast-glob": { "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1738,8 +1893,9 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1749,28 +1905,32 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fastq": { "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "flat-cache": "^3.0.4" @@ -1781,16 +1941,18 @@ }, "node_modules/filename-reserved-regex": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/filenamify": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, - "license": "MIT", "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -1805,8 +1967,9 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1816,8 +1979,9 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, - "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -1832,8 +1996,9 @@ }, "node_modules/find-up": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -1847,16 +2012,18 @@ }, "node_modules/flat": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "flatted": "^3.1.0", @@ -1868,14 +2035,16 @@ }, "node_modules/flatted": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true, - "license": "ISC", "peer": true }, "node_modules/foreground-child": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, - "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -1886,6 +2055,8 @@ }, "node_modules/fromentries": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { @@ -1900,13 +2071,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -1918,44 +2089,64 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/generic-pool": { "version": "3.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-package-type": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/gh-pages": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", + "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", "dev": true, - "license": "MIT", "dependencies": { "async": "^3.2.4", "commander": "^2.18.0", @@ -1975,8 +2166,9 @@ }, "node_modules/gh-pages/node_modules/array-union": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, - "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -1986,8 +2178,9 @@ }, "node_modules/gh-pages/node_modules/globby": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, - "license": "MIT", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -2001,8 +2194,9 @@ }, "node_modules/glob": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2020,8 +2214,9 @@ }, "node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -2032,8 +2227,9 @@ }, "node_modules/globals": { "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "type-fest": "^0.20.2" @@ -2047,8 +2243,9 @@ }, "node_modules/globby": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -2066,32 +2263,37 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/grapheme-splitter": { "version": "1.0.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/hasha": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, - "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -2105,37 +2307,42 @@ }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/html-escaper": { "version": "2.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "node_modules/ignore": { "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "parent-module": "^1.0.0", @@ -2150,24 +2357,27 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, - "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2175,13 +2385,15 @@ }, "node_modules/inherits": { "version": "2.0.4", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2191,24 +2403,27 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2218,16 +2433,18 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -2235,16 +2452,18 @@ }, "node_modules/is-plain-obj": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-stream": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -2254,13 +2473,15 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2270,34 +2491,39 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/isarray": { "version": "0.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -2307,8 +2533,9 @@ }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -2321,16 +2548,18 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, - "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -2345,8 +2574,9 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -2358,8 +2588,9 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -2371,8 +2602,9 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -2383,13 +2615,15 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2399,8 +2633,9 @@ }, "node_modules/jsesc": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -2410,20 +2645,23 @@ }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -2433,26 +2671,30 @@ }, "node_modules/jsonc-parser": { "version": "3.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true }, "node_modules/jsonfile": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/just-extend": { "version": "4.2.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -2464,8 +2706,9 @@ }, "node_modules/locate-path": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2478,24 +2721,28 @@ }, "node_modules/lodash.flattendeep": { "version": "4.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/log-symbols": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -2509,21 +2756,24 @@ }, "node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/lunr": { "version": "2.3.9", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -2536,21 +2786,24 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/make-error": { "version": "1.3.6", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "node_modules/marked": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, - "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -2560,16 +2813,18 @@ }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -2580,8 +2835,9 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2591,8 +2847,9 @@ }, "node_modules/mocha": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -2630,16 +2887,18 @@ }, "node_modules/mocha/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2649,13 +2908,15 @@ }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2668,13 +2929,15 @@ }, "node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/nanoid": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -2684,19 +2947,22 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true }, "node_modules/nise": { "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "@sinonjs/fake-timers": "^10.0.2", @@ -2707,16 +2973,18 @@ }, "node_modules/nise/node_modules/@sinonjs/commons": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/node-preload": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, - "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -2726,21 +2994,24 @@ }, "node_modules/node-releases": { "version": "2.0.12", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/nyc": { "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -2779,8 +3050,9 @@ }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -2789,8 +3061,9 @@ }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -2801,8 +3074,9 @@ }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -2812,8 +3086,9 @@ }, "node_modules/nyc/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -2826,8 +3101,9 @@ }, "node_modules/nyc/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -2837,16 +3113,18 @@ }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2858,13 +3136,15 @@ }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -2884,8 +3164,9 @@ }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -2896,24 +3177,27 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/optionator": { "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "deep-is": "^0.1.3", @@ -2929,8 +3213,9 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2943,8 +3228,9 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -2957,8 +3243,9 @@ }, "node_modules/p-map": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, - "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -2968,16 +3255,18 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/package-hash": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, - "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -2990,8 +3279,9 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "callsites": "^3.0.0" @@ -3002,53 +3292,60 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-to-regexp": { "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, - "license": "MIT", "dependencies": { "isarray": "0.0.1" } }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3058,24 +3355,27 @@ }, "node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, - "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -3085,8 +3385,9 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -3096,8 +3397,9 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3108,8 +3410,9 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -3119,8 +3422,9 @@ }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -3133,8 +3437,9 @@ }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -3144,8 +3449,9 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">= 0.8.0" @@ -3153,8 +3459,9 @@ }, "node_modules/process-on-spawn": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, - "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -3164,8 +3471,9 @@ }, "node_modules/punycode": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -3173,6 +3481,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -3187,21 +3497,22 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -3215,8 +3526,9 @@ }, "node_modules/release-zalgo": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, - "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -3226,21 +3538,24 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -3248,8 +3563,9 @@ }, "node_modules/reusify": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -3257,8 +3573,9 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, - "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -3271,6 +3588,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -3286,13 +3605,14 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -3307,13 +3627,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/semver": { - "version": "7.5.1", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3326,8 +3646,9 @@ }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3337,26 +3658,30 @@ }, "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/serialize-javascript": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3366,16 +3691,18 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shiki": { "version": "0.14.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", + "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -3385,16 +3712,18 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/sinon": { - "version": "15.1.0", + "version": "15.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.2.tgz", + "integrity": "sha512-uG1pU54Fis4EfYOPoEi13fmRHgZNg/u+3aReSEzHsN52Bpf+bMVfsBQS5MjouI+rTuG6UBIINlpuuO2Epr7SiA==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.2.0", + "@sinonjs/fake-timers": "^10.1.0", "@sinonjs/samsam": "^8.0.0", "diff": "^5.1.0", "nise": "^5.1.4", @@ -3407,32 +3736,36 @@ }, "node_modules/sinon/node_modules/diff": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3440,8 +3773,9 @@ }, "node_modules/spawn-wrap": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, - "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -3456,13 +3790,15 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3474,8 +3810,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3485,16 +3822,18 @@ }, "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -3504,8 +3843,9 @@ }, "node_modules/strip-outer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -3515,16 +3855,18 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3534,8 +3876,9 @@ }, "node_modules/test-exclude": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -3547,22 +3890,25 @@ }, "node_modules/text-table": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/to-fast-properties": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -3572,8 +3918,9 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -3583,16 +3930,18 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/ts-node": { "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -3633,21 +3982,24 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/tslib": { "version": "1.14.1", - "dev": true, - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/tsutils": { "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -3660,8 +4012,9 @@ }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -3672,16 +4025,18 @@ }, "node_modules/type-detect": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", "peer": true, "engines": { "node": ">=10" @@ -3692,16 +4047,18 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, - "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", "dev": true, - "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", @@ -3720,16 +4077,18 @@ }, "node_modules/typedoc/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3742,8 +4101,9 @@ }, "node_modules/typescript": { "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3754,14 +4114,17 @@ }, "node_modules/universalify": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/update-browserslist-db": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -3777,7 +4140,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -3791,8 +4153,9 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "punycode": "^2.1.0" @@ -3800,31 +4163,36 @@ }, "node_modules/uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/vscode-oniguruma": { "version": "1.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true }, "node_modules/vscode-textmate": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3837,13 +4205,15 @@ }, "node_modules/which-module": { "version": "2.0.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true }, "node_modules/word-wrap": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -3851,13 +4221,15 @@ }, "node_modules/workerpool": { "version": "6.2.1", - "dev": true, - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3872,13 +4244,15 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -3888,21 +4262,24 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -3918,16 +4295,18 @@ }, "node_modules/yargs-parser": { "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -3940,8 +4319,9 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -3951,8 +4331,9 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -3962,16 +4343,18 @@ }, "node_modules/yn": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -3980,7 +4363,6 @@ } }, "packages/bloom": { - "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { @@ -3991,7 +4373,6 @@ } }, "packages/client": { - "name": "@redis/client", "version": "2.0.0-next.1", "license": "MIT", "dependencies": { @@ -4008,7 +4389,6 @@ } }, "packages/graph": { - "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { @@ -4019,7 +4399,6 @@ } }, "packages/json": { - "name": "@redis/json", "version": "1.0.4", "license": "MIT", "devDependencies": { @@ -4043,7 +4422,8 @@ }, "packages/redis/node_modules/@redis/client": { "version": "1.5.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz", + "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -4063,10 +4443,10 @@ }, "packages/redis/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "packages/search": { - "name": "@redis/search", "version": "1.1.3", "license": "MIT", "devDependencies": { @@ -4077,7 +4457,6 @@ } }, "packages/test-utils": { - "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.24", "yargs": "^17.7.2" @@ -4088,8 +4467,9 @@ }, "packages/test-utils/node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4101,8 +4481,9 @@ }, "packages/test-utils/node_modules/yargs": { "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -4118,14 +4499,14 @@ }, "packages/test-utils/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "packages/time-series": { - "name": "@redis/time-series", "version": "1.0.4", "license": "MIT", "devDependencies": { From ec17674a67995bebd20ff1b30dd105fa373e5f22 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:15:02 -0400 Subject: [PATCH 131/325] workflow --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 93f0fdff96b..ac8d3c9d392 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Install Packages run: npm ci - name: Build tests tools - run: npm run build:client && npm run build:test-utils + run: npm run build - name: Run Tests run: npm run test -- -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov From d4e2ab5f601086fa31da476566fbcac8a7838c55 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:16:41 -0400 Subject: [PATCH 132/325] wip --- .../lib/commands/LATENCY_LATEST.spec.ts | 50 +++++++++---------- .../client/lib/commands/LATENCY_LATEST.ts | 20 ++++---- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/packages/client/lib/commands/LATENCY_LATEST.spec.ts b/packages/client/lib/commands/LATENCY_LATEST.spec.ts index 4087f212139..8d223ec25e6 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.spec.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.spec.ts @@ -1,27 +1,27 @@ -import {strict as assert} from 'assert'; -import testUtils, {GLOBAL} from '../test-utils'; -import { transformArguments } from './LATENCY_LATEST'; +// import {strict as assert} from 'assert'; +// import testUtils, {GLOBAL} from '../test-utils'; +// import { transformArguments } from './LATENCY_LATEST'; -describe('LATENCY LATEST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['LATENCY', 'LATEST'] - ); - }); +// describe('LATENCY LATEST', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments(), +// ['LATENCY', 'LATEST'] +// ); +// }); - testUtils.testWithClient('client.latencyLatest', async client => { - await Promise.all([ - client.configSet('latency-monitor-threshold', '100'), - client.sendCommand(['DEBUG', 'SLEEP', '1']) - ]); - const latency = await client.latencyLatest(); - assert.ok(Array.isArray(latency)); - for (const [name, timestamp, latestLatency, allTimeLatency] of latency) { - assert.equal(typeof name, 'string'); - assert.equal(typeof timestamp, 'number'); - assert.equal(typeof latestLatency, 'number'); - assert.equal(typeof allTimeLatency, 'number'); - } - }, GLOBAL.SERVERS.OPEN); -}); +// testUtils.testWithClient('client.latencyLatest', async client => { +// await Promise.all([ +// client.configSet('latency-monitor-threshold', '100'), +// client.sendCommand(['DEBUG', 'SLEEP', '1']) +// ]); +// const latency = await client.latencyLatest(); +// assert.ok(Array.isArray(latency)); +// for (const [name, timestamp, latestLatency, allTimeLatency] of latency) { +// assert.equal(typeof name, 'string'); +// assert.equal(typeof timestamp, 'number'); +// assert.equal(typeof latestLatency, 'number'); +// assert.equal(typeof allTimeLatency, 'number'); +// } +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/client/lib/commands/LATENCY_LATEST.ts b/packages/client/lib/commands/LATENCY_LATEST.ts index 3e4dd6236c6..2455841a205 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.ts @@ -1,12 +1,12 @@ -import { RedisCommandArguments } from '.'; +// import { RedisCommandArguments } from '.'; -export function transformArguments(): RedisCommandArguments { - return ['LATENCY', 'LATEST']; -} +// export function transformArguments(): RedisCommandArguments { +// return ['LATENCY', 'LATEST']; +// } -export declare function transformReply(): Array<[ - name: string, - timestamp: number, - latestLatency: number, - allTimeLatency: number -]>; +// export declare function transformReply(): Array<[ +// name: string, +// timestamp: number, +// latestLatency: number, +// allTimeLatency: number +// ]>; From 437fc86d9f0443499e4679fb849bc9ca6771da93 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:18:27 -0400 Subject: [PATCH 133/325] workflow --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ac8d3c9d392..7601fc5515e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,8 +31,8 @@ jobs: if: ${{ matrix.node-version <= 14 }} - name: Install Packages run: npm ci - - name: Build tests tools - run: npm run build + - name: Build + run: npm run build -- ./packages/client ./packages/test-utils/ - name: Run Tests run: npm run test -- -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov From 9d049c31a73642b685e89626380b9f7c212a4a51 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:24:10 -0400 Subject: [PATCH 134/325] workflow --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7601fc5515e..381b79d14fb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,7 +34,7 @@ jobs: - name: Build run: npm run build -- ./packages/client ./packages/test-utils/ - name: Run Tests - run: npm run test -- -- --forbid-only --redis-version=${{ matrix.redis-version }} + run: npm run test -w ./packages/client -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov run: | curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import From 2455ab2089fc7e7d005e5e49d63fa9c36f0719bf Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:40:08 -0400 Subject: [PATCH 135/325] wip --- packages/client/lib/client/socket.ts | 12 +--- packages/client/lib/cluster/index.spec.ts | 6 +- packages/client/lib/test-utils.ts | 76 +++++++++++------------ packages/client/lib/utils.ts | 3 - packages/client/package.json | 3 +- packages/redis/README.md | 20 +++--- 6 files changed, 55 insertions(+), 65 deletions(-) delete mode 100644 packages/client/lib/utils.ts diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index e179613062a..a841828c3a9 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'events'; import * as net from 'net'; import * as tls from 'tls'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError, ReconnectStrategyError } from '../errors'; -import { promiseTimeout } from '../utils'; +import { setTimeout } from 'timers/promises'; import { RedisArgument } from '../RESP/types'; export interface RedisSocketCommonOptions { @@ -159,7 +159,7 @@ export default class RedisSocket extends EventEmitter { } this.emit('error', err); - await promiseTimeout(retryIn); + await setTimeout(retryIn); this.emit('reconnecting'); } } while (this._isOpen && !this._isReady); @@ -283,14 +283,6 @@ export default class RedisSocket extends EventEmitter { this.emit('end'); } - cork(): void { - this._socket?.cork(); - } - - uncork(): void { - this._socket?.uncork(); - } - ref(): void { this._isSocketUnrefed = false; this._socket?.ref(); diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index 4c06dc8c917..2b283a18b58 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -6,7 +6,7 @@ // import { SQUARE_SCRIPT } from '../client/index.spec'; // import { RootNodesUnavailableError } from '../errors'; // import { spy } from 'sinon'; -// import { promiseTimeout } from '../utils'; +// import { setTimeout } from 'timers/promises'; // import RedisClient from '../client'; // describe('Cluster', () => { @@ -284,7 +284,7 @@ // // wait for migrating node to be notified about the new topology // while ((await migratingClient.clusterInfo()).state !== 'ok') { -// await promiseTimeout(50); +// await setTimeout(50); // } // // make sure to cause `MOVED` error @@ -340,7 +340,7 @@ // // wait for migrating node to be notified about the new topology // while ((await migratingClient.clusterInfo()).state !== 'ok') { -// await promiseTimeout(50); +// await setTimeout(50); // } // const listener = spy(); diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts index 65d526f6019..fa40d0a5482 100644 --- a/packages/client/lib/test-utils.ts +++ b/packages/client/lib/test-utils.ts @@ -1,6 +1,6 @@ import TestUtils from '@redis/test-utils'; import { SinonSpy } from 'sinon'; -import { promiseTimeout } from './utils'; +import { setTimeout } from 'timers/promises'; const utils = new TestUtils({ dockerImageName: 'redis', @@ -14,49 +14,49 @@ const DEBUG_MODE_ARGS = utils.isVersionGreaterThan([7]) ? []; export const GLOBAL = { - SERVERS: { - OPEN: { - serverArguments: [...DEBUG_MODE_ARGS] - }, - PASSWORD: { - serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS], - clientOptions: { - password: 'password' - } - } + SERVERS: { + OPEN: { + serverArguments: [...DEBUG_MODE_ARGS] + }, + PASSWORD: { + serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS], + clientOptions: { + password: 'password' + } + } + }, + CLUSTERS: { + OPEN: { + serverArguments: [...DEBUG_MODE_ARGS] }, - CLUSTERS: { - OPEN: { - serverArguments: [...DEBUG_MODE_ARGS] - }, - PASSWORD: { - serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS], - clusterConfiguration: { - defaults: { - password: 'password' - } - } - }, - WITH_REPLICAS: { - serverArguments: [...DEBUG_MODE_ARGS], - numberOfMasters: 2, - numberOfReplicas: 1, - clusterConfiguration: { - useReplicas: true - } + PASSWORD: { + serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS], + clusterConfiguration: { + defaults: { + password: 'password' } + } + }, + WITH_REPLICAS: { + serverArguments: [...DEBUG_MODE_ARGS], + numberOfMasters: 2, + numberOfReplicas: 1, + clusterConfiguration: { + useReplicas: true + } } + } }; export async function waitTillBeenCalled(spy: SinonSpy): Promise { - const start = process.hrtime.bigint(), - calls = spy.callCount; + const start = process.hrtime.bigint(), + calls = spy.callCount; - do { - if (process.hrtime.bigint() - start > 1_000_000_000) { - throw new Error('Waiting for more than 1 second'); - } + do { + if (process.hrtime.bigint() - start > 1_000_000_000) { + throw new Error('Waiting for more than 1 second'); + } - await promiseTimeout(50); - } while (spy.callCount === calls); + await setTimeout(50); + } while (spy.callCount === calls); } diff --git a/packages/client/lib/utils.ts b/packages/client/lib/utils.ts deleted file mode 100644 index 55bed419813..00000000000 --- a/packages/client/lib/utils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function promiseTimeout(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); -} diff --git a/packages/client/package.json b/packages/client/package.json index d0bc06792d6..374cbcae98b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -5,7 +5,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" diff --git a/packages/redis/README.md b/packages/redis/README.md index 3a790cdd4b0..3f05d8dc5a4 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -167,6 +167,16 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each > The client will not emit [any other events](../../docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. +### Links + +- [Multi](../../docs/multi.md). +- [Pub/Sub](../../docs/pub-sub.md). +- [Scan Iterators](../../docs/scan-iterators.md). +- [Programmability](../../docs/programmability.md). +- [Command Options](../../docs/command-options.md). +- [Blocking Commands](../../docs/blocking-commands.md). +- [Clustering](../../docs/clustering.md). + ## Supported Redis versions Node Redis is supported with the following versions of Redis: @@ -192,13 +202,3 @@ Thank you to all the people who already contributed to Node Redis! ## License This repository is licensed under the "MIT" license. See [LICENSE](../../LICENSE). - -### Links - -- [Multi](../../docs/multi.md). -- [Pub/Sub](../../docs/pub-sub.md). -- [Scan Iterators](../../docs/scan-iterators.md). -- [Programmability](../../docs/programmability.md). -- [Command Options](../../docs/command-options.md). -- [Blocking Commands](../../docs/blocking-commands.md). -- [Clustering](../../docs/clustering.md). From faea2488af4fd266046a3c93f7dbd1ac3a038f29 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:54:22 -0400 Subject: [PATCH 136/325] wip --- packages/client/lib/commands/ACL_LOG.spec.ts | 2 +- .../client/lib/commands/ACL_SETUSER.spec.ts | 30 +++++++++---------- .../client/lib/commands/ACL_USERS.spec.ts | 16 +++++----- .../client/lib/commands/ACL_WHOAMI.spec.ts | 16 +++++----- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/client/lib/commands/ACL_LOG.spec.ts b/packages/client/lib/commands/ACL_LOG.spec.ts index 6b63b59f81c..b2f62352306 100644 --- a/packages/client/lib/commands/ACL_LOG.spec.ts +++ b/packages/client/lib/commands/ACL_LOG.spec.ts @@ -24,7 +24,7 @@ describe('ACL LOG', () => { testUtils.testWithClient('client.aclLog', async client => { // make sure to create at least one log await Promise.all([ - client.aclSetUser('test', 'on >test'), + client.aclSetUser('test', 'on +@all'), client.auth({ username: 'test', password: 'test' diff --git a/packages/client/lib/commands/ACL_SETUSER.spec.ts b/packages/client/lib/commands/ACL_SETUSER.spec.ts index 9c8ea8a59e0..00032046641 100644 --- a/packages/client/lib/commands/ACL_SETUSER.spec.ts +++ b/packages/client/lib/commands/ACL_SETUSER.spec.ts @@ -1,23 +1,23 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './ACL_SETUSER'; +import ACL_SETUSER from './ACL_SETUSER'; describe('ACL SETUSER', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('username', 'allkeys'), - ['ACL', 'SETUSER', 'username', 'allkeys'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + ACL_SETUSER.transformArguments('username', 'allkeys'), + ['ACL', 'SETUSER', 'username', 'allkeys'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments('username', ['allkeys', 'allchannels']), - ['ACL', 'SETUSER', 'username', 'allkeys', 'allchannels'] - ); - }); + it('array', () => { + assert.deepEqual( + ACL_SETUSER.transformArguments('username', ['allkeys', 'allchannels']), + ['ACL', 'SETUSER', 'username', 'allkeys', 'allchannels'] + ); }); + }); }); diff --git a/packages/client/lib/commands/ACL_USERS.spec.ts b/packages/client/lib/commands/ACL_USERS.spec.ts index 35e06ce8494..925a42f8a82 100644 --- a/packages/client/lib/commands/ACL_USERS.spec.ts +++ b/packages/client/lib/commands/ACL_USERS.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './ACL_USERS'; +import ACL_USERS from './ACL_USERS'; describe('ACL USERS', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'USERS'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_USERS.transformArguments(), + ['ACL', 'USERS'] + ); + }); }); diff --git a/packages/client/lib/commands/ACL_WHOAMI.spec.ts b/packages/client/lib/commands/ACL_WHOAMI.spec.ts index 32eb327beea..d4bad99dbd5 100644 --- a/packages/client/lib/commands/ACL_WHOAMI.spec.ts +++ b/packages/client/lib/commands/ACL_WHOAMI.spec.ts @@ -1,14 +1,14 @@ import { strict as assert } from 'assert'; import testUtils from '../test-utils'; -import { transformArguments } from './ACL_WHOAMI'; +import ACL_WHOAMI from './ACL_WHOAMI'; describe('ACL WHOAMI', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ACL', 'WHOAMI'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ACL_WHOAMI.transformArguments(), + ['ACL', 'WHOAMI'] + ); + }); }); From f22879dffa707ad34fb7d76ea25a317e47eb2f5a Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 19 Jun 2023 18:54:32 -0400 Subject: [PATCH 137/325] wip --- packages/client/lib/commands/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 299b805905e..81cf34b5250 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -1,4 +1,5 @@ import ACL_CAT from './ACL_CAT'; +import ACL_DELUSER from './ACL_DELUSER'; import ACL_DRYRUN from './ACL_DRYRUN'; import ACL_GENPASS from './ACL_GENPASS'; import ACL_GETUSER from './ACL_GETUSER'; @@ -259,6 +260,7 @@ import ZUNIONSTORE from './ZUNIONSTORE'; import { Command } from '../RESP/types'; type ACL_CAT = typeof import('./ACL_CAT').default; +type ACL_DELUSER = typeof import('./ACL_DELUSER').default; type ACL_DRYRUN = typeof import('./ACL_DRYRUN').default; type ACL_GENPASS = typeof import('./ACL_GENPASS').default; type ACL_GETUSER = typeof import('./ACL_GETUSER').default; @@ -520,6 +522,8 @@ type ZUNIONSTORE = typeof import('./ZUNIONSTORE').default; type Commands = { ACL_CAT: ACL_CAT; aclCat: ACL_CAT; + ACL_DELUSER: ACL_DELUSER; + aclDelUser: ACL_DELUSER; ACL_DRYRUN: ACL_DRYRUN; aclDryRun: ACL_DRYRUN; ACL_GENPASS: ACL_GENPASS; @@ -1041,6 +1045,8 @@ type Commands = { export default { ACL_CAT, aclCat: ACL_CAT, + ACL_DELUSER, + aclDelUser: ACL_DELUSER, ACL_DRYRUN, aclDryRun: ACL_DRYRUN, ACL_GENPASS, From 4894c264588d5db5abc6894d1304dd8609f368a1 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 20 Jun 2023 20:04:05 -0400 Subject: [PATCH 138/325] wip --- docs/v4-to-v5.md | 8 +- packages/client/index.ts | 2 +- packages/client/lib/client/commands-queue.ts | 7 +- packages/client/lib/client/index.spec.ts | 19 +- packages/client/lib/client/index.ts | 74 ++++---- packages/client/lib/client/socket.spec.ts | 158 ++++++++-------- packages/client/lib/cluster/index.ts | 87 ++++++--- packages/client/lib/commands/ACL_LOG.spec.ts | 33 ++-- packages/client/lib/commands/ACL_LOG.ts | 33 ++-- packages/client/lib/commands/ACL_WHOAMI.ts | 2 +- .../lib/commands/CLIENT_TRACKING.spec.ts | 170 +++++++++--------- .../client/lib/commands/CLIENT_TRACKING.ts | 143 +++++++-------- .../lib/commands/CLIENT_TRACKINGINFO.spec.ts | 37 ++-- .../lib/commands/CLIENT_TRACKINGINFO.ts | 47 +++-- .../lib/commands/CLIENT_UNPAUSE.spec.ts | 28 +-- .../lib/commands/CLUSTER_ADDSLOTS.spec.ts | 28 +-- .../commands/CLUSTER_ADDSLOTSRANGE.spec.ts | 49 ++--- .../lib/commands/CLUSTER_BUMPEPOCH.spec.ts | 28 +-- .../lib/commands/CLUSTER_KEYSLOT.spec.ts | 28 +-- .../client/lib/commands/CLUSTER_MEET.spec.ts | 14 +- packages/client/lib/commands/CLUSTER_MEET.ts | 2 +- .../lib/commands/CLUSTER_REPLICATE.spec.ts | 14 +- .../client/lib/commands/CLUSTER_RESET.spec.ts | 30 ++-- packages/client/lib/commands/CLUSTER_RESET.ts | 21 ++- .../lib/commands/CLUSTER_SAVECONFIG.spec.ts | 28 +-- .../client/lib/commands/CLUSTER_SAVECONFIG.ts | 14 +- .../commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts | 14 +- .../lib/commands/CLUSTER_SET-CONFIG-EPOCH.ts | 13 +- .../lib/commands/CLUSTER_SETSLOT.spec.ts | 28 +-- .../client/lib/commands/CLUSTER_SETSLOT.ts | 33 ++-- .../client/lib/commands/CLUSTER_SLOTS.spec.ts | 96 +++------- .../lib/commands/FUNCTION_RESTORE.spec.ts | 4 +- packages/client/lib/commands/index.ts | 154 ++++++++++++++-- packages/client/lib/test-utils.ts | 3 +- packages/test-utils/lib/index.ts | 55 +++--- 35 files changed, 845 insertions(+), 659 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index ad06eec97a5..fde8e283797 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -161,9 +161,15 @@ Some command arguments/replies have changed to align more closely to data types - `HELLO`: `protover` moved from the options object to it's own argument, `auth` -> `AUTH`, `clientName` -> `SETNAME` - `MODULE LIST`: `version` -> `ver` [^map-keys] - `MEMORY STATS`: [^map-keys] +- `CLIENT TRACKINGINFO`: `flags` in RESP2 - `Set` -> `Array` (to match RESP3 default type mapping) +- `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] +- `FUNCTION RESTORE`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] [^enum-to-constants]: TODO [^boolean-to-number]: TODO -[^map-keys]: [TODO](https://github.com/redis/node-redis/discussions/2506) \ No newline at end of file +[^map-keys]: [TODO](https://github.com/redis/node-redis/discussions/2506) + +[^future-proofing]: TODO \ No newline at end of file diff --git a/packages/client/index.ts b/packages/client/index.ts index c9b93f3377b..09874984de1 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -1,4 +1,4 @@ -export { RedisModules, RedisFunctions, RedisScripts, RespVersions } from './lib/RESP/types'; +export { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, CommandPolicies } from './lib/RESP/types'; export { RESP_TYPES } from './lib/RESP/decoder'; export { VerbatimString } from './lib/RESP/verbatim-string'; export { defineScript } from './lib/lua-script'; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index b3ede1ccd67..58699174cd3 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -6,11 +6,14 @@ import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, Pu import { AbortError, ErrorReply } from '../errors'; import { EventEmitter } from 'stream'; -export interface CommandOptions { +export interface CommandOptions { chainId?: symbol; asap?: boolean; abortSignal?: AbortSignal; - typeMapping?: TypeMapping; + /** + * Maps bettween RESP and JavaScript types + */ + typeMapping?: T; } export interface CommandWaitingToBeSent extends CommandWaitingForReply { diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index f1e88bb140b..7a259720ef4 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -122,10 +122,10 @@ describe('Client', () => { client.connect() ]); - const promise = once(client, 'end'); - console.log('listen to end', client.listeners('end')); - client.close(); - await promise; + await Promise.all([ + once(client, 'end'), + client.close() + ]); }, { ...GLOBAL.SERVERS.OPEN, disableClientSetup: true @@ -335,9 +335,7 @@ describe('Client', () => { }); testUtils.testWithClient('duplicate should reuse command options', async client => { - const duplicate = client.withTypeMapping({ - [RESP_TYPES.SIMPLE_STRING]: Buffer - }).duplicate(); + const duplicate = client.duplicate(); await duplicate.connect(); @@ -351,6 +349,13 @@ describe('Client', () => { } }, { ...GLOBAL.SERVERS.OPEN, + clientOptions: { + commandOptions: { + typeMapping: { + [RESP_TYPES.SIMPLE_STRING]: Buffer + } + } + }, disableClientSetup: true, }); diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 75f94333f70..3d43ae55b8b 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -11,18 +11,27 @@ import { Command, CommandArguments, CommandSignature, TypeMapping, CommanderConf import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; -import { ReplyWithTypeMapping, CommandReply } from '../RESP/types'; import { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; // import { RedisClientPool } from './pool'; +interface ClientCommander< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends CommanderConfig{ + commandOptions?: CommandOptions; +} + export interface RedisClientOptions< M extends RedisModules = RedisModules, F extends RedisFunctions = RedisFunctions, S extends RedisScripts = RedisScripts, RESP extends RespVersions = RespVersions, TYPE_MAPPING extends TypeMapping = TypeMapping -> extends CommanderConfig, TypeMappingOption { +> extends ClientCommander { /** * `redis[s]://[[username][:password]@][host][:port][/db-number]` * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details @@ -68,13 +77,6 @@ export interface RedisClientOptions< pingInterval?: number; } -export interface TypeMappingOption { - /** - * Maps bettwen RESP types to JavaScript types - */ - typeMapping?: TYPE_MAPPING; -} - type WithCommands< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping @@ -134,7 +136,7 @@ export type RedisClientType< RedisClientExtensions ); -type ProxyClient = RedisClient & { commandOptions?: CommandOptions }; +type ProxyClient = RedisClient; type NamespaceProxyClient = { self: ProxyClient }; @@ -153,7 +155,7 @@ export default class RedisClient< const transformReply = getTransformReply(command, resp); return async function (this: ProxyClient, ...args: Array) { const redisArgs = command.transformArguments(...args), - reply = await this.sendCommand(redisArgs, this.commandOptions); + reply = await this.sendCommand(redisArgs, this._commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -164,7 +166,7 @@ export default class RedisClient< const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyClient, ...args: Array) { const redisArgs = command.transformArguments(...args), - reply = await this.self.sendCommand(redisArgs, this.self.commandOptions); + reply = await this.self.sendCommand(redisArgs, this.self._commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -178,7 +180,7 @@ export default class RedisClient< const fnArgs = fn.transformArguments(...args), reply = await this.self.sendCommand( prefix.concat(fnArgs), - this.self.commandOptions + this.self._commandOptions ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -192,12 +194,12 @@ export default class RedisClient< return async function (this: ProxyClient, ...args: Array) { const scriptArgs = script.transformArguments(...args), redisArgs = prefix.concat(scriptArgs), - reply = await this.sendCommand(redisArgs, this.commandOptions).catch((err: unknown) => { + reply = await this.sendCommand(redisArgs, this._commandOptions).catch((err: unknown) => { if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; redisArgs[0] = 'EVAL'; redisArgs[1] = script.SCRIPT; - return this.sendCommand(redisArgs, this.commandOptions); + return this.sendCommand(redisArgs, this._commandOptions); }); return transformReply ? transformReply(reply, scriptArgs.preserve) : @@ -211,7 +213,7 @@ export default class RedisClient< S extends RedisScripts = {}, RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {} - >(config?: CommanderConfig & TypeMappingOption) { + >(config?: ClientCommander) { const Client = attachConfig({ BaseClass: RedisClient, commands: COMMANDS, @@ -282,10 +284,11 @@ export default class RedisClient< self = this; - private readonly _options?: RedisClientOptions; + private readonly _options?: RedisClientOptions; private readonly _socket: RedisSocket; private readonly _queue: RedisCommandsQueue; private _selectedDB = 0; + private _commandOptions?: CommandOptions; get options(): RedisClientOptions | undefined { return this._options; @@ -303,14 +306,14 @@ export default class RedisClient< return this._queue.isPubSubActive; } - constructor(options?: RedisClientOptions) { + constructor(options?: RedisClientOptions) { super(); this._options = this._initiateOptions(options); this._queue = this._initiateQueue(); this._socket = this._initiateSocket(); } - private _initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { + private _initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { if (options?.url) { const parsed = RedisClient.parseURL(options.url); if (options.socket) { @@ -324,10 +327,8 @@ export default class RedisClient< this._selectedDB = options.database; } - if (options?.typeMapping) { - (this as unknown as ProxyClient).commandOptions = { - typeMapping: options.typeMapping - }; + if (options?.commandOptions) { + this._commandOptions = options.commandOptions; } return options; @@ -462,15 +463,18 @@ export default class RedisClient< }, this._options.pingInterval); } - withCommandOptions(options: T) { + withCommandOptions< + OPTIONS extends CommandOptions, + TYPE_MAPPING extends TypeMapping + >(options: OPTIONS) { const proxy = Object.create(this.self); - proxy.commandOptions = options; + proxy._commandOptions = options; return proxy as RedisClientType< M, F, S, RESP, - T['typeMapping'] extends TypeMapping ? T['typeMapping'] : {} + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {} >; } @@ -482,8 +486,8 @@ export default class RedisClient< value: V ) { const proxy = Object.create(this.self); - proxy.commandOptions = Object.create((this as unknown as ProxyClient).commandOptions ?? null); - proxy.commandOptions[key] = value; + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; return proxy as RedisClientType< M, F, @@ -539,17 +543,11 @@ export default class RedisClient< _RESP extends RespVersions = RESP, _TYPE_MAPPING extends TypeMapping = TYPE_MAPPING >(overrides?: Partial>) { - const client = new (Object.getPrototypeOf(this).constructor)({ + return new (Object.getPrototypeOf(this).constructor)({ ...this._options, + commandOptions: this._commandOptions, ...overrides }) as RedisClientType<_M, _F, _S, _RESP, _TYPE_MAPPING>; - - const { commandOptions } = this as ProxyClient; - if (commandOptions) { - return client.withCommandOptions(commandOptions); - } - - return client; } connect() { @@ -732,7 +730,7 @@ export default class RedisClient< const promise = Promise.all( commands.map(({ args }) => this._queue.addCommand(args, { - typeMapping: (this as ProxyClient).commandOptions?.typeMapping + typeMapping: this._commandOptions?.typeMapping })) ); this._scheduleWrite(); @@ -750,7 +748,7 @@ export default class RedisClient< return Promise.reject(new ClientClosedError()); } - const typeMapping = (this as ProxyClient).commandOptions?.typeMapping, + const typeMapping = this._commandOptions?.typeMapping, chainId = Symbol('MULTI Chain'), promises = [ this._queue.addCommand(['MULTI'], { chainId }), diff --git a/packages/client/lib/client/socket.spec.ts b/packages/client/lib/client/socket.spec.ts index eb555351ac4..ad874f06c76 100644 --- a/packages/client/lib/client/socket.spec.ts +++ b/packages/client/lib/client/socket.spec.ts @@ -4,84 +4,84 @@ import { once } from 'events'; import RedisSocket, { RedisSocketOptions } from './socket'; describe('Socket', () => { - function createSocket(options: RedisSocketOptions): RedisSocket { - const socket = new RedisSocket( - () => Promise.resolve(), - options - ); - - socket.on('error', () => { - // ignore errors - }); - - return socket; - } - - describe('reconnectStrategy', () => { - it('false', async () => { - const socket = createSocket({ - host: 'error', - connectTimeout: 1, - reconnectStrategy: false - }); - - await assert.rejects(socket.connect()); - - assert.equal(socket.isOpen, false); - }); - - it('0', async () => { - const socket = createSocket({ - host: 'error', - connectTimeout: 1, - reconnectStrategy: 0 - }); - - socket.connect(); - await once(socket, 'error'); - assert.equal(socket.isOpen, true); - assert.equal(socket.isReady, false); - socket.disconnect(); - assert.equal(socket.isOpen, false); - }); - - it('custom strategy', async () => { - const numberOfRetries = 3; - - const reconnectStrategy = spy((retries: number) => { - assert.equal(retries + 1, reconnectStrategy.callCount); - - if (retries === numberOfRetries) return new Error(`${numberOfRetries}`); - - return 0; - }); - - const socket = createSocket({ - host: 'error', - connectTimeout: 1, - reconnectStrategy - }); - - await assert.rejects(socket.connect(), { - message: `${numberOfRetries}` - }); - - assert.equal(socket.isOpen, false); - }); - - it('should handle errors', async () => { - const socket = createSocket({ - host: 'error', - connectTimeout: 1, - reconnectStrategy(retries: number) { - if (retries === 1) return new Error('done'); - throw new Error(); - } - }); - - await assert.rejects(socket.connect()); - - assert.equal(socket.isOpen, false); - }); + function createSocket(options: RedisSocketOptions): RedisSocket { + const socket = new RedisSocket( + () => Promise.resolve(), + options + ); + + socket.on('error', () => { + // ignore errors }); + + return socket; + } + + describe('reconnectStrategy', () => { + it('false', async () => { + const socket = createSocket({ + host: 'error', + connectTimeout: 1, + reconnectStrategy: false + }); + + await assert.rejects(socket.connect()); + + assert.equal(socket.isOpen, false); + }); + + it('0', async () => { + const socket = createSocket({ + host: 'error', + connectTimeout: 1, + reconnectStrategy: 0 + }); + + socket.connect(); + await once(socket, 'error'); + assert.equal(socket.isOpen, true); + assert.equal(socket.isReady, false); + socket.destroy(); + assert.equal(socket.isOpen, false); + }); + + it('custom strategy', async () => { + const numberOfRetries = 3; + + const reconnectStrategy = spy((retries: number) => { + assert.equal(retries + 1, reconnectStrategy.callCount); + + if (retries === numberOfRetries) return new Error(`${numberOfRetries}`); + + return 0; + }); + + const socket = createSocket({ + host: 'error', + connectTimeout: 1, + reconnectStrategy + }); + + await assert.rejects(socket.connect(), { + message: `${numberOfRetries}` + }); + + assert.equal(socket.isOpen, false); + }); + + it('should handle errors', async () => { + const socket = createSocket({ + host: 'error', + connectTimeout: 1, + reconnectStrategy(retries: number) { + if (retries === 1) return new Error('done'); + throw new Error(); + } + }); + + await assert.rejects(socket.connect()); + + assert.equal(socket.isOpen, false); + }); + }); }); diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 17a3dc0904d..e0386e74c58 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -10,17 +10,30 @@ import { RedisMultiQueuedCommand } from '../multi-command'; import { PubSubListener } from '../client/pub-sub'; import { ErrorReply } from '../errors'; +interface ClusterCommander< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + POLICIES extends CommandPolicies +> extends CommanderConfig{ + commandOptions?: ClusterCommandOptions; +} + export type RedisClusterClientOptions = Omit< RedisClientOptions, - 'modules' | 'functions' | 'scripts' | 'database' | 'RESP' + keyof ClusterCommander >; export interface RedisClusterOptions< M extends RedisModules = RedisModules, F extends RedisFunctions = RedisFunctions, S extends RedisScripts = RedisScripts, - RESP extends RespVersions = RespVersions -> extends CommanderConfig { + RESP extends RespVersions = RespVersions, + TYPE_MAPPING extends TypeMapping = TypeMapping, + POLICIES extends CommandPolicies = CommandPolicies +> extends ClusterCommander { /** * Should contain details for some of the cluster nodes that the client will use to discover * the "cluster topology". We recommend including details for at least 3 nodes here. @@ -70,11 +83,14 @@ export type RedisClusterType< > = RedisCluster & WithCommands; // & WithModules & WithFunctions & WithScripts -export interface ClusterCommandOptions extends CommandOptions { - policies?: CommandPolicies; +export interface ClusterCommandOptions< + TYPE_MAPPING extends TypeMapping = TypeMapping, + POLICIES extends CommandPolicies = CommandPolicies +> extends CommandOptions { + policies?: POLICIES; } -type ProxyCluster = RedisCluster & { commandOptions?: ClusterCommandOptions }; +type ProxyCluster = RedisCluster; type NamespaceProxyCluster = { self: ProxyCluster }; @@ -113,7 +129,7 @@ export default class RedisCluster< firstKey, command.IS_READ_ONLY, redisArgs, - this.commandOptions, + this._commandOptions, command.POLICIES ); @@ -136,7 +152,7 @@ export default class RedisCluster< firstKey, command.IS_READ_ONLY, redisArgs, - this.self.commandOptions, + this.self._commandOptions, command.POLICIES ); @@ -161,7 +177,7 @@ export default class RedisCluster< firstKey, fn.IS_READ_ONLY, redisArgs, - this.self.commandOptions, + this.self._commandOptions, fn.POLICIES ); @@ -186,7 +202,7 @@ export default class RedisCluster< firstKey, script.IS_READ_ONLY, redisArgs, - this.commandOptions, + this._commandOptions, script.POLICIES ); @@ -200,8 +216,10 @@ export default class RedisCluster< M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 - >(config?: CommanderConfig) { + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, + POLICIES extends CommandPolicies = {} + >(config?: ClusterCommander) { const Cluster = attachConfig({ BaseClass: RedisCluster, commands: COMMANDS, @@ -217,7 +235,7 @@ export default class RedisCluster< return (options?: Omit>) => { // returning a proxy of the client to prevent the namespaces.self to leak between proxies // namespaces will be bootstraped on first access per proxy - return Object.create(new Cluster(options)) as RedisClusterType; + return Object.create(new Cluster(options)) as RedisClusterType; }; } @@ -225,15 +243,19 @@ export default class RedisCluster< M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 - >(options?: RedisClusterOptions) { + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, + POLICIES extends CommandPolicies = {} + >(options?: RedisClusterOptions) { return RedisCluster.factory(options)(options); } - private readonly _options: RedisClusterOptions; + private readonly _options: RedisClusterOptions; private readonly _slots: RedisClusterSlots; + private _commandOptions?: ClusterCommandOptions; + /** * An array of the cluster slots, each slot contain its `master` and `replicas`. * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). @@ -285,34 +307,49 @@ export default class RedisCluster< return this._slots.isOpen; } - constructor(options: RedisClusterOptions) { + constructor(options: RedisClusterOptions) { super(); this._options = options; this._slots = new RedisClusterSlots(options, this.emit.bind(this)); + + if (options?.commandOptions) { + this._commandOptions = options.commandOptions; + } } - duplicate(overrides?: Partial>): RedisClusterType { + duplicate< + _M extends RedisModules = M, + _F extends RedisFunctions = F, + _S extends RedisScripts = S, + _RESP extends RespVersions = RESP, + _TYPE_MAPPING extends TypeMapping = TYPE_MAPPING + >(overrides?: Partial>) { return new (Object.getPrototypeOf(this).constructor)({ ...this._options, + commandOptions: this._commandOptions, ...overrides - }); + }) as RedisClusterType<_M, _F, _S, _RESP, _TYPE_MAPPING>; } connect() { return this._slots.connect(); } - withCommandOptions(options: T) { + withCommandOptions< + OPTIONS extends ClusterCommandOptions, + TYPE_MAPPING extends TypeMapping, + POLICIES extends CommandPolicies + >(options: OPTIONS) { const proxy = Object.create(this); - proxy.commandOptions = options; + proxy._commandOptions = options; return proxy as RedisClusterType< M, F, S, RESP, - T['typeMapping'] extends TypeMapping ? T['typeMapping'] : {}, - T['policies'] extends CommandPolicies ? T['policies'] : {} + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {}, + POLICIES extends CommandPolicies ? POLICIES : {} >; } @@ -324,8 +361,8 @@ export default class RedisCluster< value: V ) { const proxy = Object.create(this); - proxy.commandOptions = Object.create((this as unknown as ProxyCluster).commandOptions ?? null); - proxy.commandOptions[key] = value; + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; return proxy as RedisClusterType< M, F, diff --git a/packages/client/lib/commands/ACL_LOG.spec.ts b/packages/client/lib/commands/ACL_LOG.spec.ts index b2f62352306..8e66ea063aa 100644 --- a/packages/client/lib/commands/ACL_LOG.spec.ts +++ b/packages/client/lib/commands/ACL_LOG.spec.ts @@ -22,32 +22,29 @@ describe('ACL LOG', () => { }); testUtils.testWithClient('client.aclLog', async client => { - // make sure to create at least one log - await Promise.all([ - client.aclSetUser('test', 'on +@all'), + // make sure to create one log + await assert.rejects( client.auth({ - username: 'test', - password: 'test' - }), - client.auth({ - username: 'default', - password: '' + username: 'incorrect', + password: 'incorrect' }) - ]); + ); const logs = await client.aclLog(); assert.ok(Array.isArray(logs)); for (const log of logs) { - assert.equal(typeof log.count, 'number'); - assert.equal(typeof log.timestamp, 'number'); + assert.equal(typeof log.reason, 'string'); + assert.equal(typeof log.context, 'string'); + assert.equal(typeof log.object, 'string'); assert.equal(typeof log.username, 'string'); - assert.equal(typeof log.clientId, 'string'); - assert.equal(typeof log.command, 'string'); - assert.equal(typeof log.args, 'string'); - assert.equal(typeof log.key, 'string'); - assert.equal(typeof log.result, 'number'); - assert.equal(typeof log.duration, 'number'); + assert.equal(typeof log['age-seconds'], 'number'); + assert.equal(typeof log['client-info'], 'string'); + if (testUtils.isVersionGreaterThan([7, 2])) { + assert.equal(typeof log['entry-id'], 'number'); + assert.equal(typeof log['timestamp-created'], 'number'); + assert.equal(typeof log['timestamp-last-updated'], 'number'); + } } }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ACL_LOG.ts b/packages/client/lib/commands/ACL_LOG.ts index 4140111ecfc..55172095d1b 100644 --- a/packages/client/lib/commands/ACL_LOG.ts +++ b/packages/client/lib/commands/ACL_LOG.ts @@ -1,4 +1,4 @@ -import { Resp2Reply } from '../RESP/types'; +import { DoubleReply, Resp2Reply } from '../RESP/types'; import { ArrayReply, BlobStringReply, Command, NumberReply, TuplesToMapReply } from '../RESP/types'; export type AclLogReply = ArrayReply, BlobStringReply], [BlobStringReply<'object'>, BlobStringReply], [BlobStringReply<'username'>, BlobStringReply], - [BlobStringReply<'age-seconds'>, BlobStringReply], - [BlobStringReply<'client-info'>, BlobStringReply] + [BlobStringReply<'age-seconds'>, DoubleReply], + [BlobStringReply<'client-info'>, BlobStringReply], + /** added in 7.0 */ + [BlobStringReply<'entry-id'>, NumberReply], + /** added in 7.0 */ + [BlobStringReply<'timestamp-created'>, NumberReply], + /** added in 7.0 */ + [BlobStringReply<'timestamp-last-updated'>, NumberReply] ]>>; export default { @@ -24,15 +30,18 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => ({ - count: Number(reply[1]), - reason: reply[3], - context: reply[5], - object: reply[7], - username: reply[9], - 'age-seconds': Number(reply[11]), - 'client-info': reply[13] - }), + 2: (reply: Resp2Reply) => reply.map(item => ({ + count: item[1], + reason: item[3], + context: item[5], + object: item[7], + username: item[9], + 'age-seconds': Number(item[11]), + 'client-info': item[13], + 'entry-id': item[15], + 'timestamp-created': item[17], + 'timestamp-last-updated': item[19] + })), 3: undefined as unknown as () => AclLogReply } } as const satisfies Command; diff --git a/packages/client/lib/commands/ACL_WHOAMI.ts b/packages/client/lib/commands/ACL_WHOAMI.ts index 5aa56c4d351..81a1c84a3c6 100644 --- a/packages/client/lib/commands/ACL_WHOAMI.ts +++ b/packages/client/lib/commands/ACL_WHOAMI.ts @@ -4,7 +4,7 @@ export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments() { - return ['ACL', 'USERS']; + return ['ACL', 'WHOAMI']; }, transformReply: undefined as unknown as () => BlobStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_TRACKING.spec.ts b/packages/client/lib/commands/CLIENT_TRACKING.spec.ts index bbd0b13e777..0a8ea58e084 100644 --- a/packages/client/lib/commands/CLIENT_TRACKING.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKING.spec.ts @@ -1,101 +1,101 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_TRACKING'; +import CLIENT_TRACKING from './CLIENT_TRACKING'; describe('CLIENT TRACKING', () => { - testUtils.isVersionGreaterThanHook([6]); + testUtils.isVersionGreaterThanHook([6]); - describe('transformArguments', () => { - describe('true', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(true), - ['CLIENT', 'TRACKING', 'ON'] - ); - }); + describe('transformArguments', () => { + describe('true', () => { + it('simple', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true), + ['CLIENT', 'TRACKING', 'ON'] + ); + }); - it('with REDIRECT', () => { - assert.deepEqual( - transformArguments(true, { - REDIRECT: 1 - }), - ['CLIENT', 'TRACKING', 'ON', 'REDIRECT', '1'] - ); - }); + it('with REDIRECT', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + REDIRECT: 1 + }), + ['CLIENT', 'TRACKING', 'ON', 'REDIRECT', '1'] + ); + }); - describe('with BCAST', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(true, { - BCAST: true - }), - ['CLIENT', 'TRACKING', 'ON', 'BCAST'] - ); - }); + describe('with BCAST', () => { + it('simple', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + BCAST: true + }), + ['CLIENT', 'TRACKING', 'ON', 'BCAST'] + ); + }); - describe('with PREFIX', () => { - it('string', () => { - assert.deepEqual( - transformArguments(true, { - BCAST: true, - PREFIX: 'prefix' - }), - ['CLIENT', 'TRACKING', 'ON', 'BCAST', 'PREFIX', 'prefix'] - ); - }); + describe('with PREFIX', () => { + it('string', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + BCAST: true, + PREFIX: 'prefix' + }), + ['CLIENT', 'TRACKING', 'ON', 'BCAST', 'PREFIX', 'prefix'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(true, { - BCAST: true, - PREFIX: ['1', '2'] - }), - ['CLIENT', 'TRACKING', 'ON', 'BCAST', 'PREFIX', '1', 'PREFIX', '2'] - ); - }); - }); - }); + it('array', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + BCAST: true, + PREFIX: ['1', '2'] + }), + ['CLIENT', 'TRACKING', 'ON', 'BCAST', 'PREFIX', '1', 'PREFIX', '2'] + ); + }); + }); + }); - it('with OPTIN', () => { - assert.deepEqual( - transformArguments(true, { - OPTIN: true - }), - ['CLIENT', 'TRACKING', 'ON', 'OPTIN'] - ); - }); + it('with OPTIN', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + OPTIN: true + }), + ['CLIENT', 'TRACKING', 'ON', 'OPTIN'] + ); + }); - it('with OPTOUT', () => { - assert.deepEqual( - transformArguments(true, { - OPTOUT: true - }), - ['CLIENT', 'TRACKING', 'ON', 'OPTOUT'] - ); - }); + it('with OPTOUT', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + OPTOUT: true + }), + ['CLIENT', 'TRACKING', 'ON', 'OPTOUT'] + ); + }); - it('with NOLOOP', () => { - assert.deepEqual( - transformArguments(true, { - NOLOOP: true - }), - ['CLIENT', 'TRACKING', 'ON', 'NOLOOP'] - ); - }); - }); + it('with NOLOOP', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(true, { + NOLOOP: true + }), + ['CLIENT', 'TRACKING', 'ON', 'NOLOOP'] + ); + }); + }); - it('false', () => { - assert.deepEqual( - transformArguments(false), - ['CLIENT', 'TRACKING', 'OFF'] - ); - }); + it('false', () => { + assert.deepEqual( + CLIENT_TRACKING.transformArguments(false), + ['CLIENT', 'TRACKING', 'OFF'] + ); }); + }); - testUtils.testWithClient('client.clientTracking', async client => { - assert.equal( - await client.clientTracking(false), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientTracking', async client => { + assert.equal( + await client.clientTracking(false), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_TRACKING.ts b/packages/client/lib/commands/CLIENT_TRACKING.ts index 03926b5300f..5eebb8492ac 100644 --- a/packages/client/lib/commands/CLIENT_TRACKING.ts +++ b/packages/client/lib/commands/CLIENT_TRACKING.ts @@ -1,83 +1,86 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument } from './generic-transformers'; +interface CommonOptions { + REDIRECT?: number; + NOLOOP?: boolean; +} -// interface CommonOptions { -// REDIRECT?: number; -// NOLOOP?: boolean; -// } +interface BroadcastOptions { + BCAST?: boolean; + PREFIX?: RedisVariadicArgument; +} -// interface BroadcastOptions { -// BCAST?: boolean; -// PREFIX?: RedisCommandArgument | Array; -// } +interface OptInOptions { + OPTIN?: boolean; +} -// interface OptInOptions { -// OPTIN?: boolean; -// } +interface OptOutOptions { + OPTOUT?: boolean; +} -// interface OptOutOptions { -// OPTOUT?: boolean; -// } +type ClientTrackingOptions = CommonOptions & ( + BroadcastOptions | + OptInOptions | + OptOutOptions +); -// type ClientTrackingOptions = CommonOptions & ( -// BroadcastOptions | -// OptInOptions | -// OptOutOptions -// ); +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments( + mode: M, + options?: M extends true ? ClientTrackingOptions : never + ) { + const args: Array = [ + 'CLIENT', + 'TRACKING', + mode ? 'ON' : 'OFF' + ]; -// export function transformArguments( -// mode: M, -// options?: M extends true ? ClientTrackingOptions : undefined -// ): RedisCommandArguments { -// const args: RedisCommandArguments = [ -// 'CLIENT', -// 'TRACKING', -// mode ? 'ON' : 'OFF' -// ]; + if (mode) { + if (options?.REDIRECT) { + args.push( + 'REDIRECT', + options.REDIRECT.toString() + ); + } -// if (mode) { -// if (options?.REDIRECT) { -// args.push( -// 'REDIRECT', -// options.REDIRECT.toString() -// ); -// } + if (isBroadcast(options)) { + args.push('BCAST'); -// if (isBroadcast(options)) { -// args.push('BCAST'); + if (options?.PREFIX) { + if (Array.isArray(options.PREFIX)) { + for (const prefix of options.PREFIX) { + args.push('PREFIX', prefix); + } + } else { + args.push('PREFIX', options.PREFIX); + } + } + } else if (isOptIn(options)) { + args.push('OPTIN'); + } else if (isOptOut(options)) { + args.push('OPTOUT'); + } -// if (options?.PREFIX) { -// if (Array.isArray(options.PREFIX)) { -// for (const prefix of options.PREFIX) { -// args.push('PREFIX', prefix); -// } -// } else { -// args.push('PREFIX', options.PREFIX); -// } -// } -// } else if (isOptIn(options)) { -// args.push('OPTIN'); -// } else if (isOptOut(options)) { -// args.push('OPTOUT'); -// } + if (options?.NOLOOP) { + args.push('NOLOOP'); + } + } -// if (options?.NOLOOP) { -// args.push('NOLOOP'); -// } -// } + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -// return args; -// } +function isBroadcast(options?: ClientTrackingOptions): options is BroadcastOptions { + return (options as BroadcastOptions)?.BCAST === true; +} -// function isBroadcast(options?: ClientTrackingOptions): options is BroadcastOptions { -// return (options as BroadcastOptions)?.BCAST === true; -// } +function isOptIn(options?: ClientTrackingOptions): options is OptInOptions { + return (options as OptInOptions)?.OPTIN === true; +} -// function isOptIn(options?: ClientTrackingOptions): options is OptInOptions { -// return (options as OptInOptions)?.OPTIN === true; -// } - -// function isOptOut(options?: ClientTrackingOptions): options is OptOutOptions { -// return (options as OptOutOptions)?.OPTOUT === true; -// } - -// export declare function transformReply(): 'OK' | Buffer; +function isOptOut(options?: ClientTrackingOptions): options is OptOutOptions { + return (options as OptOutOptions)?.OPTOUT === true; +} diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts index 49bffe7612d..beee6649f7d 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts @@ -1,25 +1,26 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_TRACKINGINFO'; +import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO'; +import { RESP_TYPES } from '../RESP/decoder'; describe('CLIENT TRACKINGINFO', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'TRACKINGINFO'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_TRACKINGINFO.transformArguments(), + ['CLIENT', 'TRACKINGINFO'] + ); + }); - testUtils.testWithClient('client.clientTrackingInfo', async client => { - assert.deepEqual( - await client.clientTrackingInfo(), - { - flags: new Set(['off']), - redirect: -1, - prefixes: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientTrackingInfo', async client => { + assert.deepEqual( + await client.clientTrackingInfo(), + { + flags: ['off'], + redirect: -1, + prefixes: [] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts index fd897bb67c6..4c443532f5f 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts @@ -1,28 +1,23 @@ -// import { RedisCommandArguments } from '.'; +import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; -// export function transformArguments(): RedisCommandArguments { -// return ['CLIENT', 'TRACKINGINFO']; -// } +type TrackingInfo = TuplesToMapReply<[ + [BlobStringReply<'flags'>, SetReply], + [BlobStringReply<'redirect'>, NumberReply], + [BlobStringReply<'prefixes'>, ArrayReply] +]>; -// type RawReply = [ -// 'flags', -// Array, -// 'redirect', -// number, -// 'prefixes', -// Array -// ]; - -// interface Reply { -// flags: Set; -// redirect: number; -// prefixes: Array; -// } - -// export function transformReply(reply: RawReply): Reply { -// return { -// flags: new Set(reply[1]), -// redirect: reply[3], -// prefixes: reply[5] -// }; -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['CLIENT', 'TRACKINGINFO']; + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + flags: reply[1], + redirect: reply[3], + prefixes: reply[5] + }), + 3: undefined as unknown as () => TrackingInfo + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts b/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts index 73c731ee87f..1c59c3b82c6 100644 --- a/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts +++ b/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_UNPAUSE'; +import CLIENT_UNPAUSE from './CLIENT_UNPAUSE'; describe('CLIENT UNPAUSE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'UNPAUSE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_UNPAUSE.transformArguments(), + ['CLIENT', 'UNPAUSE'] + ); + }); - testUtils.testWithClient('client.unpause', async client => { - assert.equal( - await client.clientUnpause(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientUnpause', async client => { + assert.equal( + await client.clientUnpause(), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts index c16476de436..4faed754227 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_ADDSLOTS'; +import CLUSTER_ADDSLOTS from './CLUSTER_ADDSLOTS'; describe('CLUSTER ADDSLOTS', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments(0), - ['CLUSTER', 'ADDSLOTS', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + CLUSTER_ADDSLOTS.transformArguments(0), + ['CLUSTER', 'ADDSLOTS', '0'] + ); + }); - it('multiple', () => { - assert.deepEqual( - transformArguments([0, 1]), - ['CLUSTER', 'ADDSLOTS', '0', '1'] - ); - }); + it('multiple', () => { + assert.deepEqual( + CLUSTER_ADDSLOTS.transformArguments([0, 1]), + ['CLUSTER', 'ADDSLOTS', '0', '1'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts index ebd1e3445ff..496d52bd592 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts @@ -1,29 +1,32 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_ADDSLOTSRANGE'; +import testUtils from '../test-utils'; +import CLUSTER_ADDSLOTSRANGE from './CLUSTER_ADDSLOTSRANGE'; describe('CLUSTER ADDSLOTSRANGE', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments({ - start: 0, - end: 1 - }), - ['CLUSTER', 'ADDSLOTSRANGE', '0', '1'] - ); - }); + testUtils.isVersionGreaterThanHook([7, 0]); - it('multiple', () => { - assert.deepEqual( - transformArguments([{ - start: 0, - end: 1 - }, { - start: 2, - end: 3 - }]), - ['CLUSTER', 'ADDSLOTSRANGE', '0', '1', '2', '3'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + CLUSTER_ADDSLOTSRANGE.transformArguments({ + start: 0, + end: 1 + }), + ['CLUSTER', 'ADDSLOTSRANGE', '0', '1'] + ); }); + + it('multiple', () => { + assert.deepEqual( + CLUSTER_ADDSLOTSRANGE.transformArguments([{ + start: 0, + end: 1 + }, { + start: 2, + end: 3 + }]), + ['CLUSTER', 'ADDSLOTSRANGE', '0', '1', '2', '3'] + ); + }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts index edb68b3b3b0..4c064a08127 100644 --- a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts +++ b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_BUMPEPOCH'; +import CLUSTER_BUMPEPOCH from './CLUSTER_BUMPEPOCH'; describe('CLUSTER BUMPEPOCH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'BUMPEPOCH'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_BUMPEPOCH.transformArguments(), + ['CLUSTER', 'BUMPEPOCH'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterBumpEpoch', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterBumpEpoch(), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterBumpEpoch', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterBumpEpoch(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts index 3bbc9f9cb2d..1af795be5e0 100644 --- a/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_KEYSLOT'; +import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; describe('CLUSTER KEYSLOT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['CLUSTER', 'KEYSLOT', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_KEYSLOT.transformArguments('key'), + ['CLUSTER', 'KEYSLOT', 'key'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterKeySlot', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterKeySlot('key'), - 'number' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterKeySlot', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterKeySlot('key'), + 'number' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_MEET.spec.ts b/packages/client/lib/commands/CLUSTER_MEET.spec.ts index 50a5393efa2..283c996cf8a 100644 --- a/packages/client/lib/commands/CLUSTER_MEET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_MEET.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_MEET'; +import CLUSTER_MEET from './CLUSTER_MEET'; describe('CLUSTER MEET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379), - ['CLUSTER', 'MEET', '127.0.0.1', '6379'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_MEET.transformArguments('127.0.0.1', 6379), + ['CLUSTER', 'MEET', '127.0.0.1', '6379'] + ); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_MEET.ts b/packages/client/lib/commands/CLUSTER_MEET.ts index 3e5d343b6f1..949412702d3 100644 --- a/packages/client/lib/commands/CLUSTER_MEET.ts +++ b/packages/client/lib/commands/CLUSTER_MEET.ts @@ -4,5 +4,5 @@ export default { transformArguments(host: string, port: number) { return ['CLUSTER', 'MEET', host, port.toString()]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts b/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts index 926b7dd0a77..bb6335a7117 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_REPLICATE'; +import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; describe('CLUSTER REPLICATE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('0'), - ['CLUSTER', 'REPLICATE', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_REPLICATE.transformArguments('0'), + ['CLUSTER', 'REPLICATE', '0'] + ); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_RESET.spec.ts b/packages/client/lib/commands/CLUSTER_RESET.spec.ts index 340da7457c1..c9186ca7b11 100644 --- a/packages/client/lib/commands/CLUSTER_RESET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_RESET.spec.ts @@ -1,20 +1,22 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_RESET'; +import CLUSTER_RESET from './CLUSTER_RESET'; describe('CLUSTER RESET', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'RESET'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CLUSTER_RESET.transformArguments(), + ['CLUSTER', 'RESET'] + ); + }); - it('with mode', () => { - assert.deepEqual( - transformArguments('HARD'), - ['CLUSTER', 'RESET', 'HARD'] - ); - }); + it('with mode', () => { + assert.deepEqual( + CLUSTER_RESET.transformArguments({ + mode: 'HARD' + }), + ['CLUSTER', 'RESET', 'HARD'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_RESET.ts b/packages/client/lib/commands/CLUSTER_RESET.ts index c6901e045dc..7aaac9d3b0d 100644 --- a/packages/client/lib/commands/CLUSTER_RESET.ts +++ b/packages/client/lib/commands/CLUSTER_RESET.ts @@ -1,11 +1,20 @@ -export function transformArguments(mode?: 'HARD' | 'SOFT'): Array { +import { SimpleStringReply, Command } from '../RESP/types'; + +export interface ClusterResetOptions { + mode?: 'HARD' | 'SOFT'; +} + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(options?: ClusterResetOptions) { const args = ['CLUSTER', 'RESET']; - if (mode) { - args.push(mode); + if (options?.mode) { + args.push(options.mode); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts b/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts index 81ba4aa2509..d49b32a426e 100644 --- a/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_SAVECONFIG'; +import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; describe('CLUSTER SAVECONFIG', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'SAVECONFIG'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_SAVECONFIG.transformArguments(), + ['CLUSTER', 'SAVECONFIG'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterSaveConfig', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - await client.clusterSaveConfig(), - 'OK' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterSaveConfig', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + await client.clusterSaveConfig(), + 'OK' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_SAVECONFIG.ts b/packages/client/lib/commands/CLUSTER_SAVECONFIG.ts index 7e7fb181cc6..489ffd27e48 100644 --- a/packages/client/lib/commands/CLUSTER_SAVECONFIG.ts +++ b/packages/client/lib/commands/CLUSTER_SAVECONFIG.ts @@ -1,5 +1,11 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'SAVECONFIG']; -} +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'SAVECONFIG']; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -export declare function transformReply(): 'OK'; diff --git a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts index dd241574168..b4c26b659c7 100644 --- a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_SET-CONFIG-EPOCH'; +import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH'; describe('CLUSTER SET-CONFIG-EPOCH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(0), - ['CLUSTER', 'SET-CONFIG-EPOCH', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_SET_CONFIG_EPOCH.transformArguments(0), + ['CLUSTER', 'SET-CONFIG-EPOCH', '0'] + ); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.ts b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.ts index c50a6b9d3a5..2a650840c44 100644 --- a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.ts +++ b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.ts @@ -1,5 +1,10 @@ -export function transformArguments(configEpoch: number): Array { - return ['CLUSTER', 'SET-CONFIG-EPOCH', configEpoch.toString()]; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(configEpoch: number) { + return ['CLUSTER', 'SET-CONFIG-EPOCH', configEpoch.toString() ]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts index 0f46aafd13e..cbdbaa89296 100644 --- a/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { ClusterSlotStates, transformArguments } from './CLUSTER_SETSLOT'; +import CLUSTER_SETSLOT, { CLUSTER_SLOT_STATES } from './CLUSTER_SETSLOT'; describe('CLUSTER SETSLOT', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(0, ClusterSlotStates.IMPORTING), - ['CLUSTER', 'SETSLOT', '0', 'IMPORTING'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CLUSTER_SETSLOT.transformArguments(0, CLUSTER_SLOT_STATES.IMPORTING), + ['CLUSTER', 'SETSLOT', '0', 'IMPORTING'] + ); + }); - it('with nodeId', () => { - assert.deepEqual( - transformArguments(0, ClusterSlotStates.IMPORTING, 'nodeId'), - ['CLUSTER', 'SETSLOT', '0', 'IMPORTING', 'nodeId'] - ); - }); + it('with nodeId', () => { + assert.deepEqual( + CLUSTER_SETSLOT.transformArguments(0, CLUSTER_SLOT_STATES.IMPORTING, 'nodeId'), + ['CLUSTER', 'SETSLOT', '0', 'IMPORTING', 'nodeId'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_SETSLOT.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.ts index c01505c71a3..e79cf88b4ae 100644 --- a/packages/client/lib/commands/CLUSTER_SETSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_SETSLOT.ts @@ -1,22 +1,25 @@ -export enum ClusterSlotStates { - IMPORTING = 'IMPORTING', - MIGRATING = 'MIGRATING', - STABLE = 'STABLE', - NODE = 'NODE' -} +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments( - slot: number, - state: ClusterSlotStates, - nodeId?: string -): Array { +export const CLUSTER_SLOT_STATES = { + IMPORTING: 'IMPORTING', + MIGRATING: 'MIGRATING', + STABLE: 'STABLE', + NODE: 'NODE' +} as const; + +export type ClusterSlotStates = typeof CLUSTER_SLOT_STATES[keyof typeof CLUSTER_SLOT_STATES]; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(slot: number, state: ClusterSlotStates, nodeId?: string) { const args = ['CLUSTER', 'SETSLOT', slot.toString(), state]; if (nodeId) { - args.push(nodeId); + args.push(nodeId); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts index 6efbfe13ce1..4650fe83b2d 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts @@ -1,76 +1,30 @@ import { strict as assert } from 'assert'; -import { transformArguments, transformReply } from './CLUSTER_SLOTS'; +import testUtils, { GLOBAL } from '../test-utils'; +import CLUSTER_SLOTS from './CLUSTER_SLOTS'; describe('CLUSTER SLOTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'SLOTS'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_SLOTS.transformArguments(), + ['CLUSTER', 'SLOTS'] + ); + }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - [ - 0, - 5460, - ['127.0.0.1', 30001, '09dbe9720cda62f7865eabc5fd8857c5d2678366'], - ['127.0.0.1', 30004, '821d8ca00d7ccf931ed3ffc7e3db0599d2271abf'] - ], - [ - 5461, - 10922, - ['127.0.0.1', 30002, 'c9d93d9f2c0c524ff34cc11838c2003d8c29e013'], - ['127.0.0.1', 30005, 'faadb3eb99009de4ab72ad6b6ed87634c7ee410f'] - ], - [ - 10923, - 16383, - ['127.0.0.1', 30003, '044ec91f325b7595e76dbcb18cc688b6a5b434a1'], - ['127.0.0.1', 30006, '58e6e48d41228013e5d9c1c37c5060693925e97e'] - ] - ]), - [{ - from: 0, - to: 5460, - master: { - ip: '127.0.0.1', - port: 30001, - id: '09dbe9720cda62f7865eabc5fd8857c5d2678366' - }, - replicas: [{ - ip: '127.0.0.1', - port: 30004, - id: '821d8ca00d7ccf931ed3ffc7e3db0599d2271abf' - }] - }, { - from: 5461, - to: 10922, - master: { - ip: '127.0.0.1', - port: 30002, - id: 'c9d93d9f2c0c524ff34cc11838c2003d8c29e013' - }, - replicas: [{ - ip: '127.0.0.1', - port: 30005, - id: 'faadb3eb99009de4ab72ad6b6ed87634c7ee410f' - }] - }, { - from: 10923, - to: 16383, - master: { - ip: '127.0.0.1', - port: 30003, - id: '044ec91f325b7595e76dbcb18cc688b6a5b434a1' - }, - replicas: [{ - ip: '127.0.0.1', - port: 30006, - id: '58e6e48d41228013e5d9c1c37c5060693925e97e' - }] - }] - ); - }); + testUtils.testWithCluster('clusterNode.clusterSlots', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]), + slots = await client.clusterSlots(); + assert.ok(Array.isArray(slots)); + for (const { from, to, master, replicas } of slots) { + assert.equal(typeof from, 'number'); + assert.equal(typeof to, 'number'); + assert.equal(typeof master.host, 'string'); + assert.equal(typeof master.port, 'number'); + assert.equal(typeof master.id, 'string'); + for (const replica of replicas) { + assert.equal(typeof replica.host, 'string'); + assert.equal(typeof replica.port, 'number'); + assert.equal(typeof replica.id, 'string'); + } + } + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts index 546bc4a3636..09f46b32db2 100644 --- a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts @@ -30,7 +30,9 @@ describe('FUNCTION RESTORE', () => { await client.withTypeMapping({ [RESP_TYPES.BLOB_STRING]: Buffer }).functionDump(), - 'FLUSH' + { + mode: 'REPLACE' + } ), 'OK' ); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 81cf34b5250..aca729b4e17 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -36,11 +36,33 @@ import CLIENT_LIST from './CLIENT_LIST'; import CLIENT_NO_EVICT from './CLIENT_NO-EVICT'; import CLIENT_PAUSE from './CLIENT_PAUSE'; import CLIENT_SETNAME from './CLIENT_SETNAME'; +import CLIENT_TRACKING from './CLIENT_TRACKING'; +import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO'; +import CLIENT_UNPAUSE from './CLIENT_UNPAUSE'; import CLUSTER_ADDSLOTS from './CLUSTER_ADDSLOTS'; -import CLUSTER_SLOTS from './CLUSTER_SLOTS'; +import CLUSTER_ADDSLOTSRANGE from './CLUSTER_ADDSLOTSRANGE'; +import CLUSTER_BUMPEPOCH from './CLUSTER_BUMPEPOCH'; +import CLUSTER_COUNT_FAILURE_REPORTS from './CLUSTER_COUNT-FAILURE-REPORTS'; +import CLUSTER_COUNTKEYSINSLOT from './CLUSTER_COUNTKEYSINSLOT'; +import CLUSTER_DELSLOTS from './CLUSTER_DELSLOTS'; +import CLUSTER_DELSLOTSRANGE from './CLUSTER_DELSLOTSRANGE'; +import CLUSTER_FAILOVER from './CLUSTER_FAILOVER'; +import CLUSTER_FLUSHSLOTS from './CLUSTER_FLUSHSLOTS'; +import CLUSTER_FORGET from './CLUSTER_FORGET'; +import CLUSTER_GETKEYSINSLOT from './CLUSTER_GETKEYSINSLOT'; +// import CLUSTER_INFO from './CLUSTER_INFO'; +import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; +// import CLUSTER_LINKS from './CLUSTER_LINKS'; import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; +// import CLUSTER_NODES from './CLUSTER_NODES'; +// import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; +import CLUSTER_RESET from './CLUSTER_RESET'; +import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; +import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH'; +import CLUSTER_SETSLOT from './CLUSTER_SETSLOT'; +import CLUSTER_SLOTS from './CLUSTER_SLOTS'; import COPY from './COPY'; import DBSIZE from './DBSIZE'; import DECR from './DECR'; @@ -90,7 +112,7 @@ import FUNCTION_KILL from './FUNCTION_KILL'; import FUNCTION_LIST_WITHCODE from './FUNCTION_LIST_WITHCODE'; import FUNCTION_LIST from './FUNCTION_LIST'; import FUNCTION_LOAD from './FUNCTION_LOAD'; -// import FUNCTION_RESTORE from './FUNCTION_RESTORE'; +import FUNCTION_RESTORE from './FUNCTION_RESTORE'; // import FUNCTION_STATS from './FUNCTION_STATS'; import HDEL from './HDEL'; import HELLO from './HELLO'; @@ -297,11 +319,33 @@ type CLIENT_LIST = typeof import('./CLIENT_LIST').default; type CLIENT_NO_EVICT = typeof import('./CLIENT_NO-EVICT').default; type CLIENT_PAUSE = typeof import('./CLIENT_PAUSE').default; type CLIENT_SETNAME = typeof import('./CLIENT_SETNAME').default; +type CLIENT_TRACKING = typeof import('./CLIENT_TRACKING').default; +type CLIENT_TRACKINGINFO = typeof import('./CLIENT_TRACKINGINFO').default; +type CLIENT_UNPAUSE = typeof import('./CLIENT_UNPAUSE').default; type CLUSTER_ADDSLOTS = typeof import('./CLUSTER_ADDSLOTS').default; -type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; +type CLUSTER_ADDSLOTSRANGE = typeof import('./CLUSTER_ADDSLOTSRANGE').default; +type CLUSTER_BUMPEPOCH = typeof import('./CLUSTER_BUMPEPOCH').default; +type CLUSTER_COUNT_FAILURE_REPORTS = typeof import('./CLUSTER_COUNT-FAILURE-REPORTS').default; +type CLUSTER_COUNTKEYSINSLOT = typeof import('./CLUSTER_COUNTKEYSINSLOT').default; +type CLUSTER_DELSLOTS = typeof import('./CLUSTER_DELSLOTS').default; +type CLUSTER_DELSLOTSRANGE = typeof import('./CLUSTER_DELSLOTSRANGE').default; +type CLUSTER_FAILOVER = typeof import('./CLUSTER_FAILOVER').default; +type CLUSTER_FLUSHSLOTS = typeof import('./CLUSTER_FLUSHSLOTS').default; +type CLUSTER_FORGET = typeof import('./CLUSTER_FORGET').default; +type CLUSTER_GETKEYSINSLOT = typeof import('./CLUSTER_GETKEYSINSLOT').default; +// type CLUSTER_INFO = typeof import('./CLUSTER_INFO').default; +type CLUSTER_KEYSLOT = typeof import('./CLUSTER_KEYSLOT').default; +// type CLUSTER_LINKS = typeof import('./CLUSTER_LINKS').default; type CLUSTER_MEET = typeof import('./CLUSTER_MEET').default; type CLUSTER_MYID = typeof import('./CLUSTER_MYID').default; +// type CLUSTER_NODES = typeof import('./CLUSTER_NODES').default; +// type CLUSTER_REPLICAS = typeof import('./CLUSTER_REPLICAS').default; type CLUSTER_REPLICATE = typeof import('./CLUSTER_REPLICATE').default; +type CLUSTER_RESET = typeof import('./CLUSTER_RESET').default; +type CLUSTER_SAVECONFIG = typeof import('./CLUSTER_SAVECONFIG').default; +type CLUSTER_SET_CONFIG_EPOCH = typeof import('./CLUSTER_SET-CONFIG-EPOCH').default; +type CLUSTER_SETSLOT = typeof import('./CLUSTER_SETSLOT').default; +type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; type COPY = typeof import('./COPY').default; type DBSIZE = typeof DBSIZE; type DECR = typeof import('./DECR').default; @@ -351,7 +395,7 @@ type FUNCTION_KILL = typeof import('./FUNCTION_KILL').default; type FUNCTION_LIST_WITHCODE = typeof import('./FUNCTION_LIST_WITHCODE').default; type FUNCTION_LIST = typeof import('./FUNCTION_LIST').default; type FUNCTION_LOAD = typeof import('./FUNCTION_LOAD').default; -// type FUNCTION_RESTORE = typeof import('./FUNCTION_RESTORE').default; +type FUNCTION_RESTORE = typeof import('./FUNCTION_RESTORE').default; // type FUNCTION_STATS = typeof import('./FUNCTION_STATS').default; type HDEL = typeof import('./HDEL').default; type HELLO = typeof import('./HELLO').default; @@ -596,16 +640,60 @@ type Commands = { clientPause: CLIENT_PAUSE; CLIENT_SETNAME: CLIENT_SETNAME; clientSetName: CLIENT_SETNAME; + CLIENT_TRACKING: CLIENT_TRACKING; + clientTracking: CLIENT_TRACKING; + CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO; + clientTrackingInfo: CLIENT_TRACKINGINFO; + CLIENT_UNPAUSE: CLIENT_UNPAUSE; + clientUnpause: CLIENT_UNPAUSE; CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS; clusterAddSlots: CLUSTER_ADDSLOTS; - CLUSTER_SLOTS: CLUSTER_SLOTS; - clusterSlots: CLUSTER_SLOTS; + CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE; + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE; + CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH; + clusterBumpEpoch: CLUSTER_BUMPEPOCH; + 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS; + clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS; + CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT; + clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT; + CLUSTER_DELSLOTS: CLUSTER_DELSLOTS; + clusterDelSlots: CLUSTER_DELSLOTS; + CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE; + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE; + CLUSTER_FAILOVER: CLUSTER_FAILOVER; + clusterFailover: CLUSTER_FAILOVER; + CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS; + clusterFlushSlots: CLUSTER_FLUSHSLOTS; + CLUSTER_FORGET: CLUSTER_FORGET; + clusterForget: CLUSTER_FORGET; + CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT; + clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT; + // CLUSTER_INFO: CLUSTER_INFO; + // clusterInfo: CLUSTER_INFO; + CLUSTER_KEYSLOT: CLUSTER_KEYSLOT; + clusterKeySlot: CLUSTER_KEYSLOT; + // CLUSTER_LINKS: CLUSTER_LINKS; + // clusterLinks: CLUSTER_LINKS; CLUSTER_MEET: CLUSTER_MEET; clusterMeet: CLUSTER_MEET; CLUSTER_MYID: CLUSTER_MYID; clusterMyId: CLUSTER_MYID; + // CLUSTER_NODES: CLUSTER_NODES; + // clusterNodes: CLUSTER_NODES; + // CLUSTER_REPLICAS: CLUSTER_REPLICAS; + // clusterReplicas: CLUSTER_REPLICAS; CLUSTER_REPLICATE: CLUSTER_REPLICATE; clusterReplicate: CLUSTER_REPLICATE; + CLUSTER_RESET: CLUSTER_RESET; + clusterReset: CLUSTER_RESET; + CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG; + clusterSaveConfig: CLUSTER_SAVECONFIG; + 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH; + clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH; + CLUSTER_SETSLOT: CLUSTER_SETSLOT; + clusterSetSlot: CLUSTER_SETSLOT; + CLUSTER_SLOTS: CLUSTER_SLOTS; + clusterSlots: CLUSTER_SLOTS; COPY: COPY; copy: COPY; DBSIZE: DBSIZE; @@ -658,8 +746,8 @@ type Commands = { functionList: FUNCTION_LIST; FUNCTION_LOAD: FUNCTION_LOAD; functionLoad: FUNCTION_LOAD; - // FUNCTION_RESTORE: FUNCTION_RESTORE; - // functionRestore: FUNCTION_RESTORE; + FUNCTION_RESTORE: FUNCTION_RESTORE; + functionRestore: FUNCTION_RESTORE; // FUNCTION_STATS: FUNCTION_STATS; // functionStats: FUNCTION_STATS; GEOADD: GEOADD; @@ -1119,16 +1207,60 @@ export default { clientPause: CLIENT_PAUSE, CLIENT_SETNAME, clientSetName: CLIENT_SETNAME, + CLIENT_TRACKING, + clientTracking: CLIENT_TRACKING, + CLIENT_TRACKINGINFO, + clientTrackingInfo: CLIENT_TRACKINGINFO, + CLIENT_UNPAUSE, + clientUnpause: CLIENT_UNPAUSE, CLUSTER_ADDSLOTS, clusterAddSlots: CLUSTER_ADDSLOTS, - CLUSTER_SLOTS, - clusterSlots: CLUSTER_SLOTS, + CLUSTER_ADDSLOTSRANGE, + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE, + CLUSTER_BUMPEPOCH, + clusterBumpEpoch: CLUSTER_BUMPEPOCH, + 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS, + clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS, + CLUSTER_COUNTKEYSINSLOT, + clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT, + CLUSTER_DELSLOTS, + clusterDelSlots: CLUSTER_DELSLOTS, + CLUSTER_DELSLOTSRANGE, + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE, + CLUSTER_FAILOVER, + clusterFailover: CLUSTER_FAILOVER, + CLUSTER_FLUSHSLOTS, + clusterFlushSlots: CLUSTER_FLUSHSLOTS, + CLUSTER_FORGET, + clusterForget: CLUSTER_FORGET, + CLUSTER_GETKEYSINSLOT, + clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT, + // CLUSTER_INFO, + // clusterInfo: CLUSTER_INFO, + CLUSTER_KEYSLOT, + clusterKeySlot: CLUSTER_KEYSLOT, + // CLUSTER_LINKS, + // clusterLinks: CLUSTER_LINKS, CLUSTER_MEET, clusterMeet: CLUSTER_MEET, CLUSTER_MYID, clusterMyId: CLUSTER_MYID, + // CLUSTER_NODES, + // clusterNodes: CLUSTER_NODES, + // CLUSTER_REPLICAS, + // clusterReplicas: CLUSTER_REPLICAS, CLUSTER_REPLICATE, clusterReplicate: CLUSTER_REPLICATE, + CLUSTER_RESET, + clusterReset: CLUSTER_RESET, + CLUSTER_SAVECONFIG, + clusterSaveConfig: CLUSTER_SAVECONFIG, + 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH, + clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH, + CLUSTER_SETSLOT, + clusterSetSlot: CLUSTER_SETSLOT, + CLUSTER_SLOTS, + clusterSlots: CLUSTER_SLOTS, COPY, copy: COPY, DBSIZE, @@ -1563,4 +1695,4 @@ export default { zUnion: ZUNION, ZUNIONSTORE, zUnionStore: ZUNIONSTORE -} as const satisfies Record as Commands; +} satisfies Record as Commands; diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts index fa40d0a5482..4aca735c928 100644 --- a/packages/client/lib/test-utils.ts +++ b/packages/client/lib/test-utils.ts @@ -4,7 +4,8 @@ import { setTimeout } from 'timers/promises'; const utils = new TestUtils({ dockerImageName: 'redis', - dockerImageVersionArgument: 'redis-version' + dockerImageVersionArgument: 'redis-version', + defaultDockerVersion: '7.2-rc' }); export default utils; diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index f424535297b..7ccc2a2d488 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -3,12 +3,15 @@ import { RedisFunctions, RedisScripts, RespVersions, + TypeMapping, + CommandPolicies, createClient, RedisClientOptions, RedisClientType, createCluster, RedisClusterOptions, - RedisClusterType + RedisClusterType, + RESP_TYPES } from '@redis/client/index'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; @@ -28,10 +31,11 @@ interface ClientTestOptions< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping > extends CommonTestOptions { serverArguments: Array; - clientOptions?: Partial>; + clientOptions?: Partial>; disableClientSetup?: boolean; } @@ -39,10 +43,12 @@ interface ClusterTestOptions< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + POLICIES extends CommandPolicies > extends CommonTestOptions { serverArguments: Array; - clusterConfiguration?: Partial>; + clusterConfiguration?: Partial>; numberOfMasters?: number; numberOfReplicas?: number; } @@ -51,10 +57,12 @@ interface AllTestOptions< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + POLICIES extends CommandPolicies > { - client: ClientTestOptions; - cluster: ClusterTestOptions; + client: ClientTestOptions; + cluster: ClusterTestOptions; } interface Version { @@ -135,11 +143,12 @@ export default class TestUtils { M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} >( title: string, - fn: (client: RedisClientType) => unknown, - options: ClientTestOptions + fn: (client: RedisClientType) => unknown, + options: ClientTestOptions ): void { let dockerPromise: ReturnType; if (this.isVersionGreaterThan(options.minimumDockerVersion)) { @@ -187,8 +196,10 @@ export default class TestUtils { M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions - >(cluster: RedisClusterType): Promise { + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + POLICIES extends CommandPolicies + >(cluster: RedisClusterType): Promise { return Promise.all( cluster.masters.map(async ({ client }) => { if (client) { @@ -202,11 +213,13 @@ export default class TestUtils { M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, + POLICIES extends CommandPolicies = {} >( title: string, - fn: (cluster: RedisClusterType) => unknown, - options: ClusterTestOptions + fn: (cluster: RedisClusterType) => unknown, + options: ClusterTestOptions ): void { let dockersPromise: ReturnType; if (this.isVersionGreaterThan(options.minimumDockerVersion)) { @@ -225,7 +238,7 @@ export default class TestUtils { it(title, async function () { if (!dockersPromise) return this.skip(); - + const dockers = await dockersPromise, cluster = createCluster({ rootNodes: dockers.map(({ port }) => ({ @@ -253,11 +266,13 @@ export default class TestUtils { M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2 + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, + POLICIES extends CommandPolicies = {} >( title: string, - fn: (client: RedisClientType | RedisClusterType) => unknown, - options: AllTestOptions + fn: (client: RedisClientType | RedisClusterType) => unknown, + options: AllTestOptions ) { this.testWithClient(`client.${title}`, fn, options.client); this.testWithCluster(`cluster.${title}`, fn, options.cluster); From b46f08228ce7ca9975121d842a4651e38e096611 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 21 Jun 2023 19:09:45 -0400 Subject: [PATCH 139/325] wip --- docs/v4-to-v5.md | 3 + packages/client/lib/commands/ASKING.spec.ts | 14 +-- .../client/lib/commands/BGREWRITEAOF.spec.ts | 22 ++-- packages/client/lib/commands/BGSAVE.spec.ts | 41 +++--- packages/client/lib/commands/BGSAVE.ts | 14 ++- .../CLUSTER_COUNT-FAILURE-REPORTS.spec.ts | 31 +++-- .../commands/CLUSTER_COUNTKEYSINSLOT.spec.ts | 28 ++--- .../lib/commands/CLUSTER_COUNTKEYSINSLOT.ts | 2 +- .../lib/commands/CLUSTER_DELSLOTS.spec.ts | 28 ++--- .../commands/CLUSTER_DELSLOTSRANGE.spec.ts | 46 +++---- .../lib/commands/CLUSTER_FAILOVER.spec.ts | 32 ++--- .../client/lib/commands/CLUSTER_FAILOVER.ts | 12 +- .../lib/commands/CLUSTER_FLUSHSLOTS.spec.ts | 14 +-- .../lib/commands/CLUSTER_FORGET.spec.ts | 14 +-- .../commands/CLUSTER_GETKEYSINSLOT.spec.ts | 34 ++--- .../client/lib/commands/CLUSTER_KEYSLOT.ts | 2 + .../client/lib/commands/CLUSTER_LINKS.spec.ts | 42 +++---- packages/client/lib/commands/CLUSTER_LINKS.ts | 63 ++++------ packages/client/lib/commands/CLUSTER_MEET.ts | 2 + packages/client/lib/commands/CLUSTER_MYID.ts | 2 + .../client/lib/commands/CLUSTER_REPLICATE.ts | 2 + .../client/lib/commands/CLUSTER_SETSLOT.ts | 8 +- .../client/lib/commands/CLUSTER_SLOTS.spec.ts | 2 +- .../client/lib/commands/COMMAND_COUNT.spec.ts | 34 ++--- packages/client/lib/commands/COMMAND_COUNT.ts | 17 +-- .../lib/commands/COMMAND_GETKEYS.spec.ts | 34 ++--- .../client/lib/commands/COMMAND_GETKEYS.ts | 17 +-- .../client/lib/commands/CONFIG_GET.spec.ts | 30 ++++- packages/client/lib/commands/CONFIG_GET.ts | 13 +- .../client/lib/commands/CONFIG_RESETSTAT.ts | 2 + .../client/lib/commands/CONFIG_REWRITE.ts | 2 + .../client/lib/commands/CONFIG_SET.spec.ts | 8 ++ packages/client/lib/commands/CONFIG_SET.ts | 2 + packages/client/lib/commands/FLUSHALL.ts | 4 +- packages/client/lib/commands/FLUSHDB.ts | 4 +- .../client/lib/commands/FUNCTION_FLUSH.ts | 4 +- .../lib/commands/LATENCY_DOCTOR.spec.ts | 30 ++--- .../client/lib/commands/LATENCY_DOCTOR.ts | 13 +- .../client/lib/commands/LATENCY_GRAPH.spec.ts | 42 +++---- packages/client/lib/commands/LATENCY_GRAPH.ts | 50 ++++---- .../lib/commands/LATENCY_LATEST.spec.ts | 50 ++++---- .../client/lib/commands/LATENCY_LATEST.ts | 24 ++-- .../client/lib/commands/MEMORY_STATS.spec.ts | 82 ++++++------ packages/client/lib/commands/MEMORY_STATS.ts | 98 +++++++-------- packages/client/lib/commands/ROLE.spec.ts | 118 +++++++++--------- packages/client/lib/commands/ROLE.ts | 10 +- packages/client/lib/commands/SHUTDOWN.spec.ts | 70 +++++++---- packages/client/lib/commands/SHUTDOWN.ts | 40 ++++-- packages/client/lib/commands/SWAPDB.spec.ts | 34 ++--- packages/client/lib/commands/SWAPDB.ts | 14 ++- packages/client/lib/commands/TIME.spec.ts | 33 ++--- packages/client/lib/commands/TIME.ts | 26 ++-- packages/client/lib/commands/index.ts | 88 ++++++++++--- 53 files changed, 826 insertions(+), 625 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index fde8e283797..8026bf28d33 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -165,6 +165,9 @@ Some command arguments/replies have changed to align more closely to data types - `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] - `FUNCTION RESTORE`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] +- `TIME`: `Date` -> `[unixTimestamp: string, microseconds: string]` [^enum-to-constants]: TODO diff --git a/packages/client/lib/commands/ASKING.spec.ts b/packages/client/lib/commands/ASKING.spec.ts index 3da2015199e..661a5aa7c1d 100644 --- a/packages/client/lib/commands/ASKING.spec.ts +++ b/packages/client/lib/commands/ASKING.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ASKING'; +import ASKING from './ASKING'; describe('ASKING', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ASKING'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ASKING.transformArguments(), + ['ASKING'] + ); + }); }); diff --git a/packages/client/lib/commands/BGREWRITEAOF.spec.ts b/packages/client/lib/commands/BGREWRITEAOF.spec.ts index d0e150e155b..b29e90634cb 100644 --- a/packages/client/lib/commands/BGREWRITEAOF.spec.ts +++ b/packages/client/lib/commands/BGREWRITEAOF.spec.ts @@ -1,11 +1,19 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './BGREWRITEAOF'; +import testUtils, { GLOBAL } from '../test-utils'; +import BGREWRITEAOF from './BGREWRITEAOF'; describe('BGREWRITEAOF', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['BGREWRITEAOF'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BGREWRITEAOF.transformArguments(), + ['BGREWRITEAOF'] + ); + }); + + testUtils.testWithClient('client.bgRewriteAof', async client => { + assert.equal( + typeof await client.bgRewriteAof(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/BGSAVE.spec.ts b/packages/client/lib/commands/BGSAVE.spec.ts index 8e4de5eef5b..b8e82e21278 100644 --- a/packages/client/lib/commands/BGSAVE.spec.ts +++ b/packages/client/lib/commands/BGSAVE.spec.ts @@ -1,23 +1,30 @@ import { strict as assert } from 'assert'; -import { describe } from 'mocha'; -import { transformArguments } from './BGSAVE'; +import testUtils, { GLOBAL } from '../test-utils'; +import BGSAVE from './BGSAVE'; describe('BGSAVE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['BGSAVE'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + BGSAVE.transformArguments(), + ['BGSAVE'] + ); + }); - it('with SCHEDULE', () => { - assert.deepEqual( - transformArguments({ - SCHEDULE: true - }), - ['BGSAVE', 'SCHEDULE'] - ); - }); + it('with SCHEDULE', () => { + assert.deepEqual( + BGSAVE.transformArguments({ + SCHEDULE: true + }), + ['BGSAVE', 'SCHEDULE'] + ); }); + }); + + testUtils.testWithClient('client.bgSave', async client => { + assert.equal( + typeof await client.bgSave(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/BGSAVE.ts b/packages/client/lib/commands/BGSAVE.ts index 1cc60cb5dae..dc0f5056708 100644 --- a/packages/client/lib/commands/BGSAVE.ts +++ b/packages/client/lib/commands/BGSAVE.ts @@ -1,10 +1,20 @@ import { SimpleStringReply, Command } from '../RESP/types'; +export interface BgSaveOptions { + SCHEDULE?: boolean; +} + export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments() { - return ['BGSAVE']; + transformArguments(options?: BgSaveOptions) { + const args = ['BGSAVE']; + + if (options?.SCHEDULE) { + args.push('SCHEDULE'); + } + + return args; }, transformReply: undefined as unknown as () => SimpleStringReply } as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts index 558110d0a28..68b3cde620b 100644 --- a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts @@ -1,22 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_COUNT-FAILURE-REPORTS'; +import CLUSTER_COUNT_FAILURE_REPORTS from './CLUSTER_COUNT-FAILURE-REPORTS'; describe('CLUSTER COUNT-FAILURE-REPORTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('0'), - ['CLUSTER', 'COUNT-FAILURE-REPORTS', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_COUNT_FAILURE_REPORTS.transformArguments('0'), + ['CLUSTER', 'COUNT-FAILURE-REPORTS', '0'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterCountFailureReports', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterCountFailureReports( - await client.clusterMyId() - ), - 'number' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterCountFailureReports', async cluster => { + const [master] = cluster.masters, + client = await cluster.nodeClient(master); + assert.equal( + typeof await client.clusterCountFailureReports(master.id), + 'number' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts index 27ecbcfffa3..2faa95c0804 100644 --- a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_COUNTKEYSINSLOT'; +import CLUSTER_COUNTKEYSINSLOT from './CLUSTER_COUNTKEYSINSLOT'; describe('CLUSTER COUNTKEYSINSLOT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(0), - ['CLUSTER', 'COUNTKEYSINSLOT', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_COUNTKEYSINSLOT.transformArguments(0), + ['CLUSTER', 'COUNTKEYSINSLOT', '0'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterCountKeysInSlot', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterCountKeysInSlot(0), - 'number' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterCountKeysInSlot', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterCountKeysInSlot(0), + 'number' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts index 2892c2aae2d..61f46230e89 100644 --- a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.ts @@ -4,7 +4,7 @@ export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments(slot: number) { - return ['CLUSTER', 'COUNT-FAILURE-REPORTS', slot.toString()]; + return ['CLUSTER', 'COUNTKEYSINSLOT', slot.toString()]; }, transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts index 85d13f4ed3d..85a188c31e0 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_DELSLOTS'; +import CLUSTER_DELSLOTS from './CLUSTER_DELSLOTS'; describe('CLUSTER DELSLOTS', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments(0), - ['CLUSTER', 'DELSLOTS', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + CLUSTER_DELSLOTS.transformArguments(0), + ['CLUSTER', 'DELSLOTS', '0'] + ); + }); - it('multiple', () => { - assert.deepEqual( - transformArguments([0, 1]), - ['CLUSTER', 'DELSLOTS', '0', '1'] - ); - }); + it('multiple', () => { + assert.deepEqual( + CLUSTER_DELSLOTS.transformArguments([0, 1]), + ['CLUSTER', 'DELSLOTS', '0', '1'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts index 8fd50d01a54..38ee60b9178 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts @@ -1,29 +1,29 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_DELSLOTSRANGE'; +import CLUSTER_DELSLOTSRANGE from './CLUSTER_DELSLOTSRANGE'; describe('CLUSTER DELSLOTSRANGE', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments({ - start: 0, - end: 1 - }), - ['CLUSTER', 'DELSLOTSRANGE', '0', '1'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + CLUSTER_DELSLOTSRANGE.transformArguments({ + start: 0, + end: 1 + }), + ['CLUSTER', 'DELSLOTSRANGE', '0', '1'] + ); + }); - it('multiple', () => { - assert.deepEqual( - transformArguments([{ - start: 0, - end: 1 - }, { - start: 2, - end: 3 - }]), - ['CLUSTER', 'DELSLOTSRANGE', '0', '1', '2', '3'] - ); - }); + it('multiple', () => { + assert.deepEqual( + CLUSTER_DELSLOTSRANGE.transformArguments([{ + start: 0, + end: 1 + }, { + start: 2, + end: 3 + }]), + ['CLUSTER', 'DELSLOTSRANGE', '0', '1', '2', '3'] + ); }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts b/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts index 578ff56b9cd..542e529f46b 100644 --- a/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts @@ -1,20 +1,22 @@ import { strict as assert } from 'assert'; -import { FailoverModes, transformArguments } from './CLUSTER_FAILOVER'; +import CLUSTER_FAILOVER, { FAILOVER_MODES } from './CLUSTER_FAILOVER'; describe('CLUSTER FAILOVER', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'FAILOVER'] - ); - }); - - it('with mode', () => { - assert.deepEqual( - transformArguments(FailoverModes.FORCE), - ['CLUSTER', 'FAILOVER', 'FORCE'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CLUSTER_FAILOVER.transformArguments(), + ['CLUSTER', 'FAILOVER'] + ); }); + + it('with mode', () => { + assert.deepEqual( + CLUSTER_FAILOVER.transformArguments({ + mode: FAILOVER_MODES.FORCE + }), + ['CLUSTER', 'FAILOVER', 'FORCE'] + ); + }); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_FAILOVER.ts b/packages/client/lib/commands/CLUSTER_FAILOVER.ts index 857e11f7b1f..63f79a246ba 100644 --- a/packages/client/lib/commands/CLUSTER_FAILOVER.ts +++ b/packages/client/lib/commands/CLUSTER_FAILOVER.ts @@ -5,16 +5,20 @@ export const FAILOVER_MODES = { TAKEOVER: 'TAKEOVER' } as const; -export type FailoverModes = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES]; +export type FailoverMode = typeof FAILOVER_MODES[keyof typeof FAILOVER_MODES]; + +export interface ClusterFailoverOptions { + mode?: FailoverMode; +} export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(mode?: FailoverModes) { + transformArguments(options?: ClusterFailoverOptions) { const args = ['CLUSTER', 'FAILOVER']; - if (mode) { - args.push(mode); + if (options?.mode) { + args.push(options.mode); } return args; diff --git a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts index f91a9a70cfd..7ea2c33ccaf 100644 --- a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_FLUSHSLOTS'; +import CLUSTER_FLUSHSLOTS from './CLUSTER_FLUSHSLOTS'; describe('CLUSTER FLUSHSLOTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'FLUSHSLOTS'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_FLUSHSLOTS.transformArguments(), + ['CLUSTER', 'FLUSHSLOTS'] + ); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_FORGET.spec.ts b/packages/client/lib/commands/CLUSTER_FORGET.spec.ts index cadcdb678f3..5d144ac1091 100644 --- a/packages/client/lib/commands/CLUSTER_FORGET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FORGET.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_FORGET'; +import CLUSTER_FORGET from './CLUSTER_FORGET'; describe('CLUSTER FORGET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('0'), - ['CLUSTER', 'FORGET', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_FORGET.transformArguments('0'), + ['CLUSTER', 'FORGET', '0'] + ); + }); }); diff --git a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts index 957b7de20cb..cba7a384eed 100644 --- a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts @@ -1,21 +1,25 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_GETKEYSINSLOT'; +import CLUSTER_GETKEYSINSLOT from './CLUSTER_GETKEYSINSLOT'; describe('CLUSTER GETKEYSINSLOT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(0, 10), - ['CLUSTER', 'GETKEYSINSLOT', '0', '10'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_GETKEYSINSLOT.transformArguments(0, 10), + ['CLUSTER', 'GETKEYSINSLOT', '0', '10'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterGetKeysInSlot', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]), - reply = await client.clusterGetKeysInSlot(0, 1); - assert.ok(Array.isArray(reply)); - for (const item of reply) { - assert.equal(typeof item, 'string'); - } - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterGetKeysInSlot', async cluster => { + const slot = 12539, // "key" slot + client = await cluster.nodeClient(cluster.slots[slot].master), + [, reply] = await Promise.all([ + client.set('key', 'value'), + client.clusterGetKeysInSlot(slot, 1), + ]) + assert.ok(Array.isArray(reply)); + for (const item of reply) { + assert.equal(typeof item, 'string'); + } + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_KEYSLOT.ts b/packages/client/lib/commands/CLUSTER_KEYSLOT.ts index fc68287eae5..81e84430116 100644 --- a/packages/client/lib/commands/CLUSTER_KEYSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_KEYSLOT.ts @@ -1,6 +1,8 @@ import { Command, NumberReply, RedisArgument } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(key: RedisArgument) { return ['CLUSTER', 'KEYSLOT', key]; }, diff --git a/packages/client/lib/commands/CLUSTER_LINKS.spec.ts b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts index 982973e8ea5..c1490663935 100644 --- a/packages/client/lib/commands/CLUSTER_LINKS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_LINKS'; +import CLUSTER_LINKS from './CLUSTER_LINKS'; describe('CLUSTER LINKS', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'LINKS'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_LINKS.transformArguments(), + ['CLUSTER', 'LINKS'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterLinks', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]), - links = await client.clusterLinks(); - assert.ok(Array.isArray(links)); - for (const link of links) { - assert.equal(typeof link.direction, 'string'); - assert.equal(typeof link.node, 'string'); - assert.equal(typeof link.createTime, 'number'); - assert.equal(typeof link.events, 'string'); - assert.equal(typeof link.sendBufferAllocated, 'number'); - assert.equal(typeof link.sendBufferUsed, 'number'); - } - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterLinks', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]), + links = await client.clusterLinks(); + assert.ok(Array.isArray(links)); + for (const link of links) { + assert.equal(typeof link.direction, 'string'); + assert.equal(typeof link.node, 'string'); + assert.equal(typeof link['create-time'], 'number'); + assert.equal(typeof link.events, 'string'); + assert.equal(typeof link['send-buffer-allocated'], 'number'); + assert.equal(typeof link['send-buffer-used'], 'number'); + } + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_LINKS.ts b/packages/client/lib/commands/CLUSTER_LINKS.ts index 9a5608c102f..486553f9d07 100644 --- a/packages/client/lib/commands/CLUSTER_LINKS.ts +++ b/packages/client/lib/commands/CLUSTER_LINKS.ts @@ -1,38 +1,29 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'LINKS']; -} - -type ClusterLinksRawReply = Array<[ - 'direction', - string, - 'node', - string, - 'createTime', - number, - 'events', - string, - 'send-buffer-allocated', - number, - 'send-buffer-used', - number -]>; +import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types'; -type ClusterLinksReply = Array<{ - direction: string; - node: string; - createTime: number; - events: string; - sendBufferAllocated: number; - sendBufferUsed: number; -}>; +type ClusterLinksReply = ArrayReply, BlobStringReply], + [BlobStringReply<'node'>, BlobStringReply], + [BlobStringReply<'create-time'>, NumberReply], + [BlobStringReply<'events'>, BlobStringReply], + [BlobStringReply<'send-buffer-allocated'>, NumberReply], + [BlobStringReply<'send-buffer-used'>, NumberReply], +]>>; -export function transformReply(reply: ClusterLinksRawReply): ClusterLinksReply { - return reply.map(peerLink => ({ - direction: peerLink[1], - node: peerLink[3], - createTime: Number(peerLink[5]), - events: peerLink[7], - sendBufferAllocated: Number(peerLink[9]), - sendBufferUsed: Number(peerLink[11]) - })); -} +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'LINKS']; + }, + transformReply: { + 2: (reply: Resp2Reply) => reply.map(link => ({ + direction: link[1], + node: link[3], + 'create-time': link[5], + events: link[7], + 'send-buffer-allocated': link[9], + 'send-buffer-used': link[11] + })), + 3: undefined as unknown as () => ClusterLinksReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_MEET.ts b/packages/client/lib/commands/CLUSTER_MEET.ts index 949412702d3..df72599d40b 100644 --- a/packages/client/lib/commands/CLUSTER_MEET.ts +++ b/packages/client/lib/commands/CLUSTER_MEET.ts @@ -1,6 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(host: string, port: number) { return ['CLUSTER', 'MEET', host, port.toString()]; }, diff --git a/packages/client/lib/commands/CLUSTER_MYID.ts b/packages/client/lib/commands/CLUSTER_MYID.ts index 6c682ddccf8..73711b47ebb 100644 --- a/packages/client/lib/commands/CLUSTER_MYID.ts +++ b/packages/client/lib/commands/CLUSTER_MYID.ts @@ -1,6 +1,8 @@ import { BlobStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['CLUSTER', 'MYID']; }, diff --git a/packages/client/lib/commands/CLUSTER_REPLICATE.ts b/packages/client/lib/commands/CLUSTER_REPLICATE.ts index c589ad33d71..7431142024c 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICATE.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICATE.ts @@ -1,6 +1,8 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(nodeId: RedisArgument) { return ['CLUSTER', 'REPLICATE', nodeId]; }, diff --git a/packages/client/lib/commands/CLUSTER_SETSLOT.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.ts index e79cf88b4ae..ad04513688e 100644 --- a/packages/client/lib/commands/CLUSTER_SETSLOT.ts +++ b/packages/client/lib/commands/CLUSTER_SETSLOT.ts @@ -1,4 +1,4 @@ -import { SimpleStringReply, Command } from '../RESP/types'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export const CLUSTER_SLOT_STATES = { IMPORTING: 'IMPORTING', @@ -7,13 +7,13 @@ export const CLUSTER_SLOT_STATES = { NODE: 'NODE' } as const; -export type ClusterSlotStates = typeof CLUSTER_SLOT_STATES[keyof typeof CLUSTER_SLOT_STATES]; +export type ClusterSlotState = typeof CLUSTER_SLOT_STATES[keyof typeof CLUSTER_SLOT_STATES]; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(slot: number, state: ClusterSlotStates, nodeId?: string) { - const args = ['CLUSTER', 'SETSLOT', slot.toString(), state]; + transformArguments(slot: number, state: ClusterSlotState, nodeId?: RedisArgument) { + const args: Array = ['CLUSTER', 'SETSLOT', slot.toString(), state]; if (nodeId) { args.push(nodeId); diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts index 4650fe83b2d..9010361c78b 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts @@ -26,5 +26,5 @@ describe('CLUSTER SLOTS', () => { assert.equal(typeof replica.id, 'string'); } } - }, GLOBAL.CLUSTERS.OPEN); + }, GLOBAL.CLUSTERS.WITH_REPLICAS); }); diff --git a/packages/client/lib/commands/COMMAND_COUNT.spec.ts b/packages/client/lib/commands/COMMAND_COUNT.spec.ts index ca03e96ae8c..63b3af4866f 100644 --- a/packages/client/lib/commands/COMMAND_COUNT.spec.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.spec.ts @@ -1,19 +1,19 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './COMMAND_COUNT'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import COMMAND_COUNT from './COMMAND_COUNT'; -// describe('COMMAND COUNT', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(), -// ['COMMAND', 'COUNT'] -// ); -// }); +describe('COMMAND COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + COMMAND_COUNT.transformArguments(), + ['COMMAND', 'COUNT'] + ); + }); -// testUtils.testWithClient('client.commandCount', async client => { -// assert.equal( -// typeof await client.commandCount(), -// 'number' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.commandCount', async client => { + assert.equal( + typeof await client.commandCount(), + 'number' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/COMMAND_COUNT.ts b/packages/client/lib/commands/COMMAND_COUNT.ts index f1cd06702e8..10b0fdefe09 100644 --- a/packages/client/lib/commands/COMMAND_COUNT.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.ts @@ -1,9 +1,10 @@ -// import { RedisCommandArguments } from '.'; +import { NumberReply, Command } from '../RESP/types'; -// export const IS_READ_ONLY = true; - -// export function transformArguments(): RedisCommandArguments { -// return ['COMMAND', 'COUNT']; -// } - -// export declare function transformReply(): number; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['COMMAND', 'COUNT']; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts index e17566e0dff..a1a7bd2fc26 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts @@ -1,19 +1,19 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './COMMAND_GETKEYS'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import COMMAND_GETKEYS from './COMMAND_GETKEYS'; -// describe('COMMAND GETKEYS', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(['GET', 'key']), -// ['COMMAND', 'GETKEYS', 'GET', 'key'] -// ); -// }); +describe('COMMAND GETKEYS', () => { + it('transformArguments', () => { + assert.deepEqual( + COMMAND_GETKEYS.transformArguments(['GET', 'key']), + ['COMMAND', 'GETKEYS', 'GET', 'key'] + ); + }); -// testUtils.testWithClient('client.commandGetKeys', async client => { -// assert.deepEqual( -// await client.commandGetKeys(['GET', 'key']), -// ['key'] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.commandGetKeys', async client => { + assert.deepEqual( + await client.commandGetKeys(['GET', 'key']), + ['key'] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/COMMAND_GETKEYS.ts b/packages/client/lib/commands/COMMAND_GETKEYS.ts index fb43798c1b3..55cca415b8d 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.ts @@ -1,9 +1,10 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -// export const IS_READ_ONLY = true; - -// export function transformArguments(args: Array): RedisCommandArguments { -// return ['COMMAND', 'GETKEYS', ...args]; -// } - -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(args: Array) { + return ['COMMAND', 'GETKEYS', ...args]; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CONFIG_GET.spec.ts b/packages/client/lib/commands/CONFIG_GET.spec.ts index 8077a093d85..ae65092e4f7 100644 --- a/packages/client/lib/commands/CONFIG_GET.spec.ts +++ b/packages/client/lib/commands/CONFIG_GET.spec.ts @@ -1,11 +1,31 @@ import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_GET from './CONFIG_GET'; describe('CONFIG GET', () => { - it('transformArguments', () => { - assert.deepEqual( - CONFIG_GET.transformArguments('*'), - ['CONFIG', 'GET', '*'] - ); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + CONFIG_GET.transformArguments('*'), + ['CONFIG', 'GET', '*'] + ); + }); + + it('Array', () => { + assert.deepEqual( + CONFIG_GET.transformArguments(['1', '2']), + ['CONFIG', 'GET', '1', '2'] + ); + }); }); + + + testUtils.testWithClient('client.configGet', async client => { + const config = await client.configGet('*'); + assert.equal(typeof config, 'object'); + for (const [key, value] of Object.entries(config)) { + assert.equal(typeof key, 'string'); + assert.equal(typeof value, 'string'); + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CONFIG_GET.ts b/packages/client/lib/commands/CONFIG_GET.ts index 0fc8229229f..72fb6e56f5f 100644 --- a/packages/client/lib/commands/CONFIG_GET.ts +++ b/packages/client/lib/commands/CONFIG_GET.ts @@ -1,11 +1,14 @@ -import { RedisArgument, Command } from '../RESP/types'; -import { transformTuplesReply } from './generic-transformers'; +import { MapReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments, transformTuplesReply } from './generic-transformers'; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(parameter: RedisArgument) { - return ['CONFIG', 'GET', parameter]; + transformArguments(parameters: RedisVariadicArgument) { + return pushVariadicArguments(['CONFIG', 'GET'], parameters); }, - transformReply: transformTuplesReply + transformReply: { + 2: transformTuplesReply, + 3: undefined as unknown as () => MapReply + } } as const satisfies Command; diff --git a/packages/client/lib/commands/CONFIG_RESETSTAT.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.ts index 119bbd6051b..4d5deb18b47 100644 --- a/packages/client/lib/commands/CONFIG_RESETSTAT.ts +++ b/packages/client/lib/commands/CONFIG_RESETSTAT.ts @@ -1,6 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['CONFIG', 'RESETSTAT']; }, diff --git a/packages/client/lib/commands/CONFIG_REWRITE.ts b/packages/client/lib/commands/CONFIG_REWRITE.ts index 63f9acdb90e..6fbc4b1fa27 100644 --- a/packages/client/lib/commands/CONFIG_REWRITE.ts +++ b/packages/client/lib/commands/CONFIG_REWRITE.ts @@ -1,6 +1,8 @@ import { SimpleStringReply, Command } from '../RESP/types'; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments() { return ['CONFIG', 'REWRITE']; }, diff --git a/packages/client/lib/commands/CONFIG_SET.spec.ts b/packages/client/lib/commands/CONFIG_SET.spec.ts index fac5e1dbe9f..86d590072c8 100644 --- a/packages/client/lib/commands/CONFIG_SET.spec.ts +++ b/packages/client/lib/commands/CONFIG_SET.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_SET from './CONFIG_SET'; describe('CONFIG SET', () => { @@ -21,4 +22,11 @@ describe('CONFIG SET', () => { ); }); }); + + testUtils.testWithClient('client.configSet', async client => { + assert.equal( + await client.configSet('maxmemory', '0'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CONFIG_SET.ts b/packages/client/lib/commands/CONFIG_SET.ts index 58f16e96933..c7072245e22 100644 --- a/packages/client/lib/commands/CONFIG_SET.ts +++ b/packages/client/lib/commands/CONFIG_SET.ts @@ -5,6 +5,8 @@ type SingleParameter = [parameter: RedisArgument, value: RedisArgument]; type MultipleParameters = [config: Record]; export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments( ...[parameterOrConfig, value]: SingleParameter | MultipleParameters ) { diff --git a/packages/client/lib/commands/FLUSHALL.ts b/packages/client/lib/commands/FLUSHALL.ts index 6c814b34a4b..5e6484a991e 100644 --- a/packages/client/lib/commands/FLUSHALL.ts +++ b/packages/client/lib/commands/FLUSHALL.ts @@ -5,12 +5,12 @@ export const REDIS_FLUSH_MODES = { SYNC: 'SYNC' } as const; -export type RedisFlushModes = typeof REDIS_FLUSH_MODES[keyof typeof REDIS_FLUSH_MODES]; +export type RedisFlushMode = typeof REDIS_FLUSH_MODES[keyof typeof REDIS_FLUSH_MODES]; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: false, - transformArguments(mode?: RedisFlushModes) { + transformArguments(mode?: RedisFlushMode) { const args = ['FLUSHALL']; if (mode) { diff --git a/packages/client/lib/commands/FLUSHDB.ts b/packages/client/lib/commands/FLUSHDB.ts index cb7be1156a2..75c7a66f190 100644 --- a/packages/client/lib/commands/FLUSHDB.ts +++ b/packages/client/lib/commands/FLUSHDB.ts @@ -1,10 +1,10 @@ import { SimpleStringReply, Command } from '../RESP/types'; -import { RedisFlushModes } from './FLUSHALL'; +import { RedisFlushMode } from './FLUSHALL'; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: false, - transformArguments(mode?: RedisFlushModes) { + transformArguments(mode?: RedisFlushMode) { const args = ['FLUSHDB']; if (mode) { diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.ts b/packages/client/lib/commands/FUNCTION_FLUSH.ts index 010e9b81087..844d3586d90 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.ts @@ -1,10 +1,10 @@ import { SimpleStringReply, Command } from '../RESP/types'; -import { RedisFlushModes } from './FLUSHALL'; +import { RedisFlushMode } from './FLUSHALL'; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: false, - transformArguments(mode?: RedisFlushModes) { + transformArguments(mode?: RedisFlushMode) { const args = ['FUNCTION', 'FLUSH']; if (mode) { diff --git a/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts b/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts index 3888ff8bd36..67446270be3 100644 --- a/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts +++ b/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts @@ -1,19 +1,19 @@ -import {strict as assert} from 'assert'; -import testUtils, {GLOBAL} from '../test-utils'; -import { transformArguments } from './LATENCY_DOCTOR'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import LATENCY_DOCTOR from './LATENCY_DOCTOR'; describe('LATENCY DOCTOR', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['LATENCY', 'DOCTOR'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LATENCY_DOCTOR.transformArguments(), + ['LATENCY', 'DOCTOR'] + ); + }); - testUtils.testWithClient('client.latencyDoctor', async client => { - assert.equal( - typeof (await client.latencyDoctor()), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.latencyDoctor', async client => { + assert.equal( + typeof await client.latencyDoctor(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LATENCY_DOCTOR.ts b/packages/client/lib/commands/LATENCY_DOCTOR.ts index d2106c06114..96dc6b65702 100644 --- a/packages/client/lib/commands/LATENCY_DOCTOR.ts +++ b/packages/client/lib/commands/LATENCY_DOCTOR.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['LATENCY', 'DOCTOR']; -} +import { BlobStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['LATENCY', 'DOCTOR']; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts index 21755a253b3..f4a3c668965 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LATENCY_GRAPH'; +import LATENCY_GRAPH from './LATENCY_GRAPH'; describe('LATENCY GRAPH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('command'), - [ - 'LATENCY', - 'GRAPH', - 'command' - ] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LATENCY_GRAPH.transformArguments('command'), + [ + 'LATENCY', + 'GRAPH', + 'command' + ] + ); + }); - testUtils.testWithClient('client.latencyGraph', async client => { - await Promise.all([ - client.configSet('latency-monitor-threshold', '1'), - client.sendCommand(['DEBUG', 'SLEEP', '0.001']) - ]); + testUtils.testWithClient('client.latencyGraph', async client => { + await Promise.all([ + client.configSet('latency-monitor-threshold', '1'), + client.sendCommand(['DEBUG', 'SLEEP', '0.001']) + ]); - assert.equal( - typeof await client.latencyGraph('command'), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + typeof await client.latencyGraph('command'), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LATENCY_GRAPH.ts b/packages/client/lib/commands/LATENCY_GRAPH.ts index a789a79075a..c2fdbbd187e 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.ts @@ -1,25 +1,31 @@ -// import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command, BlobStringReply } from '../RESP/types'; -// export type EventType = -// 'active-defrag-cycle' -// | 'aof-fsync-always' -// | 'aof-stat' -// | 'aof-rewrite-diff-write' -// | 'aof-rename' -// | 'aof-write' -// | 'aof-write-active-child' -// | 'aof-write-alone' -// | 'aof-write-pending-fsync' -// | 'command' -// | 'expire-cycle' -// | 'eviction-cycle' -// | 'eviction-del' -// | 'fast-command' -// | 'fork' -// | 'rdb-unlink-temp-file'; +export const LATENCY_EVENTS = { + ACTIVE_DEFRAG_CYCLE: 'active-defrag-cycle', + AOF_FSYNC_ALWAYS: 'aof-fsync-always', + AOF_STAT: 'aof-stat', + AOF_REWRITE_DIFF_WRITE: 'aof-rewrite-diff-write', + AOF_RENAME: 'aof-rename', + AOF_WRITE: 'aof-write', + AOF_WRITE_ACTIVE_CHILD: 'aof-write-active-child', + AOF_WRITE_ALONE: 'aof-write-alone', + AOF_WRITE_PENDING_FSYNC: 'aof-write-pending-fsync', + COMMAND: 'command', + EXPIRE_CYCLE: 'expire-cycle', + EVICTION_CYCLE: 'eviction-cycle', + EVICTION_DEL: 'eviction-del', + FAST_COMMAND: 'fast-command', + FORK: 'fork', + RDB_UNLINK_TEMP_FILE: 'rdb-unlink-temp-file' +} as const; -// export function transformArguments(event: EventType): RedisCommandArguments { -// return ['LATENCY', 'GRAPH', event]; -// } +export type LatencyEvent = typeof LATENCY_EVENTS[keyof typeof LATENCY_EVENTS]; -// export declare function transformReply(): string; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(event: LatencyEvent) { + return ['LATENCY', 'GRAPH', event]; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/LATENCY_LATEST.spec.ts b/packages/client/lib/commands/LATENCY_LATEST.spec.ts index 8d223ec25e6..0fe8085ef66 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.spec.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.spec.ts @@ -1,27 +1,27 @@ -// import {strict as assert} from 'assert'; -// import testUtils, {GLOBAL} from '../test-utils'; -// import { transformArguments } from './LATENCY_LATEST'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import LATENCY_LATEST from './LATENCY_LATEST'; -// describe('LATENCY LATEST', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(), -// ['LATENCY', 'LATEST'] -// ); -// }); +describe('LATENCY LATEST', () => { + it('transformArguments', () => { + assert.deepEqual( + LATENCY_LATEST.transformArguments(), + ['LATENCY', 'LATEST'] + ); + }); -// testUtils.testWithClient('client.latencyLatest', async client => { -// await Promise.all([ -// client.configSet('latency-monitor-threshold', '100'), -// client.sendCommand(['DEBUG', 'SLEEP', '1']) -// ]); -// const latency = await client.latencyLatest(); -// assert.ok(Array.isArray(latency)); -// for (const [name, timestamp, latestLatency, allTimeLatency] of latency) { -// assert.equal(typeof name, 'string'); -// assert.equal(typeof timestamp, 'number'); -// assert.equal(typeof latestLatency, 'number'); -// assert.equal(typeof allTimeLatency, 'number'); -// } -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.latencyLatest', async client => { + await Promise.all([ + client.configSet('latency-monitor-threshold', '100'), + client.sendCommand(['DEBUG', 'SLEEP', '1']) + ]); + const latency = await client.latencyLatest(); + assert.ok(Array.isArray(latency)); + for (const [name, timestamp, latestLatency, allTimeLatency] of latency) { + assert.equal(typeof name, 'string'); + assert.equal(typeof timestamp, 'number'); + assert.equal(typeof latestLatency, 'number'); + assert.equal(typeof allTimeLatency, 'number'); + } + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/LATENCY_LATEST.ts b/packages/client/lib/commands/LATENCY_LATEST.ts index 2455841a205..29548af30dc 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.ts @@ -1,12 +1,16 @@ -// import { RedisCommandArguments } from '.'; +import { ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; -// export function transformArguments(): RedisCommandArguments { -// return ['LATENCY', 'LATEST']; -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['LATENCY', 'LATEST']; + }, + transformReply: undefined as unknown as () => ArrayReply<[ + name: BlobStringReply, + timestamp: NumberReply, + latestLatency: NumberReply, + allTimeLatency: NumberReply + ]> +} as const satisfies Command; -// export declare function transformReply(): Array<[ -// name: string, -// timestamp: number, -// latestLatency: number, -// allTimeLatency: number -// ]>; diff --git a/packages/client/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts index 6c53b61b036..28caa208b8a 100644 --- a/packages/client/lib/commands/MEMORY_STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_STATS.spec.ts @@ -1,43 +1,43 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import MEMORY_STATS from './MEMORY_STATS'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import MEMORY_STATS from './MEMORY_STATS'; -// describe('MEMORY STATS', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// MEMORY_STATS.transformArguments(), -// ['MEMORY', 'STATS'] -// ); -// }); +describe('MEMORY STATS', () => { + it('transformArguments', () => { + assert.deepEqual( + MEMORY_STATS.transformArguments(), + ['MEMORY', 'STATS'] + ); + }); -// testUtils.testWithClient('client.memoryStats', async client => { -// const memoryStats = await client.memoryStats(); -// assert.equal(typeof memoryStats['peak.allocated'], 'number'); -// assert.equal(typeof memoryStats['total.allocated'], 'number'); -// assert.equal(typeof memoryStats['startup.allocated'], 'number'); -// assert.equal(typeof memoryStats['replication.backlog'], 'number'); -// assert.equal(typeof memoryStats['clients.slaves'], 'number'); -// assert.equal(typeof memoryStats['clients.normal'], 'number'); -// assert.equal(typeof memoryStats['cluster.links'], 'number'); -// assert.equal(typeof memoryStats['aof.buffer'], 'number'); -// assert.equal(typeof memoryStats['lua.caches'], 'number'); -// assert.equal(typeof memoryStats['functions.caches'], 'number'); -// assert.equal(typeof memoryStats['overhead.total'], 'number'); -// assert.equal(typeof memoryStats['keys.count'], 'number'); -// assert.equal(typeof memoryStats['keys.bytes-per-key'], 'number'); -// assert.equal(typeof memoryStats['dataset.bytes'], 'number'); -// assert.equal(typeof memoryStats['dataset.percentage'], 'string'); -// assert.equal(typeof memoryStats['peak.percentage'], 'string'); -// assert.equal(typeof memoryStats['allocator.allocated'], 'number'); -// assert.equal(typeof memoryStats['allocator.active'], 'number'); -// assert.equal(typeof memoryStats['allocator.resident'], 'number'); -// assert.equal(typeof memoryStats['allocator-fragmentation.ratio'], 'string'); -// assert.equal(typeof memoryStats['allocator-fragmentation.bytes'], 'number'); -// assert.equal(typeof memoryStats['allocator-rss.ratio'], 'string'); -// assert.equal(typeof memoryStats['allocator-rss.bytes'], 'number'); -// assert.equal(typeof memoryStats['rss-overhead.ratio'], 'string'); -// assert.equal(typeof memoryStats['rss-overhead.bytes'], 'number'); -// assert.equal(typeof memoryStats['fragmentation'], 'string'); -// assert.equal(typeof memoryStats['fragmentation.bytes'], 'number'); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.memoryStats', async client => { + const memoryStats = await client.memoryStats(); + assert.equal(typeof memoryStats['peak.allocated'], 'number'); + assert.equal(typeof memoryStats['total.allocated'], 'number'); + assert.equal(typeof memoryStats['startup.allocated'], 'number'); + assert.equal(typeof memoryStats['replication.backlog'], 'number'); + assert.equal(typeof memoryStats['clients.slaves'], 'number'); + assert.equal(typeof memoryStats['clients.normal'], 'number'); + assert.equal(typeof memoryStats['cluster.links'], 'number'); + assert.equal(typeof memoryStats['aof.buffer'], 'number'); + assert.equal(typeof memoryStats['lua.caches'], 'number'); + assert.equal(typeof memoryStats['functions.caches'], 'number'); + assert.equal(typeof memoryStats['overhead.total'], 'number'); + assert.equal(typeof memoryStats['keys.count'], 'number'); + assert.equal(typeof memoryStats['keys.bytes-per-key'], 'number'); + assert.equal(typeof memoryStats['dataset.bytes'], 'number'); + assert.equal(typeof memoryStats['dataset.percentage'], 'string'); + assert.equal(typeof memoryStats['peak.percentage'], 'string'); + assert.equal(typeof memoryStats['allocator.allocated'], 'number'); + assert.equal(typeof memoryStats['allocator.active'], 'number'); + assert.equal(typeof memoryStats['allocator.resident'], 'number'); + assert.equal(typeof memoryStats['allocator-fragmentation.ratio'], 'string'); + assert.equal(typeof memoryStats['allocator-fragmentation.bytes'], 'number'); + assert.equal(typeof memoryStats['allocator-rss.ratio'], 'string'); + assert.equal(typeof memoryStats['allocator-rss.bytes'], 'number'); + assert.equal(typeof memoryStats['rss-overhead.ratio'], 'string'); + assert.equal(typeof memoryStats['rss-overhead.bytes'], 'number'); + assert.equal(typeof memoryStats['fragmentation'], 'string'); + assert.equal(typeof memoryStats['fragmentation.bytes'], 'number'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 4cc2ca2e4d6..2d798ccd2c6 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -1,53 +1,53 @@ -// import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Command, Resp2Reply } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Command, Resp2Reply } from '../RESP/types'; -// export type MemoryStatsReply = TuplesToMapReply<[ -// [BlobStringReply<'peak.allocated'>, NumberReply], -// [BlobStringReply<'total.allocated'>, NumberReply], -// [BlobStringReply<'startup.allocated'>, NumberReply], -// [BlobStringReply<'replication.backlog'>, NumberReply], -// [BlobStringReply<'clients.slaves'>, NumberReply], -// [BlobStringReply<'clients.normal'>, NumberReply], -// [BlobStringReply<'cluster.links'>, NumberReply], -// [BlobStringReply<'aof.buffer'>, NumberReply], -// [BlobStringReply<'lua.caches'>, NumberReply], -// [BlobStringReply<'functions.caches'>, NumberReply], -// [BlobStringReply<'overhead.total'>, NumberReply], -// [BlobStringReply<'keys.count'>, NumberReply], -// [BlobStringReply<'keys.bytes-per-key'>, NumberReply], -// [BlobStringReply<'dataset.bytes'>, NumberReply], -// [BlobStringReply<'dataset.percentage'>, DoubleReply], -// [BlobStringReply<'peak.percentage'>, DoubleReply], -// [BlobStringReply<'allocator.allocated'>, NumberReply], -// [BlobStringReply<'allocator.active'>, NumberReply], -// [BlobStringReply<'allocator.resident'>, NumberReply], -// [BlobStringReply<'allocator-fragmentation.ratio'>, DoubleReply], -// [BlobStringReply<'allocator-fragmentation.bytes'>, NumberReply], -// [BlobStringReply<'allocator-rss.ratio'>, DoubleReply], -// [BlobStringReply<'allocator-rss.bytes'>, NumberReply], -// [BlobStringReply<'rss-overhead.ratio'>, DoubleReply], -// [BlobStringReply<'rss-overhead.bytes'>, NumberReply], -// [BlobStringReply<'fragmentation'>, DoubleReply], -// [BlobStringReply<'fragmentation.bytes'>, NumberReply] -// ]>; +export type MemoryStatsReply = TuplesToMapReply<[ + [BlobStringReply<'peak.allocated'>, NumberReply], + [BlobStringReply<'total.allocated'>, NumberReply], + [BlobStringReply<'startup.allocated'>, NumberReply], + [BlobStringReply<'replication.backlog'>, NumberReply], + [BlobStringReply<'clients.slaves'>, NumberReply], + [BlobStringReply<'clients.normal'>, NumberReply], + [BlobStringReply<'cluster.links'>, NumberReply], + [BlobStringReply<'aof.buffer'>, NumberReply], + [BlobStringReply<'lua.caches'>, NumberReply], + [BlobStringReply<'functions.caches'>, NumberReply], + [BlobStringReply<'overhead.total'>, NumberReply], + [BlobStringReply<'keys.count'>, NumberReply], + [BlobStringReply<'keys.bytes-per-key'>, NumberReply], + [BlobStringReply<'dataset.bytes'>, NumberReply], + [BlobStringReply<'dataset.percentage'>, DoubleReply], + [BlobStringReply<'peak.percentage'>, DoubleReply], + [BlobStringReply<'allocator.allocated'>, NumberReply], + [BlobStringReply<'allocator.active'>, NumberReply], + [BlobStringReply<'allocator.resident'>, NumberReply], + [BlobStringReply<'allocator-fragmentation.ratio'>, DoubleReply], + [BlobStringReply<'allocator-fragmentation.bytes'>, NumberReply], + [BlobStringReply<'allocator-rss.ratio'>, DoubleReply], + [BlobStringReply<'allocator-rss.bytes'>, NumberReply], + [BlobStringReply<'rss-overhead.ratio'>, DoubleReply], + [BlobStringReply<'rss-overhead.bytes'>, NumberReply], + [BlobStringReply<'fragmentation'>, DoubleReply], + [BlobStringReply<'fragmentation.bytes'>, NumberReply] +]>; -// export default { -// FIRST_KEY_INDEX: undefined, -// IS_READ_ONLY: true, -// transformArguments() { -// return ['MEMORY', 'STATS']; -// }, -// transformReply: { -// 2: (rawReply: Array) => { -// const reply: Partial> = {}; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['MEMORY', 'STATS']; + }, + transformReply: { + 2: (rawReply: Array) => { + const reply: Partial> = {}; -// let i = 0; -// while (i < rawReply.length) { -// const key = rawReply[i++] as keyof MemoryStatsReply['DEFAULT']; -// reply[key] = rawReply[i++] as any; -// } + let i = 0; + while (i < rawReply.length) { + const key = rawReply[i++] as keyof MemoryStatsReply['DEFAULT']; + reply[key] = rawReply[i++] as any; + } -// return reply as MemoryStatsReply['DEFAULT']; -// }, -// 3: undefined as unknown as () => MemoryStatsReply -// } -// } as const satisfies Command; + return reply as MemoryStatsReply['DEFAULT']; + }, + 3: undefined as unknown as () => MemoryStatsReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ROLE.spec.ts b/packages/client/lib/commands/ROLE.spec.ts index 2e6d9b163ae..85f586e441b 100644 --- a/packages/client/lib/commands/ROLE.spec.ts +++ b/packages/client/lib/commands/ROLE.spec.ts @@ -1,69 +1,69 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './ROLE'; +import ROLE from './ROLE'; describe('ROLE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['ROLE'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ROLE.transformArguments(), + ['ROLE'] + ); + }); - describe('transformReply', () => { - it('master', () => { - assert.deepEqual( - transformReply(['master', 3129659, [['127.0.0.1', '9001', '3129242'], ['127.0.0.1', '9002', '3129543']]]), - { - role: 'master', - replicationOffest: 3129659, - replicas: [{ - ip: '127.0.0.1', - port: 9001, - replicationOffest: 3129242 - }, { - ip: '127.0.0.1', - port: 9002, - replicationOffest: 3129543 - }] - } - ); - }); + describe('transformReply', () => { + it('master', () => { + assert.deepEqual( + ROLE.transformReply(['master', 3129659, [['127.0.0.1', '9001', '3129242'], ['127.0.0.1', '9002', '3129543']]] as any), + { + role: 'master', + replicationOffest: 3129659, + replicas: [{ + host: '127.0.0.1', + port: 9001, + replicationOffest: 3129242 + }, { + host: '127.0.0.1', + port: 9002, + replicationOffest: 3129543 + }] + } + ); + }); - it('replica', () => { - assert.deepEqual( - transformReply(['slave', '127.0.0.1', 9000, 'connected', 3167038]), - { - role: 'slave', - master: { - ip: '127.0.0.1', - port: 9000 - }, - state: 'connected', - dataReceived: 3167038 - } - ); - }); + it('replica', () => { + assert.deepEqual( + ROLE.transformReply(['slave', '127.0.0.1', 9000, 'connected', 3167038] as any), + { + role: 'slave', + master: { + host: '127.0.0.1', + port: 9000 + }, + state: 'connected', + dataReceived: 3167038 + } + ); + }); - it('sentinel', () => { - assert.deepEqual( - transformReply(['sentinel', ['resque-master', 'html-fragments-master', 'stats-master', 'metadata-master']]), - { - role: 'sentinel', - masterNames: ['resque-master', 'html-fragments-master', 'stats-master', 'metadata-master'] - } - ); - }); + it('sentinel', () => { + assert.deepEqual( + ROLE.transformReply(['sentinel', ['resque-master', 'html-fragments-master', 'stats-master', 'metadata-master']] as any), + { + role: 'sentinel', + masterNames: ['resque-master', 'html-fragments-master', 'stats-master', 'metadata-master'] + } + ); }); + }); - testUtils.testWithClient('client.role', async client => { - assert.deepEqual( - await client.role(), - { - role: 'master', - replicationOffest: 0, - replicas: [] - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.role', async client => { + assert.deepEqual( + await client.role(), + { + role: 'master', + replicationOffest: 0, + replicas: [] + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/ROLE.ts b/packages/client/lib/commands/ROLE.ts index 2cab0a783ed..40b9d67047b 100644 --- a/packages/client/lib/commands/ROLE.ts +++ b/packages/client/lib/commands/ROLE.ts @@ -3,7 +3,7 @@ import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types type MasterRole = [ role: BlobStringReply<'master'>, replicationOffest: NumberReply, - replicas: ArrayReply<[host: BlobStringReply, port: NumberReply, replicationOffest: NumberReply]>, + replicas: ArrayReply<[host: BlobStringReply, port: BlobStringReply, replicationOffest: BlobStringReply]> ]; type SlaveRole = [ @@ -36,8 +36,8 @@ export default { replicationOffest, replicas: replicas.map(([host, port, replicationOffest]) => ({ host, - port, - replicationOffest, + port: Number(port), + replicationOffest: Number(replicationOffest) })), }; } @@ -48,7 +48,7 @@ export default { role, master: { host: masterHost, - port: masterPort, + port: masterPort }, state, dataReceived, @@ -59,7 +59,7 @@ export default { const [role, masterNames] = reply as SentinelRole; return { role, - masterNames, + masterNames }; } } diff --git a/packages/client/lib/commands/SHUTDOWN.spec.ts b/packages/client/lib/commands/SHUTDOWN.spec.ts index caa3a5dfd0d..4d0d54dc877 100644 --- a/packages/client/lib/commands/SHUTDOWN.spec.ts +++ b/packages/client/lib/commands/SHUTDOWN.spec.ts @@ -1,27 +1,49 @@ -// import { strict as assert } from 'assert'; -// import { transformArguments } from './SHUTDOWN'; +import { strict as assert } from 'assert'; +import SHUTDOWN from './SHUTDOWN'; -// describe('SHUTDOWN', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments(), -// ['SHUTDOWN'] -// ); -// }); +describe('SHUTDOWN', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + SHUTDOWN.transformArguments(), + ['SHUTDOWN'] + ); + }); -// it('NOSAVE', () => { -// assert.deepEqual( -// transformArguments('NOSAVE'), -// ['SHUTDOWN', 'NOSAVE'] -// ); -// }); + it('with mode', () => { + assert.deepEqual( + SHUTDOWN.transformArguments({ + mode: 'NOSAVE' + }), + ['SHUTDOWN', 'NOSAVE'] + ); + }); -// it('SAVE', () => { -// assert.deepEqual( -// transformArguments('SAVE'), -// ['SHUTDOWN', 'SAVE'] -// ); -// }); -// }); -// }); + it('with NOW', () => { + assert.deepEqual( + SHUTDOWN.transformArguments({ + NOW: true + }), + ['SHUTDOWN', 'NOW'] + ); + }); + + it('with FORCE', () => { + assert.deepEqual( + SHUTDOWN.transformArguments({ + FORCE: true + }), + ['SHUTDOWN', 'FORCE'] + ); + }); + + it('with ABORT', () => { + assert.deepEqual( + SHUTDOWN.transformArguments({ + ABORT: true + }), + ['SHUTDOWN', 'ABORT'] + ); + }); + }); +}); diff --git a/packages/client/lib/commands/SHUTDOWN.ts b/packages/client/lib/commands/SHUTDOWN.ts index e2c544c389d..e0f3d08ce81 100644 --- a/packages/client/lib/commands/SHUTDOWN.ts +++ b/packages/client/lib/commands/SHUTDOWN.ts @@ -1,11 +1,35 @@ -// export function transformArguments(mode?: 'NOSAVE' | 'SAVE'): Array { -// const args = ['SHUTDOWN']; +import { SimpleStringReply, Command } from '../RESP/types'; -// if (mode) { -// args.push(mode); -// } +export interface ShutdownOptions { + mode?: 'NOSAVE' | 'SAVE'; + NOW?: boolean; + FORCE?: boolean; + ABORT?: boolean; +} -// return args; -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(options?: ShutdownOptions) { + const args = ['SHUTDOWN'] -// export declare function transformReply(): void; + if (options?.mode) { + args.push(options.mode); + } + + if (options?.NOW) { + args.push('NOW'); + } + + if (options?.FORCE) { + args.push('FORCE'); + } + + if (options?.ABORT) { + args.push('ABORT'); + } + + return args; + }, + transformReply: undefined as unknown as () => void | SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SWAPDB.spec.ts b/packages/client/lib/commands/SWAPDB.spec.ts index dee881b5dc5..a4c6d1833a2 100644 --- a/packages/client/lib/commands/SWAPDB.spec.ts +++ b/packages/client/lib/commands/SWAPDB.spec.ts @@ -1,19 +1,19 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './SWAPDB'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import SWAPDB from './SWAPDB'; -// describe('SWAPDB', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(0, 1), -// ['SWAPDB', '0', '1'] -// ); -// }); +describe('SWAPDB', () => { + it('transformArguments', () => { + assert.deepEqual( + SWAPDB.transformArguments(0, 1), + ['SWAPDB', '0', '1'] + ); + }); -// testUtils.testWithClient('client.swapDb', async client => { -// assert.equal( -// await client.swapDb(0, 1), -// 'OK' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.swapDb', async client => { + assert.equal( + await client.swapDb(0, 1), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/SWAPDB.ts b/packages/client/lib/commands/SWAPDB.ts index 0ab785fb594..f3b768e95f4 100644 --- a/packages/client/lib/commands/SWAPDB.ts +++ b/packages/client/lib/commands/SWAPDB.ts @@ -1,5 +1,11 @@ -// export function transformArguments(index1: number, index2: number): Array { -// return ['SWAPDB', index1.toString(), index2.toString()]; -// } +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(index1: number, index2: number) { + return ['SWAPDB', index1.toString(), index2.toString()]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -// export declare function transformReply(): string; diff --git a/packages/client/lib/commands/TIME.spec.ts b/packages/client/lib/commands/TIME.spec.ts index 5bfd1e50d9c..a9e2448dbd9 100644 --- a/packages/client/lib/commands/TIME.spec.ts +++ b/packages/client/lib/commands/TIME.spec.ts @@ -1,18 +1,19 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './TIME'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import TIME from './TIME'; -// describe('TIME', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(), -// ['TIME'] -// ); -// }); +describe('TIME', () => { + it('transformArguments', () => { + assert.deepEqual( + TIME.transformArguments(), + ['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(Array.isArray(reply)); + assert.equal(typeof reply[0], 'string'); + assert.equal(typeof reply[1], 'string'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/TIME.ts b/packages/client/lib/commands/TIME.ts index 298a4d5aee2..d4dc67ae483 100644 --- a/packages/client/lib/commands/TIME.ts +++ b/packages/client/lib/commands/TIME.ts @@ -1,15 +1,13 @@ -// export function transformArguments(): Array { -// return ['TIME']; -// } +import { BlobStringReply, Command } from '../RESP/types'; -// interface TimeReply extends Date { -// microseconds: number; -// } - -// export function transformReply(reply: [string, string]): TimeReply { -// const seconds = Number(reply[0]), -// microseconds = Number(reply[1]), -// d: Partial = new Date(seconds * 1000 + microseconds / 1000); -// d.microseconds = microseconds; -// return d as TimeReply; -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['TIME']; + }, + transformReply: undefined as unknown as () => [ + unixTimestamp: BlobStringReply<`${number}`>, + microseconds: BlobStringReply<`${number}`> + ] +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index aca729b4e17..73cfe3c89e4 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -52,7 +52,7 @@ import CLUSTER_FORGET from './CLUSTER_FORGET'; import CLUSTER_GETKEYSINSLOT from './CLUSTER_GETKEYSINSLOT'; // import CLUSTER_INFO from './CLUSTER_INFO'; import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; -// import CLUSTER_LINKS from './CLUSTER_LINKS'; +import CLUSTER_LINKS from './CLUSTER_LINKS'; import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; // import CLUSTER_NODES from './CLUSTER_NODES'; @@ -63,6 +63,10 @@ import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH'; import CLUSTER_SETSLOT from './CLUSTER_SETSLOT'; import CLUSTER_SLOTS from './CLUSTER_SLOTS'; +import CONFIG_GET from './CONFIG_GET'; +import CONFIG_RESETASTAT from './CONFIG_RESETSTAT'; +import CONFIG_REWRITE from './CONFIG_REWRITE'; +import CONFIG_SET from './CONFIG_SET'; import COPY from './COPY'; import DBSIZE from './DBSIZE'; import DECR from './DECR'; @@ -138,6 +142,9 @@ import INCRBYFLOAT from './INCRBYFLOAT'; import INFO from './INFO'; import KEYS from './KEYS'; import LASTSAVE from './LASTSAVE'; +import LATENCY_DOCTOR from './LATENCY_DOCTOR'; +import LATENCY_GRAPH from './LATENCY_GRAPH'; +import LATENCY_LATEST from './LATENCY_LATEST'; import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; import LCS_IDX from './LCS_IDX'; import LCS_LEN from './LCS_LEN'; @@ -161,7 +168,7 @@ import LTRIM from './LTRIM'; import MEMORY_DOCTOR from './MEMORY_DOCTOR'; import MEMORY_MALLOC_STATS from './MEMORY_MALLOC-STATS'; import MEMORY_PURGE from './MEMORY_PURGE'; -// import MEMORY_STATS from './MEMORY_STATS'; +import MEMORY_STATS from './MEMORY_STATS'; import MEMORY_USAGE from './MEMORY_USAGE'; import MGET from './MGET'; import MODULE_LIST from './MODULE_LIST'; @@ -193,6 +200,7 @@ import RANDOMKEY from './RANDOMKEY'; import READONLY from './READONLY'; import RENAME from './RENAME'; import RENAMENX from './RENAMENX'; +import ROLE from './ROLE'; import RPOP_COUNT from './RPOP_COUNT'; import RPOP from './RPOP'; import RPOPLPUSH from './RPOPLPUSH'; @@ -233,6 +241,8 @@ import SSCAN from './SSCAN'; import STRLEN from './STRLEN'; import SUNION from './SUNION'; import SUNIONSTORE from './SUNIONSTORE'; +import SWAPDB from './SWAPDB'; +import TIME from './TIME'; import TOUCH from './TOUCH'; import TTL from './TTL'; import TYPE from './TYPE'; @@ -335,7 +345,7 @@ type CLUSTER_FORGET = typeof import('./CLUSTER_FORGET').default; type CLUSTER_GETKEYSINSLOT = typeof import('./CLUSTER_GETKEYSINSLOT').default; // type CLUSTER_INFO = typeof import('./CLUSTER_INFO').default; type CLUSTER_KEYSLOT = typeof import('./CLUSTER_KEYSLOT').default; -// type CLUSTER_LINKS = typeof import('./CLUSTER_LINKS').default; +type CLUSTER_LINKS = typeof import('./CLUSTER_LINKS').default; type CLUSTER_MEET = typeof import('./CLUSTER_MEET').default; type CLUSTER_MYID = typeof import('./CLUSTER_MYID').default; // type CLUSTER_NODES = typeof import('./CLUSTER_NODES').default; @@ -346,6 +356,10 @@ type CLUSTER_SAVECONFIG = typeof import('./CLUSTER_SAVECONFIG').default; type CLUSTER_SET_CONFIG_EPOCH = typeof import('./CLUSTER_SET-CONFIG-EPOCH').default; type CLUSTER_SETSLOT = typeof import('./CLUSTER_SETSLOT').default; type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; +type CONFIG_GET = typeof import('./CONFIG_GET').default; +type CONFIG_RESETASTAT = typeof import('./CONFIG_RESETSTAT').default; +type CONFIG_REWRITE = typeof import('./CONFIG_REWRITE').default; +type CONFIG_SET = typeof import('./CONFIG_SET').default; type COPY = typeof import('./COPY').default; type DBSIZE = typeof DBSIZE; type DECR = typeof import('./DECR').default; @@ -421,6 +435,9 @@ type INCRBYFLOAT = typeof import('./INCRBYFLOAT').default; type INFO = typeof import('./INFO').default; type KEYS = typeof import('./KEYS').default; type LASTSAVE = typeof import('./LASTSAVE').default; +type LATENCY_DOCTOR = typeof import('./LATENCY_DOCTOR').default; +type LATENCY_GRAPH = typeof import('./LATENCY_GRAPH').default; +type LATENCY_LATEST = typeof import('./LATENCY_LATEST').default; type LCS_IDX_WITHMATCHLEN = typeof import('./LCS_IDX_WITHMATCHLEN').default; type LCS_IDX = typeof import('./LCS_IDX').default; type LCS_LEN = typeof import('./LCS_LEN').default; @@ -444,7 +461,7 @@ type LTRIM = typeof import('./LTRIM').default; type MEMORY_DOCTOR = typeof import('./MEMORY_DOCTOR').default; type MEMORY_MALLOC_STATS = typeof import('./MEMORY_MALLOC-STATS').default; type MEMORY_PURGE = typeof import('./MEMORY_PURGE').default; -// type MEMORY_STATS = typeof import('./MEMORY_STATS').default; +type MEMORY_STATS = typeof import('./MEMORY_STATS').default; type MEMORY_USAGE = typeof import('./MEMORY_USAGE').default; type MGET = typeof import('./MGET').default; type MODULE_LIST = typeof import('./MODULE_LIST').default; @@ -477,6 +494,7 @@ type READONLY = typeof import('./READONLY').default; type RENAME = typeof import('./RENAME').default; type RENAMENX = typeof import('./RENAMENX').default; type RPOP_COUNT = typeof import('./RPOP_COUNT').default; +type ROLE = typeof import('./ROLE').default; type RPOP = typeof import('./RPOP').default; type RPOPLPUSH = typeof import('./RPOPLPUSH').default; type RPUSH = typeof import('./RPUSH').default; @@ -516,6 +534,8 @@ type SSCAN = typeof import('./SSCAN').default; type STRLEN = typeof import('./STRLEN').default; type SUNION = typeof import('./SUNION').default; type SUNIONSTORE = typeof import('./SUNIONSTORE').default; +type SWAPDB = typeof import('./SWAPDB').default; +type TIME = typeof import('./TIME').default; type TOUCH = typeof import('./TOUCH').default; type TTL = typeof import('./TTL').default; type TYPE = typeof import('./TYPE').default; @@ -672,8 +692,8 @@ type Commands = { // clusterInfo: CLUSTER_INFO; CLUSTER_KEYSLOT: CLUSTER_KEYSLOT; clusterKeySlot: CLUSTER_KEYSLOT; - // CLUSTER_LINKS: CLUSTER_LINKS; - // clusterLinks: CLUSTER_LINKS; + CLUSTER_LINKS: CLUSTER_LINKS; + clusterLinks: CLUSTER_LINKS; CLUSTER_MEET: CLUSTER_MEET; clusterMeet: CLUSTER_MEET; CLUSTER_MYID: CLUSTER_MYID; @@ -694,6 +714,14 @@ type Commands = { clusterSetSlot: CLUSTER_SETSLOT; CLUSTER_SLOTS: CLUSTER_SLOTS; clusterSlots: CLUSTER_SLOTS; + CONFIG_GET: CONFIG_GET; + configGet: CONFIG_GET; + CONFIG_RESETASTAT: CONFIG_RESETASTAT; + configResetStat: CONFIG_RESETASTAT; + CONFIG_REWRITE: CONFIG_REWRITE; + configRewrite: CONFIG_REWRITE; + CONFIG_SET: CONFIG_SET; + configSet: CONFIG_SET; COPY: COPY; copy: COPY; DBSIZE: DBSIZE; @@ -844,6 +872,12 @@ type Commands = { keys: KEYS; LASTSAVE: LASTSAVE; lastSave: LASTSAVE; + LATENCY_DOCTOR: LATENCY_DOCTOR; + latencyDoctor: LATENCY_DOCTOR; + LATENCY_GRAPH: LATENCY_GRAPH; + latencyGraph: LATENCY_GRAPH; + LATENCY_LATEST: LATENCY_LATEST; + latencyLatest: LATENCY_LATEST; LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN; lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN; LCS_IDX: LCS_IDX; @@ -889,8 +923,8 @@ type Commands = { memoryMallocStats: MEMORY_MALLOC_STATS; MEMORY_PURGE: MEMORY_PURGE; memoryPurge: MEMORY_PURGE; - // MEMORY_STATS: MEMORY_STATS; - // memoryStats: MEMORY_STATS; + MEMORY_STATS: MEMORY_STATS; + memoryStats: MEMORY_STATS; MEMORY_USAGE: MEMORY_USAGE; memoryUsage: MEMORY_USAGE; MGET: MGET; @@ -958,6 +992,8 @@ type Commands = { renameNX: RENAMENX; RPOP_COUNT: RPOP_COUNT; rPopCount: RPOP_COUNT; + ROLE: ROLE; + role: ROLE; RPOP: RPOP; rPop: RPOP; RPOPLPUSH: RPOPLPUSH; @@ -1036,6 +1072,10 @@ type Commands = { sUnion: SUNION; SUNIONSTORE: SUNIONSTORE; sUnionStore: SUNIONSTORE; + SWAPDB: SWAPDB; + swapDb: SWAPDB; + TIME: TIME; + time: TIME; TOUCH: TOUCH; touch: TOUCH; TTL: TTL; @@ -1239,8 +1279,8 @@ export default { // clusterInfo: CLUSTER_INFO, CLUSTER_KEYSLOT, clusterKeySlot: CLUSTER_KEYSLOT, - // CLUSTER_LINKS, - // clusterLinks: CLUSTER_LINKS, + CLUSTER_LINKS, + clusterLinks: CLUSTER_LINKS, CLUSTER_MEET, clusterMeet: CLUSTER_MEET, CLUSTER_MYID, @@ -1261,6 +1301,14 @@ export default { clusterSetSlot: CLUSTER_SETSLOT, CLUSTER_SLOTS, clusterSlots: CLUSTER_SLOTS, + CONFIG_GET, + configGet: CONFIG_GET, + CONFIG_RESETASTAT, + configResetStat: CONFIG_RESETASTAT, + CONFIG_REWRITE, + configRewrite: CONFIG_REWRITE, + CONFIG_SET, + configSet: CONFIG_SET, COPY, copy: COPY, DBSIZE, @@ -1313,8 +1361,8 @@ export default { functionList: FUNCTION_LIST, FUNCTION_LOAD, functionLoad: FUNCTION_LOAD, - // FUNCTION_RESTORE, - // functionRestore: FUNCTION_RESTORE, + FUNCTION_RESTORE, + functionRestore: FUNCTION_RESTORE, // FUNCTION_STATS, // functionStats: FUNCTION_STATS, GEOADD, @@ -1411,6 +1459,12 @@ export default { keys: KEYS, LASTSAVE, lastSave: LASTSAVE, + LATENCY_DOCTOR, + latencyDoctor: LATENCY_DOCTOR, + LATENCY_GRAPH, + latencyGraph: LATENCY_GRAPH, + LATENCY_LATEST, + latencyLatest: LATENCY_LATEST, LCS_IDX_WITHMATCHLEN, lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN, LCS_IDX, @@ -1456,8 +1510,8 @@ export default { memoryMallocStats: MEMORY_MALLOC_STATS, MEMORY_PURGE, memoryPurge: MEMORY_PURGE, - // MEMORY_STATS, - // memoryStats: MEMORY_STATS, + MEMORY_STATS, + memoryStats: MEMORY_STATS, MEMORY_USAGE, memoryUsage: MEMORY_USAGE, MGET, @@ -1525,6 +1579,8 @@ export default { renameNX: RENAMENX, RPOP_COUNT, rPopCount: RPOP_COUNT, + ROLE, + role: ROLE, RPOP, rPop: RPOP, RPOPLPUSH, @@ -1603,6 +1659,10 @@ export default { sUnion: SUNION, SUNIONSTORE, sUnionStore: SUNIONSTORE, + SWAPDB, + swapDb: SWAPDB, + TIME, + time: TIME, TOUCH, touch: TOUCH, TTL, From 2b318d4100b463d98210d86951100bcd34e15bde Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 22 Jun 2023 18:18:23 -0400 Subject: [PATCH 140/325] WIP --- docs/v4-to-v5.md | 1 + packages/client/lib/RESP/types.ts | 6 +- packages/client/lib/commands/BLMPOP.ts | 4 +- packages/client/lib/commands/LMPOP.ts | 25 ++- packages/client/lib/commands/ZADD.ts | 21 ++- packages/client/lib/commands/ZADD_INCR.ts | 11 +- packages/client/lib/commands/ZINCRBY.ts | 5 +- packages/client/lib/commands/ZINTERSTORE.ts | 1 + packages/client/lib/commands/ZMPOP.spec.ts | 79 +++++---- packages/client/lib/commands/ZMPOP.ts | 100 +++++------ packages/client/lib/commands/ZMSCORE.ts | 4 +- packages/client/lib/commands/ZPOPMAX.spec.ts | 70 ++++---- packages/client/lib/commands/ZPOPMAX.ts | 21 ++- .../client/lib/commands/ZPOPMAX_COUNT.spec.ts | 44 +++-- packages/client/lib/commands/ZPOPMAX_COUNT.ts | 25 ++- packages/client/lib/commands/ZPOPMIN.spec.ts | 70 ++++---- packages/client/lib/commands/ZPOPMIN.ts | 33 +++- .../client/lib/commands/ZPOPMIN_COUNT.spec.ts | 44 +++-- packages/client/lib/commands/ZPOPMIN_COUNT.ts | 25 ++- .../client/lib/commands/ZRANGESTORE.spec.ts | 155 ++++++++---------- packages/client/lib/commands/ZRANGESTORE.ts | 114 ++++++------- .../lib/commands/ZRANGE_WITHSCORES.spec.ts | 128 ++++++++------- .../client/lib/commands/ZRANGE_WITHSCORES.ts | 24 +-- packages/client/lib/commands/ZSCAN.ts | 17 +- packages/client/lib/commands/ZSCORE.ts | 7 +- .../lib/commands/generic-transformers.ts | 111 ++++--------- packages/client/lib/commands/index.ts | 42 +++++ 27 files changed, 602 insertions(+), 585 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 8026bf28d33..5d4e2956a2a 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -168,6 +168,7 @@ Some command arguments/replies have changed to align more closely to data types - `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] - `TIME`: `Date` -> `[unixTimestamp: string, microseconds: string]` +- `ZMPOP`: `{ elements: Array<{ member: string; score: number; }>; }` -> `{ members: Array<{ value: string; score: number; }>; }` to match other sorted set commands (e.g. `ZRANGE`, `ZSCAN`) [^enum-to-constants]: TODO diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 812c79c4963..75656309693 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -308,11 +308,7 @@ export type Resp2Reply = ( RESP_TYPES['ARRAY'], Resp2Array>> > : - RespType< - RESP_TYPE, - DEFAULT, - TYPES - > : + RESP3REPLY : RESP3REPLY ); diff --git a/packages/client/lib/commands/BLMPOP.ts b/packages/client/lib/commands/BLMPOP.ts index ec9ab56829b..971b87edeff 100644 --- a/packages/client/lib/commands/BLMPOP.ts +++ b/packages/client/lib/commands/BLMPOP.ts @@ -1,6 +1,6 @@ import { Command } from '../RESP/types'; -import { transformLMPopArguments, LMPopOptions, ListSide, RedisVariadicArgument } from './generic-transformers'; -import LMPOP from './LMPOP'; +import { ListSide, RedisVariadicArgument } from './generic-transformers'; +import LMPOP, { LMPopOptions, transformLMPopArguments } from './LMPOP'; export default { FIRST_KEY_INDEX: 3, diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts index 7ce4bbc2d7b..b828f47f066 100644 --- a/packages/client/lib/commands/LMPOP.ts +++ b/packages/client/lib/commands/LMPOP.ts @@ -1,5 +1,26 @@ -import { NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; -import { transformLMPopArguments, LMPopOptions, ListSide, RedisVariadicArgument } from './generic-transformers'; +import { CommandArguments, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; +import { ListSide, RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; + +export interface LMPopOptions { + COUNT?: number; +} + +export function transformLMPopArguments( + args: CommandArguments, + keys: RedisVariadicArgument, + side: ListSide, + options?: LMPopOptions +): CommandArguments { + pushVariadicArgument(args, keys); + + args.push(side); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} export default { FIRST_KEY_INDEX: 2, diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index ff729f4f9c5..0c5602bf988 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,5 +1,5 @@ -import { RedisArgument, NumberReply, DoubleReply, Command, CommandArguments } from '../RESP/types'; -import { ZMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; +import { RedisArgument, Command } from '../RESP/types'; +import { SortedSetMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export interface ZAddOptions { condition?: 'NX' | 'XX'; @@ -27,7 +27,7 @@ export default { FIRST_KEY_INDEX: 1, transformArguments( key: RedisArgument, - members: ZMember | Array, + members: SortedSetMember | Array, options?: ZAddOptions ) { const args = ['ZADD', key]; @@ -56,16 +56,12 @@ export default { return args; }, - transformReply: { - 2: transformDoubleReply, - 3: undefined as unknown as () => NumberReply - } + transformReply: transformDoubleReply } as const satisfies Command; export function pushMembers( - args: CommandArguments, - members: ZMember | Array -) { + args: Array, + members: SortedSetMember | Array) { if (Array.isArray(members)) { for (const member of members) { pushMember(args, member); @@ -75,7 +71,10 @@ export function pushMembers( } } -function pushMember(args: Array, member: ZMember) { +function pushMember( + args: Array, + member: SortedSetMember +) { args.push( transformDoubleArgument(member.score), member.value diff --git a/packages/client/lib/commands/ZADD_INCR.ts b/packages/client/lib/commands/ZADD_INCR.ts index a278b2ee89a..8fb10721674 100644 --- a/packages/client/lib/commands/ZADD_INCR.ts +++ b/packages/client/lib/commands/ZADD_INCR.ts @@ -1,6 +1,6 @@ -import { RedisArgument, DoubleReply, NullReply, Command } from '../RESP/types'; +import { RedisArgument, Command } from '../RESP/types'; import { pushMembers } from './ZADD'; -import { ZMember, transformDoubleArgument, transformNullableDoubleReply } from './generic-transformers'; +import { SortedSetMember, transformNullableDoubleReply } from './generic-transformers'; export interface ZAddOptions { condition?: 'NX' | 'XX'; @@ -12,7 +12,7 @@ export default { FIRST_KEY_INDEX: 1, transformArguments( key: RedisArgument, - members: ZMember | Array, + members: SortedSetMember | Array, options?: ZAddOptions ) { const args = ['ZADD', key]; @@ -35,8 +35,5 @@ export default { return args; }, - transformReply: { - 2: transformNullableDoubleReply, - 3: undefined as unknown as () => DoubleReply | NullReply - } + transformReply: transformNullableDoubleReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts index c20da15161d..3bb987d5f1c 100644 --- a/packages/client/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -15,8 +15,5 @@ export default { member ]; }, - transformReply: { - 2: transformDoubleReply, - 3: undefined as unknown as () => DoubleReply - } + transformReply: transformDoubleReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTERSTORE.ts b/packages/client/lib/commands/ZINTERSTORE.ts index 941ddd68e57..a5334566d73 100644 --- a/packages/client/lib/commands/ZINTERSTORE.ts +++ b/packages/client/lib/commands/ZINTERSTORE.ts @@ -5,6 +5,7 @@ import { ZKeys } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, transformArguments( destination: RedisArgument, keys: ZKeys, diff --git a/packages/client/lib/commands/ZMPOP.spec.ts b/packages/client/lib/commands/ZMPOP.spec.ts index d99cceb41ca..e866c09f72b 100644 --- a/packages/client/lib/commands/ZMPOP.spec.ts +++ b/packages/client/lib/commands/ZMPOP.spec.ts @@ -1,32 +1,55 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZMPOP'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZMPOP from './ZMPOP'; -// describe('ZMPOP', () => { -// testUtils.isVersionGreaterThanHook([7]); +describe('ZMPOP', () => { + testUtils.isVersionGreaterThanHook([7]); -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', 'MIN'), -// ['ZMPOP', '1', 'key', 'MIN'] -// ); -// }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZMPOP.transformArguments('key', 'MIN'), + ['ZMPOP', '1', 'key', 'MIN'] + ); + }); -// it('with score and count', () => { -// assert.deepEqual( -// transformArguments('key', 'MIN', { -// COUNT: 2 -// }), -// ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] -// ); -// }); -// }); + it('with count', () => { + assert.deepEqual( + ZMPOP.transformArguments('key', 'MIN', { + COUNT: 2 + }), + ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] + ); + }); + }); -// testUtils.testWithClient('client.zmPop', async client => { -// assert.deepEqual( -// await client.zmPop('key', 'MIN'), -// null -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zmPop - null', async client => { + assert.equal( + await client.zmPop('key', 'MIN'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('zmPop - with members', async client => { + const members = [{ + value: '1', + score: 1 + }]; + + const [, reply] = await Promise.all([ + client.zAdd('key', members), + client.zmPop('key', 'MIN') + ]); + + assert.deepEqual(reply, { + key: 'key', + members + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts index ae704ab2863..6484277ae85 100644 --- a/packages/client/lib/commands/ZMPOP.ts +++ b/packages/client/lib/commands/ZMPOP.ts @@ -1,61 +1,51 @@ -// import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command, RedisArgument } from '../RESP/types'; -// import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide } from './generic-transformers'; +import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; +import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply } from './generic-transformers'; -// export interface ZMPopOptions { -// COUNT?: number; -// } +export interface ZMPopOptions { + COUNT?: number; +} -// export type ZMPopRawReply = NullReply | TuplesReply<[ -// key: BlobStringReply, -// elements: ArrayReply> -// ]>; +export type ZMPopRawReply = NullReply | TuplesReply<[ + key: BlobStringReply, + members: ArrayReply> +]>; -// export function pushZMPopArguments( -// args: Array, -// keys: RedisVariadicArgument, -// side: SortedSetSide, -// options: ZMPopOptions -// ) +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + keys: RedisVariadicArgument, + side: SortedSetSide, + options?: ZMPopOptions + ) { + const args = pushVariadicArgument(['ZMPOP'], keys); -// export default { -// FIRST_KEY_INDEX: 2, -// IS_READ_ONLY: false, -// transformArguments( -// keys: RedisVariadicArgument, -// side: SortedSetSide, -// options?: ZMPopOptions -// ) { -// const args = pushVariadicArgument(['ZMPOP'], keys); + args.push(side); -// args.push(side); + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// return args; -// }, -// transformReply: { -// 2: (reply: Resp2Reply) => { -// return reply === null ? null : { -// key: reply[0], -// elements: reply[1].map(([member, score]) => ({ -// member, -// score: Number(score) -// })) -// }; -// }, -// 3: (reply: ZMPopRawReply) => { -// return reply === null ? null : { -// key: reply[0], -// elements: reply[1].map(([member, score]) => ({ -// member, -// score -// })) -// }; -// }, -// } -// } as const satisfies Command; + return args; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply === null ? null : { + key: reply[0], + members: reply[1].map(([value, score]) => ({ + value, + score: Number(score) + })) + }; + }, + 3: (reply: ZMPopRawReply) => { + return reply === null ? null : { + key: reply[0], + members: transformSortedSetReply[3](reply[1]) + }; + }, + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts index f5a8fac0d7b..4c3903b011b 100644 --- a/packages/client/lib/commands/ZMSCORE.ts +++ b/packages/client/lib/commands/ZMSCORE.ts @@ -1,5 +1,5 @@ import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; -import { pushVariadicArguments, RedisVariadicArgument } from './generic-transformers'; +import { pushVariadicArguments, RedisVariadicArgument, transformNullableDoubleReply } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -12,7 +12,7 @@ export default { }, transformReply: { 2: (reply: ArrayReply) => { - return reply.map(score => score === null ? null : Number(score)); + return reply.map(transformNullableDoubleReply[2]); }, 3: undefined as unknown as () => ArrayReply } diff --git a/packages/client/lib/commands/ZPOPMAX.spec.ts b/packages/client/lib/commands/ZPOPMAX.spec.ts index 46b7cf1df84..c18c419e81d 100644 --- a/packages/client/lib/commands/ZPOPMAX.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX.spec.ts @@ -1,41 +1,39 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './ZPOPMAX'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZPOPMAX from './ZPOPMAX'; -// describe('ZPOPMAX', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['ZPOPMAX', 'key'] -// ); -// }); +describe('ZPOPMAX', () => { + it('transformArguments', () => { + assert.deepEqual( + ZPOPMAX.transformArguments('key'), + ['ZPOPMAX', 'key'] + ); + }); -// it('transformReply', () => { -// assert.deepEqual( -// transformReply(['value', '1']), -// { -// value: 'value', -// score: 1 -// } -// ); -// }); + testUtils.testAll('zPopMax - null', async client => { + assert.equal( + await client.zPopMax('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); -// describe('client.zPopMax', () => { -// testUtils.testWithClient('null', async client => { -// assert.equal( -// await client.zPopMax('key'), -// null -// ); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zPopMax - with member', async client => { + const member = { + value: 'value', + score: 1 + }; -// testUtils.testWithClient('member', async client => { -// const member = { score: 1, value: 'value' }, -// [, zPopMaxReply] = await Promise.all([ -// client.zAdd('key', member), -// client.zPopMax('key') -// ]); + const [, reply] = await Promise.all([ + client.zAdd('key', member), + client.zPopMax('key') + ]); -// assert.deepEqual(zPopMaxReply, member); -// }, GLOBAL.SERVERS.OPEN); -// }); -// }); + assert.deepEqual(reply, member); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZPOPMAX.ts b/packages/client/lib/commands/ZPOPMAX.ts index 959c3b927ba..4e1d476c41b 100644 --- a/packages/client/lib/commands/ZPOPMAX.ts +++ b/packages/client/lib/commands/ZPOPMAX.ts @@ -1,12 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import ZPOPMIN from './ZPOPMIN'; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { -// return [ -// 'ZPOPMAX', -// key -// ]; -// } - -// export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument) { + return ['ZPOPMAX', key]; + }, + transformReply: ZPOPMIN.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts index 1214c8b2c29..222dcf43f86 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts @@ -1,19 +1,29 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZPOPMAX_COUNT'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZPOPMAX_COUNT from './ZPOPMAX_COUNT'; -// describe('ZPOPMAX COUNT', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 1), -// ['ZPOPMAX', 'key', '1'] -// ); -// }); +describe('ZPOPMAX COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + ZPOPMAX_COUNT.transformArguments('key', 1), + ['ZPOPMAX', 'key', '1'] + ); + }); -// testUtils.testWithClient('client.zPopMaxCount', async client => { -// assert.deepEqual( -// await client.zPopMaxCount('key', 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zPopMaxCount', async client => { + const members = [{ + value: '1', + score: 1 + }]; + + const [ , reply] = await Promise.all([ + client.zAdd('key', members), + client.zPopMaxCount('key', 1) + ]); + + assert.deepEqual(reply, members); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.ts index 881f5472e68..6ca002cca1e 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.ts @@ -1,16 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformArguments as transformZPopMaxArguments } from './ZPOPMAX'; +import { RedisArgument, Command } from '../RESP/types'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX } from './ZPOPMAX'; - -// export function transformArguments( -// key: RedisCommandArgument, -// count: number -// ): RedisCommandArguments { -// return [ -// ...transformZPopMaxArguments(key), -// count.toString() -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, count: number) { + return ['ZPOPMAX', key, count.toString()]; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMIN.spec.ts b/packages/client/lib/commands/ZPOPMIN.spec.ts index 575149632cc..c2f5858a58f 100644 --- a/packages/client/lib/commands/ZPOPMIN.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN.spec.ts @@ -1,41 +1,39 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './ZPOPMIN'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZPOPMIN from './ZPOPMIN'; -// describe('ZPOPMIN', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['ZPOPMIN', 'key'] -// ); -// }); +describe('ZPOPMIN', () => { + it('transformArguments', () => { + assert.deepEqual( + ZPOPMIN.transformArguments('key'), + ['ZPOPMIN', 'key'] + ); + }); -// it('transformReply', () => { -// assert.deepEqual( -// transformReply(['value', '1']), -// { -// value: 'value', -// score: 1 -// } -// ); -// }); + testUtils.testAll('zPopMin - null', async client => { + assert.equal( + await client.zPopMin('key'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); -// describe('client.zPopMin', () => { -// testUtils.testWithClient('null', async client => { -// assert.equal( -// await client.zPopMin('key'), -// null -// ); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('zPopMax - with member', async client => { + const member = { + value: 'value', + score: 1 + }; -// testUtils.testWithClient('member', async client => { -// const member = { score: 1, value: 'value' }, -// [, zPopMinReply] = await Promise.all([ -// client.zAdd('key', member), -// client.zPopMin('key') -// ]); + const [, reply] = await Promise.all([ + client.zAdd('key', member), + client.zPopMin('key') + ]); -// assert.deepEqual(zPopMinReply, member); -// }, GLOBAL.SERVERS.OPEN); -// }); -// }); + assert.deepEqual(reply, member); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZPOPMIN.ts b/packages/client/lib/commands/ZPOPMIN.ts index dea8948b8bc..42f428ada31 100644 --- a/packages/client/lib/commands/ZPOPMIN.ts +++ b/packages/client/lib/commands/ZPOPMIN.ts @@ -1,12 +1,27 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument) { + return ['ZPOPMIN', key]; + }, + transformReply: { + 2: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, BlobStringReply]>) => { + if (reply.length === 0) return null; -// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { -// return [ -// 'ZPOPMIN', -// key -// ]; -// } + return { + value: reply[0], + score: Number(reply[1]) + }; + }, + 3: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, DoubleReply]>) => { + if (reply.length === 0) return null; -// export { transformSortedSetMemberNullReply as transformReply } from './generic-transformers'; + return { + value: reply[0], + score: reply[1] + }; + } + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts index 3d199c15384..fc19ba2b9cd 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts @@ -1,19 +1,29 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZPOPMIN_COUNT'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZPOPMIN_COUNT from './ZPOPMIN_COUNT'; -// describe('ZPOPMIN COUNT', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 1), -// ['ZPOPMIN', 'key', '1'] -// ); -// }); +describe('ZPOPMIN COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + ZPOPMIN_COUNT.transformArguments('key', 1), + ['ZPOPMIN', 'key', '1'] + ); + }); -// testUtils.testWithClient('client.zPopMinCount', async client => { -// assert.deepEqual( -// await client.zPopMinCount('key', 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zPopMinCount', async client => { + const members = [{ + value: '1', + score: 1 + }]; + + const [ , reply] = await Promise.all([ + client.zAdd('key', members), + client.zPopMinCount('key', 1) + ]); + + assert.deepEqual(reply, members); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.ts index 385043be658..36214ab1605 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.ts @@ -1,16 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformArguments as transformZPopMinArguments } from './ZPOPMIN'; +import { RedisArgument, Command } from '../RESP/types'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX } from './ZPOPMIN'; - -// export function transformArguments( -// key: RedisCommandArgument, -// count: number -// ): RedisCommandArguments { -// return [ -// ...transformZPopMinArguments(key), -// count.toString() -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, count: number) { + return ['ZPOPMIN', key, count.toString()]; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGESTORE.spec.ts b/packages/client/lib/commands/ZRANGESTORE.spec.ts index c617f38e9ae..51befc4b381 100644 --- a/packages/client/lib/commands/ZRANGESTORE.spec.ts +++ b/packages/client/lib/commands/ZRANGESTORE.spec.ts @@ -1,92 +1,81 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './ZRANGESTORE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGESTORE from './ZRANGESTORE'; -// describe('ZRANGESTORE', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('ZRANGESTORE', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1), -// ['ZRANGESTORE', 'dst', 'src', '0', '1'] -// ); -// }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1), + ['ZRANGESTORE', 'destination', 'source', '0', '1'] + ); + }); -// it('with BYSCORE', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1, { -// BY: 'SCORE' -// }), -// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE'] -// ); -// }); + it('with BYSCORE', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1, { + BY: 'SCORE' + }), + ['ZRANGESTORE', 'destination', 'source', '0', '1', 'BYSCORE'] + ); + }); -// it('with BYLEX', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1, { -// BY: 'LEX' -// }), -// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYLEX'] -// ); -// }); + it('with BYLEX', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1, { + BY: 'LEX' + }), + ['ZRANGESTORE', 'destination', 'source', '0', '1', 'BYLEX'] + ); + }); -// it('with REV', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1, { -// REV: true -// }), -// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'REV'] -// ); -// }); + it('with REV', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1, { + REV: true + }), + ['ZRANGESTORE', 'destination', 'source', '0', '1', 'REV'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1, { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'LIMIT', '0', '1'] -// ); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGESTORE', 'destination', 'source', '0', '1', 'LIMIT', '0', '1'] + ); + }); -// it('with BY & REV & LIMIT', () => { -// assert.deepEqual( -// transformArguments('dst', 'src', 0, 1, { -// BY: 'SCORE', -// REV: true, -// LIMIT: { -// offset: 0, -// count: 1 -// }, -// WITHSCORES: true -// }), -// ['ZRANGESTORE', 'dst', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] -// ); -// }); -// }); + it('with BY & REV & LIMIT', () => { + assert.deepEqual( + ZRANGESTORE.transformArguments('destination', 'source', 0, 1, { + BY: 'SCORE', + REV: true, + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGESTORE', 'destination', 'source', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1'] + ); + }); + }); -// describe('transformReply', () => { -// it('should throw TypeError when reply is not a number', () => { -// assert.throws( -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// () => (transformReply as any)([]), -// TypeError -// ); -// }); -// }); + testUtils.testWithClient('client.zRangeStore', async client => { + const [, reply] = await Promise.all([ + client.zAdd('{tag}source', { + score: 1, + value: '1' + }), + client.zRangeStore('{tag}destination', '{tag}source', 0, 1) + ]); -// testUtils.testWithClient('client.zRangeStore', async client => { -// await client.zAdd('src', { -// score: 0.5, -// value: 'value' -// }); - -// assert.equal( -// await client.zRangeStore('dst', 'src', 0, 1), -// 1 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(reply, 1); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/ZRANGESTORE.ts b/packages/client/lib/commands/ZRANGESTORE.ts index 96fd8302de4..96f10120b87 100644 --- a/packages/client/lib/commands/ZRANGESTORE.ts +++ b/packages/client/lib/commands/ZRANGESTORE.ts @@ -1,62 +1,52 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformStringDoubleArgument } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// interface ZRangeStoreOptions { -// BY?: 'SCORE' | 'LEX'; -// REV?: true; -// LIMIT?: { -// offset: number; -// count: number; -// }; -// WITHSCORES?: true; -// } - -// export function transformArguments( -// dst: RedisCommandArgument, -// src: RedisCommandArgument, -// min: RedisCommandArgument | number, -// max: RedisCommandArgument | number, -// options?: ZRangeStoreOptions -// ): RedisCommandArguments { -// const args = [ -// 'ZRANGESTORE', -// dst, -// src, -// transformStringDoubleArgument(min), -// transformStringDoubleArgument(max) -// ]; - -// switch (options?.BY) { -// case 'SCORE': -// args.push('BYSCORE'); -// break; - -// case 'LEX': -// args.push('BYLEX'); -// break; -// } - -// if (options?.REV) { -// args.push('REV'); -// } - -// if (options?.LIMIT) { -// args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); -// } - -// if (options?.WITHSCORES) { -// args.push('WITHSCORES'); -// } - -// return args; -// } - -// export function transformReply(reply: number): number { -// if (typeof reply !== 'number') { -// throw new TypeError(`Upgrade to Redis 6.2.5 and up (https://github.com/redis/redis/pull/9089)`); -// } - -// return reply; -// } +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { transformStringDoubleArgument } from './generic-transformers'; + +export interface ZRangeStoreOptions { + BY?: 'SCORE' | 'LEX'; + REV?: true; + LIMIT?: { + offset: number; + count: number; + }; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + source: RedisArgument, + min: RedisArgument | number, + max: RedisArgument | number, + options?: ZRangeStoreOptions + ) { + const args = [ + 'ZRANGESTORE', + destination, + source, + transformStringDoubleArgument(min), + transformStringDoubleArgument(max) + ]; + + switch (options?.BY) { + case 'SCORE': + args.push('BYSCORE'); + break; + + case 'LEX': + args.push('BYLEX'); + break; + } + + if (options?.REV) { + args.push('REV'); + } + + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.offset.toString(), options.LIMIT.count.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts index 0f106910f5f..0d2cec9b9fa 100644 --- a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts @@ -1,65 +1,75 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZRANGE_WITHSCORES'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGE_WITHSCORES from './ZRANGE_WITHSCORES'; -// describe('ZRANGE WITHSCORES', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1), -// ['ZRANGE', 'src', '0', '1', 'WITHSCORES'] -// ); -// }); +describe('ZRANGE WITHSCORES', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGE_WITHSCORES.transformArguments('src', 0, 1), + ['ZRANGE', 'src', '0', '1', 'WITHSCORES'] + ); + }); -// it('with BY', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// BY: 'SCORE' -// }), -// ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'WITHSCORES'] -// ); -// }); + it('with BY', () => { + assert.deepEqual( + ZRANGE_WITHSCORES.transformArguments('src', 0, 1, { + BY: 'SCORE' + }), + ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'WITHSCORES'] + ); + }); -// it('with REV', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// REV: true -// }), -// ['ZRANGE', 'src', '0', '1', 'REV', 'WITHSCORES'] -// ); -// }); + it('with REV', () => { + assert.deepEqual( + ZRANGE_WITHSCORES.transformArguments('src', 0, 1, { + REV: true + }), + ['ZRANGE', 'src', '0', '1', 'REV', 'WITHSCORES'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] -// ); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGE_WITHSCORES.transformArguments('src', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] + ); + }); -// it('with BY & REV & LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// BY: 'SCORE', -// REV: true, -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] -// ); -// }); -// }); + it('with BY & REV & LIMIT', () => { + assert.deepEqual( + ZRANGE_WITHSCORES.transformArguments('src', 0, 1, { + BY: 'SCORE', + REV: true, + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGE', 'src', '0', '1', 'BYSCORE', 'REV', 'LIMIT', '0', '1', 'WITHSCORES'] + ); + }); + }); -// testUtils.testWithClient('client.zRangeWithScores', async client => { -// assert.deepEqual( -// await client.zRangeWithScores('src', 0, 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRangeWithScores', async client => { + const members = [{ + value: '1', + score: 1 + }]; + + const [, reply] = await Promise.all([ + client.zAdd('key', members), + client.zRangeWithScores('key', 0, 1) + ]); + + assert.deepEqual(reply, members); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANGE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts index d05b856263c..cfa90e99ea4 100644 --- a/packages/client/lib/commands/ZRANGE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.ts @@ -1,13 +1,15 @@ -// import { RedisCommandArguments } from '.'; -// import { transformArguments as transformZRangeArguments } from './ZRANGE'; +import { Command } from '../RESP/types'; +import ZRANGE from './ZRANGE'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGE'; +export default { + FIRST_KEY_INDEX: ZRANGE.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANGE.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZRANGE.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformZRangeArguments(...args), -// 'WITHSCORES' -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index 50c9c5fa9cb..1938e67da24 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -1,6 +1,6 @@ -import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; import { ScanCommonOptions, pushScanArguments } from './SCAN'; -import { ZMember, transformDoubleReply } from './generic-transformers'; +import { SortedSetMember, transformDoubleReply, transformSortedSetReply } from './generic-transformers'; export interface HScanEntry { field: BlobStringReply; @@ -17,19 +17,10 @@ export default { ) { return pushScanArguments(['ZSCAN', key], cursor, options); }, - transformReply([cursor, rawMembers]: [BlobStringReply, Array]) { - const members = []; - let i = 0; - while (i < rawMembers.length) { - members.push({ - value: rawMembers[i++], - score: transformDoubleReply(rawMembers[i++]) - } satisfies ZMember); - } - + transformReply([cursor, rawMembers]: [BlobStringReply, ArrayReply]) { return { cursor: Number(cursor), - members + members: transformSortedSetReply[2](rawMembers) }; } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZSCORE.ts b/packages/client/lib/commands/ZSCORE.ts index b62e6b53059..0d3db752e1c 100644 --- a/packages/client/lib/commands/ZSCORE.ts +++ b/packages/client/lib/commands/ZSCORE.ts @@ -1,5 +1,5 @@ -import { DoubleReply, NullReply, Command, RedisArgument } from '../RESP/types'; +import { RedisArgument, Command } from '../RESP/types'; import { transformNullableDoubleReply } from './generic-transformers'; export default { @@ -8,8 +8,5 @@ export default { transformArguments(key: RedisArgument, member: RedisArgument) { return ['ZSCORE', key, member]; }, - transformReply: { - 2: transformNullableDoubleReply, - 3: undefined as unknown as () => DoubleReply | NullReply - } + transformReply: transformNullableDoubleReply } as const satisfies Command; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 25b602c8441..03884ac44ad 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,30 +1,7 @@ -import { ArrayReply, BlobStringReply, CommandArguments, DoubleReply, NullReply, RedisArgument, Resp2Reply } from '../RESP/types'; +import { ArrayReply, BlobStringReply, CommandArguments, DoubleReply, NullReply, RedisArgument, Resp2Reply, TuplesReply } from '../RESP/types'; export type BitValue = 0 | 1; -export function transformDoubleReply(reply: BlobStringReply): number { - switch (reply.toString()) { - case '+inf': - return Infinity; - - case '-inf': - return -Infinity; - - default: - return Number(reply); - } -} - -export function transformNullableDoubleReply(reply: BlobStringReply | NullReply): number | null { - if (reply === null) return null; - - return transformDoubleReply(reply); -} - -export function transformArrayNullableDoubleReply(reply: Array): Array { - return reply.map(transformNullableDoubleReply); -} - export function transformDoubleArgument(num: number): string { switch (num) { case Infinity: @@ -44,6 +21,31 @@ export function transformStringDoubleArgument(num: RedisArgument | number): Redi return transformDoubleArgument(num); } +export const transformDoubleReply = { + 2: (reply: BlobStringReply) => { + switch (reply.toString()) { + case '+inf': + return Infinity; + + case '-inf': + return -Infinity; + + default: + return Number(reply); + } + }, + 3: undefined as unknown as () => DoubleReply +}; + +export const transformNullableDoubleReply = { + 2: (reply: BlobStringReply | NullReply) => { + if (reply === null) return null; + + return transformDoubleReply[2](reply); + }, + 3: undefined as unknown as () => DoubleReply | NullReply +}; + export function transformTuplesReply( reply: ArrayReply ): Record { @@ -90,27 +92,12 @@ export function transformStreamsMessagesReply(reply: Array | null): Streams })); } -export interface ZMember { - score: number; +export interface SortedSetMember { value: RedisArgument; + score: number; } -export function transformSortedSetMemberNullReply( - reply: [BlobStringReply, BlobStringReply] | [] -): ZMember | null { - if (!reply.length) return null; - - return transformSortedSetMemberReply(reply); -} - -export function transformSortedSetMemberReply( - reply: [BlobStringReply, BlobStringReply] -): ZMember { - return { - value: reply[0], - score: transformDoubleReply(reply[1]) - }; -} +export type SortedSetSide = 'MIN' | 'MAX'; export const transformSortedSetReply = { 2: (reply: ArrayReply) => { @@ -118,13 +105,13 @@ export const transformSortedSetReply = { for (let i = 0; i < reply.length; i += 2) { members.push({ value: reply[i], - score: transformDoubleReply(reply[i + 1]) + score: transformDoubleReply[2](reply[i + 1]) }); } return members; }, - 3: (reply: ArrayReply<[BlobStringReply, DoubleReply]>) => { + 3: (reply: ArrayReply>) => { return reply.map(([value, score]) => ({ value, score @@ -132,44 +119,8 @@ export const transformSortedSetReply = { } } -export function transformSortedSetWithScoresReply(reply: ArrayReply): Array { - const members = []; - - for (let i = 0; i < reply.length; i += 2) { - members.push({ - value: reply[i], - score: transformDoubleReply(reply[i + 1]) - }); - } - - return members; -} - export type ListSide = 'LEFT' | 'RIGHT'; -export type SortedSetSide = 'MIN' | 'MAX'; - -export interface LMPopOptions { - COUNT?: number; -} - -export function transformLMPopArguments( - args: CommandArguments, - keys: RedisVariadicArgument, - side: ListSide, - options?: LMPopOptions -): CommandArguments { - pushVariadicArgument(args, keys); - - args.push(side); - - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } - - return args; -} - export function transformEXAT(EXAT: number | Date): string { return (typeof EXAT === 'number' ? EXAT : Math.floor(EXAT.getTime() / 1000)).toString(); } diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 73cfe3c89e4..ac013c94ed1 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -270,14 +270,21 @@ import ZINTER from './ZINTER'; import ZINTERCARD from './ZINTERCARD'; import ZINTERSTORE from './ZINTERSTORE'; import ZLEXCOUNT from './ZLEXCOUNT'; +import ZMPOP from './ZMPOP'; import ZMSCORE from './ZMSCORE'; +import ZPOPMAX_COUNT from './ZPOPMAX_COUNT'; +import ZPOPMAX from './ZPOPMAX'; +import ZPOPMIN_COUNT from './ZPOPMIN_COUNT'; +import ZPOPMIN from './ZPOPMIN'; import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; import ZRANDMEMBER from './ZRANDMEMBER'; +import ZRANGE_WITHSCORES from './ZRANGE_WITHSCORES'; import ZRANGE from './ZRANGE'; import ZRANGEBYLEX from './ZRANGEBYLEX'; import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; +import ZRANGESTORE from './ZRANGESTORE'; import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; @@ -563,14 +570,21 @@ type ZINTER = typeof import('./ZINTER').default; type ZINTERCARD = typeof import('./ZINTERCARD').default; type ZINTERSTORE = typeof import('./ZINTERSTORE').default; type ZLEXCOUNT = typeof import('./ZLEXCOUNT').default; +type ZMPOP = typeof import('./ZMPOP').default; type ZMSCORE = typeof import('./ZMSCORE').default; +type ZPOPMAX_COUNT = typeof import('./ZPOPMAX_COUNT').default; +type ZPOPMAX = typeof import('./ZPOPMAX').default; +type ZPOPMIN_COUNT = typeof import('./ZPOPMIN_COUNT').default; +type ZPOPMIN = typeof import('./ZPOPMIN').default; type ZRANDMEMBER_COUNT_WITHSCORES = typeof import('./ZRANDMEMBER_COUNT_WITHSCORES').default; type ZRANDMEMBER_COUNT = typeof import('./ZRANDMEMBER_COUNT').default; type ZRANDMEMBER = typeof import('./ZRANDMEMBER').default; +type ZRANGE_WITHSCORES = typeof import('./ZRANGE_WITHSCORES').default; type ZRANGE = typeof import('./ZRANGE').default; type ZRANGEBYLEX = typeof import('./ZRANGEBYLEX').default; type ZRANGEBYSCORE_WITHSCORES = typeof import('./ZRANGEBYSCORE_WITHSCORES').default; type ZRANGEBYSCORE = typeof import('./ZRANGEBYSCORE').default; +type ZRANGESTORE = typeof import('./ZRANGESTORE').default; type ZREMRANGEBYSCORE = typeof import('./ZREMRANGEBYSCORE').default; type ZRANK = typeof import('./ZRANK').default; type ZREM = typeof import('./ZREM').default; @@ -1130,14 +1144,26 @@ type Commands = { zInterStore: ZINTERSTORE; ZLEXCOUNT: ZLEXCOUNT; zLexCount: ZLEXCOUNT; + ZMPOP: ZMPOP; + zmPop: ZMPOP; ZMSCORE: ZMSCORE; zmScore: ZMSCORE; + ZPOPMAX_COUNT: ZPOPMAX_COUNT; + zPopMaxCount: ZPOPMAX_COUNT; + ZPOPMAX: ZPOPMAX; + zPopMax: ZPOPMAX; + ZPOPMIN_COUNT: ZPOPMIN_COUNT; + zPopMinCount: ZPOPMIN_COUNT; + ZPOPMIN: ZPOPMIN; + zPopMin: ZPOPMIN; ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES; zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES; ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT; zRandMemberCount: ZRANDMEMBER_COUNT; ZRANDMEMBER: ZRANDMEMBER; zRandMember: ZRANDMEMBER; + ZRANGE_WITHSCORES: ZRANGE_WITHSCORES; + zRangeWithScores: ZRANGE_WITHSCORES; ZRANGE: ZRANGE; zRange: ZRANGE; ZRANGEBYLEX: ZRANGEBYLEX; @@ -1146,6 +1172,8 @@ type Commands = { zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES; ZRANGEBYSCORE: ZRANGEBYSCORE; zRangeByScore: ZRANGEBYSCORE; + ZRANGESTORE: ZRANGESTORE; + zRangeStore: ZRANGESTORE; ZRANK: ZRANK; zRank: ZRANK; ZREM: ZREM; @@ -1717,14 +1745,26 @@ export default { zInterStore: ZINTERSTORE, ZLEXCOUNT, zLexCount: ZLEXCOUNT, + ZMPOP, + zmPop: ZMPOP, ZMSCORE, zmScore: ZMSCORE, + ZPOPMAX_COUNT, + zPopMaxCount: ZPOPMAX_COUNT, + ZPOPMAX, + zPopMax: ZPOPMAX, + ZPOPMIN_COUNT, + zPopMinCount: ZPOPMIN_COUNT, + ZPOPMIN, + zPopMin: ZPOPMIN, ZRANDMEMBER_COUNT_WITHSCORES, zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES, ZRANDMEMBER_COUNT, zRandMemberCount: ZRANDMEMBER_COUNT, ZRANDMEMBER, zRandMember: ZRANDMEMBER, + ZRANGE_WITHSCORES, + zRangeWithScores: ZRANGE_WITHSCORES, ZRANGE, zRange: ZRANGE, ZRANGEBYLEX, @@ -1733,6 +1773,8 @@ export default { zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, + ZRANGESTORE, + zRangeStore: ZRANGESTORE, ZRANK, zRank: ZRANK, ZREM, From 4a9d934b84db024e21048629651b3d14e95ba5d5 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 22 Jun 2023 18:26:22 -0400 Subject: [PATCH 141/325] wip --- packages/client/lib/commands/SET.spec.ts | 22 ++++++++++++++++++- .../client/lib/commands/ZINTERCARD.spec.ts | 21 +++++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/packages/client/lib/commands/SET.spec.ts b/packages/client/lib/commands/SET.spec.ts index acd3de046dd..1819cc40f35 100644 --- a/packages/client/lib/commands/SET.spec.ts +++ b/packages/client/lib/commands/SET.spec.ts @@ -21,7 +21,27 @@ describe('SET', () => { }); describe('expiration', () => { - it('with expiration', () => { + it('\'KEEPTTL\'', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + expiration: 'KEEPTTL' + }), + ['SET', 'key', 'value', 'KEEPTTL'] + ); + }); + + it('{ type: \'KEEPTTL\' }', () => { + assert.deepEqual( + SET.transformArguments('key', 'value', { + expiration: { + type: 'KEEPTTL' + } + }), + ['SET', 'key', 'value', 'KEEPTTL'] + ); + }); + + it('{ type: \'EX\' }', () => { assert.deepEqual( SET.transformArguments('key', 'value', { expiration: { diff --git a/packages/client/lib/commands/ZINTERCARD.spec.ts b/packages/client/lib/commands/ZINTERCARD.spec.ts index 10b88cbed76..c6817b4f27b 100644 --- a/packages/client/lib/commands/ZINTERCARD.spec.ts +++ b/packages/client/lib/commands/ZINTERCARD.spec.ts @@ -13,11 +13,22 @@ describe('ZINTERCARD', () => { ); }); - it('with limit', () => { - assert.deepEqual( - ZINTERCARD.transformArguments(['1', '2'], 1), - ['ZINTERCARD', '2', '1', '2', 'LIMIT', '1'] - ); + describe('with LIMIT', () => { + it('plain number (backwards compatibility)', () => { + assert.deepEqual( + ZINTERCARD.transformArguments(['1', '2'], 1), + ['ZINTERCARD', '2', '1', '2', 'LIMIT', '1'] + ); + }); + + it('{ LIMIT: number }', () => { + assert.deepEqual( + ZINTERCARD.transformArguments(['1', '2'], { + LIMIT: 1 + }), + ['ZINTERCARD', '2', '1', '2', 'LIMIT', '1'] + ); + }); }); }); From 437f76c693e9776ec5babb86ce39d57395bc2cd2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 22 Jun 2023 18:27:49 -0400 Subject: [PATCH 142/325] wip --- packages/client/lib/RESP/types.ts | 43 ------------------------------- 1 file changed, 43 deletions(-) diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 75656309693..acaf649896f 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -368,46 +368,3 @@ const SAME = { }, transformReply: () => 'default' as const } satisfies Command; - -type SAME_DEFAULT = CommandWithPoliciesSignature< - typeof SAME, - 2, - {}, - { - request: REQUEST_POLICIES['ALL_NODES']; - response: RESPONSE_POLICIES['SPECIAL']; - } ->; - -// type SAME_RESP2 = CommandReply; -// type SAME_COMMAND_RESP2 = CommandSignuture; -// type SAME_RESP3 = CommandReply; -// type SAME_COMMAND_RESP3 = CommandSignuture; - -// interface Test { -// /** -// * This is a test -// */ -// a: 'a'; -// } - -// const DIFFERENT = { -// transformArguments(key: string): Array { -// return ['GET', key]; -// }, -// transformReply: { -// 2: () => null as any as Test, -// 3: () => '3' as const -// } -// } satisfies Command; - -// type DIFFERENT_RESP2 = CommandReply; -// type DIFFERENT_COMMAND_RESP2 = CommandSignuture; -// type DIFFERENT_RESP3 = CommandReply; -// type DIFFERENT_COMMAND_RESP3 = CommandSignuture; - -// const a = null as any as DIFFERENT_COMMAND_RESP2; - -// const b = await a('a'); - -// b.a \ No newline at end of file From 699b6f024d467cafeadb630becd65ed20aad5072 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 22 Jun 2023 18:32:15 -0400 Subject: [PATCH 143/325] wip --- packages/client/lib/RESP/types.ts | 50 ------------------------------- 1 file changed, 50 deletions(-) diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 75656309693..4816f39d5a1 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -361,53 +361,3 @@ type ReplyWithPolicy< // otherwise, return array of replies Array ); - -const SAME = { - transformArguments(key: string): Array { - return ['GET', key]; - }, - transformReply: () => 'default' as const -} satisfies Command; - -type SAME_DEFAULT = CommandWithPoliciesSignature< - typeof SAME, - 2, - {}, - { - request: REQUEST_POLICIES['ALL_NODES']; - response: RESPONSE_POLICIES['SPECIAL']; - } ->; - -// type SAME_RESP2 = CommandReply; -// type SAME_COMMAND_RESP2 = CommandSignuture; -// type SAME_RESP3 = CommandReply; -// type SAME_COMMAND_RESP3 = CommandSignuture; - -// interface Test { -// /** -// * This is a test -// */ -// a: 'a'; -// } - -// const DIFFERENT = { -// transformArguments(key: string): Array { -// return ['GET', key]; -// }, -// transformReply: { -// 2: () => null as any as Test, -// 3: () => '3' as const -// } -// } satisfies Command; - -// type DIFFERENT_RESP2 = CommandReply; -// type DIFFERENT_COMMAND_RESP2 = CommandSignuture; -// type DIFFERENT_RESP3 = CommandReply; -// type DIFFERENT_COMMAND_RESP3 = CommandSignuture; - -// const a = null as any as DIFFERENT_COMMAND_RESP2; - -// const b = await a('a'); - -// b.a \ No newline at end of file From e95634b37582b5146c5c0d4782f1418f94138e29 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 22 Jun 2023 19:41:35 -0400 Subject: [PATCH 144/325] ref #2489 --- docs/todo.md | 9 +- packages/client/lib/RESP/decoder.spec.ts | 353 ++++++++++-------- .../lib/commands/ZRANK_WITHSCORE.spec.ts | 46 +++ .../client/lib/commands/ZRANK_WITHSCORE.ts | 30 ++ packages/client/lib/commands/index.ts | 6 + todo.md | 31 -- 6 files changed, 277 insertions(+), 198 deletions(-) create mode 100644 packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts create mode 100644 packages/client/lib/commands/ZRANK_WITHSCORE.ts delete mode 100644 todo.md diff --git a/docs/todo.md b/docs/todo.md index 4d9c91e2dd3..157a7c8eafd 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,19 +1,16 @@ -# Leibale +# Client - Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie? -# Docs - +Docs: - [v4 to v5](./v4-to-v5.md) - Legacy mode - [Command Options](./command-options.md) - [RESP](./RESP.md) -# Missing functionality +# Server - `HEXISTS`: accepts one field only, should be the same as `EXISTS` -# Replies - `String` -> `Double`: - `INCRBYFLOAT` - `HINCRBYFLOAT` diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index cff4fbe047f..911baafb506 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -1,195 +1,226 @@ // import { strict as assert } from 'assert'; // import { SinonSpy, spy } from 'sinon'; -// import RESP2Decoder from './decoder'; -// import { ErrorReply } from '../../errors'; - -// interface DecoderAndSpies { -// decoder: RESP2Decoder; -// returnStringsAsBuffersSpy: SinonSpy; -// onReplySpy: SinonSpy; -// } - -// function createDecoderAndSpies(returnStringsAsBuffers: boolean): DecoderAndSpies { -// const returnStringsAsBuffersSpy = spy(() => returnStringsAsBuffers), -// onReplySpy = spy(); - -// return { -// decoder: new RESP2Decoder({ -// returnStringsAsBuffers: returnStringsAsBuffersSpy, -// onReply: onReplySpy -// }), -// returnStringsAsBuffersSpy, -// onReplySpy -// }; +// import { Decoder, RESP_TYPES } from './decoder'; +// import { ErrorReply } from '../errors'; +// import { TypeMapping } from './types'; + +// function createDecoderAndSpies(typeMapping: TypeMapping = {}) { +// const typeMappingSpy = spy(() => typeMapping), +// onReplySpy = spy(), +// onErrorReplySpy = spy(), +// onPushSpy = spy(); + +// return { +// decoder: new Decoder({ +// getTypeMapping: typeMappingSpy, +// onReply: onReplySpy, +// onErrorReply: onErrorReplySpy, +// onPush: onPushSpy +// }), +// typeMappingSpy, +// onReplySpy, +// onErrorReplySpy, +// onPushSpy +// }; // } -// function writeChunks(stream: RESP2Decoder, buffer: Buffer) { -// let i = 0; -// while (i < buffer.length) { -// stream.write(buffer.slice(i, ++i)); -// } +// function writeChunks(stream: Decoder, buffer: Buffer) { +// let i = 0; +// while (i < buffer.length) { +// stream.write(buffer.subarray(i, ++i)); +// } // } // type Replies = Array>; -// interface TestsOptions { -// toWrite: Buffer; -// returnStringsAsBuffers: boolean; -// replies: Replies; +// function generateTests(toWrite: Buffer, tests: Array): void { +// for (const test of tests) { +// describe(test.name, () => { +// generateTests(toWrite, test); +// }); +// } // } -// function generateTests({ -// toWrite, -// returnStringsAsBuffers, -// replies -// }: TestsOptions): void { -// it('single chunk', () => { -// const { decoder, returnStringsAsBuffersSpy, onReplySpy } = -// createDecoderAndSpies(returnStringsAsBuffers); -// decoder.write(toWrite); -// assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); -// testReplies(onReplySpy, replies); -// }); +// interface Test { +// typeMapping?: TypeMapping; +// replies?: Replies; +// errorReplies?: Replies; +// pushReplies?: Replies; +// } -// it('multiple chunks', () => { -// const { decoder, returnStringsAsBuffersSpy, onReplySpy } = -// createDecoderAndSpies(returnStringsAsBuffers); -// writeChunks(decoder, toWrite); -// assert.equal(returnStringsAsBuffersSpy.callCount, replies.length); -// testReplies(onReplySpy, replies); -// }); +// function genetareTypeTests(toWrite: Buffer, { typeMapping, replies, errorReplies, pushReplies }: Test) { +// const total = (replies?.length ?? 0) + (errorReplies?.length ?? 0) + (pushReplies?.length ?? 0); +// it('single chunk', () => { +// const { decoder, typeMappingSpy, onReplySpy, onErrorReplySpy, onPushSpy } = createDecoderAndSpies(typeMapping); +// decoder.write(toWrite); +// assert.equal(typeMappingSpy.callCount, total); +// testReplies(onReplySpy, replies); +// testReplies(onErrorReplySpy, errorReplies); +// testReplies(onPushSpy, pushReplies); +// }); + +// it('multiple chunks', () => { +// const { decoder, typeMappingSpy, onReplySpy, onErrorReplySpy, onPushSpy } = createDecoderAndSpies(typeMapping); +// writeChunks(decoder, toWrite); +// assert.equal(typeMappingSpy.callCount, total); +// testReplies(onReplySpy, replies); +// testReplies(onErrorReplySpy, errorReplies); +// testReplies(onPushSpy, pushReplies); +// }); // } -// function testReplies(spy: SinonSpy, replies: Replies): void { -// if (!replies) { -// assert.equal(spy.callCount, 0); -// return; -// } - -// assert.equal(spy.callCount, replies.length); -// for (const [i, reply] of replies.entries()) { -// assert.deepEqual( -// spy.getCall(i).args, -// reply -// ); -// } +// function testReplies(spy: SinonSpy, replies?: Replies): void { +// if (!replies) { +// assert.equal(spy.callCount, 0); +// return; +// } + +// assert.equal(spy.callCount, replies.length); +// for (const [i, reply] of replies.entries()) { +// assert.deepEqual( +// spy.getCall(i).args, +// reply +// ); +// } // } // describe('RESP2Parser', () => { -// describe('Simple String', () => { -// describe('as strings', () => { -// generateTests({ -// toWrite: Buffer.from('+OK\r\n'), -// returnStringsAsBuffers: false, -// replies: [['OK']] -// }); -// }); +// describe('Null', () => { +// genetareTypeTests(Buffer.from('_\r\n'), { +// replies: [[null]] +// }); +// }); -// describe('as buffers', () => { -// generateTests({ -// toWrite: Buffer.from('+OK\r\n'), -// returnStringsAsBuffers: true, -// replies: [[Buffer.from('OK')]] -// }); -// }); +// describe('Boolean', () => { +// genetareTypeTests(Buffer.from('#t\r\n'), { +// replies: [[null]] // }); +// }); -// describe('Error', () => { +// describe('Number', () => { +// generateTests(Buffer.from(':-1\r\n')) +// describe('as number', () => { +// describe('-1', () => { +// generateTests({ +// toWrite: , +// replies: [[-1]] +// }); +// }); + +// describe('0', () => { +// generateTests({ +// toWrite: Buffer.from(':0\r\n'), +// replies: [[0]] +// }); +// }); + +// describe('+1', () => { // generateTests({ -// toWrite: Buffer.from('-ERR\r\n'), -// returnStringsAsBuffers: false, -// replies: [[new ErrorReply('ERR')]] +// toWrite: Buffer.from(':+1\r\n'), +// replies: [[1]] // }); +// }); +// }); +// }); + +// describe('Simple String', () => { +// describe('as strings', () => { +// generateTests({ +// toWrite: Buffer.from('+OK\r\n'), +// replies: [['OK']] +// }); // }); -// describe('Integer', () => { -// describe('-1', () => { -// generateTests({ -// toWrite: Buffer.from(':-1\r\n'), -// returnStringsAsBuffers: false, -// replies: [[-1]] -// }); -// }); +// describe('as buffers', () => { +// generateTests({ +// toWrite: Buffer.from('+OK\r\n'), +// typeMapping: { +// [RESP_TYPES.SIMPLE_STRING]: Buffer +// }, +// replies: [[Buffer.from('OK')]] +// }); +// }); +// }); -// describe('0', () => { -// generateTests({ -// toWrite: Buffer.from(':0\r\n'), -// returnStringsAsBuffers: false, -// replies: [[0]] -// }); -// }); +// describe('Error', () => { +// generateTests({ +// toWrite: Buffer.from('-ERR\r\n'), +// errorReplies: [[new ErrorReply('ERR')]] // }); +// }); -// describe('Bulk String', () => { -// describe('null', () => { -// generateTests({ -// toWrite: Buffer.from('$-1\r\n'), -// returnStringsAsBuffers: false, -// replies: [[null]] -// }); -// }); + -// describe('as strings', () => { -// generateTests({ -// toWrite: Buffer.from('$2\r\naa\r\n'), -// returnStringsAsBuffers: false, -// replies: [['aa']] -// }); -// }); +// describe('Bulk String', () => { +// describe('null', () => { +// generateTests({ +// toWrite: Buffer.from('$-1\r\n'), +// returnStringsAsBuffers: false, +// replies: [[null]] +// }); +// }); -// describe('as buffers', () => { -// generateTests({ -// toWrite: Buffer.from('$2\r\naa\r\n'), -// returnStringsAsBuffers: true, -// replies: [[Buffer.from('aa')]] -// }); -// }); +// describe('as strings', () => { +// generateTests({ +// toWrite: Buffer.from('$2\r\naa\r\n'), +// returnStringsAsBuffers: false, +// replies: [['aa']] +// }); // }); -// describe('Array', () => { -// describe('null', () => { -// generateTests({ -// toWrite: Buffer.from('*-1\r\n'), -// returnStringsAsBuffers: false, -// replies: [[null]] -// }); -// }); +// describe('as buffers', () => { +// generateTests({ +// toWrite: Buffer.from('$2\r\naa\r\n'), +// returnStringsAsBuffers: true, +// replies: [[Buffer.from('aa')]] +// }); +// }); +// }); + +// describe('Array', () => { +// describe('null', () => { +// generateTests({ +// toWrite: Buffer.from('*-1\r\n'), +// returnStringsAsBuffers: false, +// replies: [[null]] +// }); +// }); -// const arrayBuffer = Buffer.from( -// '*5\r\n' + -// '+OK\r\n' + -// '-ERR\r\n' + -// ':0\r\n' + -// '$1\r\na\r\n' + -// '*0\r\n' -// ); - -// describe('as strings', () => { -// generateTests({ -// toWrite: arrayBuffer, -// returnStringsAsBuffers: false, -// replies: [[[ -// 'OK', -// new ErrorReply('ERR'), -// 0, -// 'a', -// [] -// ]]] -// }); -// }); +// const arrayBuffer = Buffer.from( +// '*5\r\n' + +// '+OK\r\n' + +// '-ERR\r\n' + +// ':0\r\n' + +// '$1\r\na\r\n' + +// '*0\r\n' +// ); + +// describe('as strings', () => { +// generateTests({ +// toWrite: arrayBuffer, +// returnStringsAsBuffers: false, +// replies: [[[ +// 'OK', +// new ErrorReply('ERR'), +// 0, +// 'a', +// [] +// ]]] +// }); +// }); -// describe('as buffers', () => { -// generateTests({ -// toWrite: arrayBuffer, -// returnStringsAsBuffers: true, -// replies: [[[ -// Buffer.from('OK'), -// new ErrorReply('ERR'), -// 0, -// Buffer.from('a'), -// [] -// ]]] -// }); -// }); +// describe('as buffers', () => { +// generateTests({ +// toWrite: arrayBuffer, +// returnStringsAsBuffers: true, +// replies: [[[ +// Buffer.from('OK'), +// new ErrorReply('ERR'), +// 0, +// Buffer.from('a'), +// [] +// ]]] +// }); // }); +// }); // }); diff --git a/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts b/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts new file mode 100644 index 00000000000..3d308d0d478 --- /dev/null +++ b/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts @@ -0,0 +1,46 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANK_WITHSCORE from './ZRANK_WITHSCORE'; + +describe('ZRANK WITHSCORE', () => { + testUtils.isVersionGreaterThanHook([7, 2]); + + it('transformArguments', () => { + assert.deepEqual( + ZRANK_WITHSCORE.transformArguments('key', 'member'), + ['ZRANK', 'key', 'member', 'WITHSCORE'] + ); + }); + + testUtils.testAll('zRankWithScore - null', async client => { + assert.equal( + await client.zRankWithScore('key', 'member'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('zRankWithScore - with member', async client => { + const member = { + value: '1', + score: 1 + } + + const [, reply] = await Promise.all([ + client.zAdd('key', member), + client.zRankWithScore('key', member.value) + ]) + assert.deepEqual( + reply, + { + rank: 0, + score: 1 + } + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANK_WITHSCORE.ts b/packages/client/lib/commands/ZRANK_WITHSCORE.ts new file mode 100644 index 00000000000..e68c31c20cb --- /dev/null +++ b/packages/client/lib/commands/ZRANK_WITHSCORE.ts @@ -0,0 +1,30 @@ +import { NullReply, TuplesReply, NumberReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import ZRANK from './ZRANK'; + +export default { + FIRST_KEY_INDEX: ZRANK.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANK.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZRANK.transformArguments(...args); + redisArgs.push('WITHSCORE'); + return redisArgs; + }, + transformReply: { + 2: (reply: NullReply | TuplesReply<[NumberReply, BlobStringReply]>) => { + if (reply === null) return null; + + return { + rank: reply[0], + score: Number(reply[1]) + }; + }, + 3: (reply: NullReply | TuplesReply<[BlobStringReply, DoubleReply]>) => { + if (reply === null) return null; + + return { + rank: reply[0], + score: reply[1] + }; + } + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index ac013c94ed1..6537d899133 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -286,6 +286,7 @@ import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZRANGESTORE from './ZRANGESTORE'; import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; +import ZRANK_WITHSCORE from './ZRANK_WITHSCORE'; import ZRANK from './ZRANK'; import ZREM from './ZREM'; import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; @@ -586,6 +587,7 @@ type ZRANGEBYSCORE_WITHSCORES = typeof import('./ZRANGEBYSCORE_WITHSCORES').defa type ZRANGEBYSCORE = typeof import('./ZRANGEBYSCORE').default; type ZRANGESTORE = typeof import('./ZRANGESTORE').default; type ZREMRANGEBYSCORE = typeof import('./ZREMRANGEBYSCORE').default; +type ZRANK_WITHSCORE = typeof import('./ZRANK_WITHSCORE').default; type ZRANK = typeof import('./ZRANK').default; type ZREM = typeof import('./ZREM').default; type ZREMRANGEBYLEX = typeof import('./ZREMRANGEBYLEX').default; @@ -1174,6 +1176,8 @@ type Commands = { zRangeByScore: ZRANGEBYSCORE; ZRANGESTORE: ZRANGESTORE; zRangeStore: ZRANGESTORE; + ZRANK_WITHSCORE: ZRANK_WITHSCORE; + zRankWithScore: ZRANK_WITHSCORE; ZRANK: ZRANK; zRank: ZRANK; ZREM: ZREM; @@ -1775,6 +1779,8 @@ export default { zRangeByScore: ZRANGEBYSCORE, ZRANGESTORE, zRangeStore: ZRANGESTORE, + ZRANK_WITHSCORE, + zRankWithScore: ZRANK_WITHSCORE, ZRANK, zRank: ZRANK, ZREM, diff --git a/todo.md b/todo.md deleted file mode 100644 index 3d7d0b36744..00000000000 --- a/todo.md +++ /dev/null @@ -1,31 +0,0 @@ -# return type \ missing documentation -- `XAUTOCLAIM` -- `XSETID` -- `ZUNION` - - -# create commands -- `ZREVRANGE` -- `ZREVRANGEBYLEX` -- `ZREVRANGEBYSCORE` - - -# waiting List categoreis -- Set -- Bitmap - -# fot leiba -- `BZMPOP.ts` -- `BZPOPMAX.ts` -- `BZPOPMIN.ts` -- `ZMPOP.ts` -- `ZPOPMAX.ts` -- `ZPOPMIN.ts` -- `ZREVRANGE WITHSCORE` -- `ZRANK WITHSCORE` -- `MIGRATE` -- `RESTORE` -- `WAITAOF` - -# other - From afa98d60fb531e20cb0e3d32ddf753238459ae35 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 26 Jun 2023 18:51:09 -0400 Subject: [PATCH 145/325] upgrade deps --- package-lock.json | 147 ++++++++++++++++++----------------- package.json | 8 +- packages/client/package.json | 2 +- 3 files changed, 82 insertions(+), 75 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5aa0f84c9d9..baa0125ea96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,15 @@ "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node16": "^1.0.4", "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", "gh-pages": "^5.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "typedoc": "^0.24.8", + "typescript": "^5.1.3" } }, "node_modules/@ampproject/remapping": { @@ -790,9 +790,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.1.0.tgz", - "integrity": "sha512-w1qd368vtrwttm1PRJWPW1QHlbmHrVDGs1eBH/jZvRPUFS4MNXV9Q33EQdjOdeAxZ7O8+3wM7zxztm2nfUSyKw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0" @@ -861,9 +861,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", - "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.2.tgz", + "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==", "dev": true, "peer": true }, @@ -904,15 +904,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", - "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz", + "integrity": "sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/type-utils": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/type-utils": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -938,14 +938,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", - "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.1.tgz", + "integrity": "sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "debug": "^4.3.4" }, "engines": { @@ -965,13 +965,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", - "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz", + "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0" + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -982,13 +982,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", - "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz", + "integrity": "sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.60.0", - "@typescript-eslint/utils": "5.60.0", + "@typescript-eslint/typescript-estree": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1009,9 +1009,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", - "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz", + "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1022,13 +1022,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", - "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz", + "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1049,17 +1049,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", - "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz", + "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1075,12 +1075,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", - "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz", + "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", + "@typescript-eslint/types": "5.60.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1374,9 +1374,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001504", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001504.tgz", - "integrity": "sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==", + "version": "1.0.30001508", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001508.tgz", + "integrity": "sha512-sdQZOJdmt3GJs1UMNpCCCyeuS2IEGLXnHyAo9yIO5JJDjbjoVRij4M1qep6P6gFpptD1PqIYgzM+gwJbOi92mw==", "dev": true, "funding": [ { @@ -1621,9 +1621,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.434", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.434.tgz", - "integrity": "sha512-5Gvm09UZTQRaWrimRtWRO5rvaX6Kpk5WHAPKDa7A4Gj6NIPuJ8w8WNpnxCXdd+CJJt6RBU6tUw0KyULoW6XuHw==", + "version": "1.4.441", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.441.tgz", + "integrity": "sha512-LlCgQ8zgYZPymf5H4aE9itwiIWH4YlCiv1HFLmmcBeFYi5E+3eaIFnjHzYtcFQbaKfAW+CqZ9pgxo33DZuoqPg==", "dev": true }, "node_modules/email-addresses": { @@ -3630,9 +3630,9 @@ ] }, "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3699,9 +3699,9 @@ } }, "node_modules/shiki": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", - "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -3717,13 +3717,13 @@ "dev": true }, "node_modules/sinon": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.2.tgz", - "integrity": "sha512-uG1pU54Fis4EfYOPoEi13fmRHgZNg/u+3aReSEzHsN52Bpf+bMVfsBQS5MjouI+rTuG6UBIINlpuuO2Epr7SiA==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz", + "integrity": "sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.1.0", + "@sinonjs/fake-timers": "^10.3.0", "@sinonjs/samsam": "^8.0.0", "diff": "^5.1.0", "nise": "^5.1.4", @@ -4085,9 +4085,9 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", + "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -4363,6 +4363,7 @@ } }, "packages/bloom": { + "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { @@ -4373,6 +4374,7 @@ } }, "packages/client": { + "name": "@redis/client", "version": "2.0.0-next.1", "license": "MIT", "dependencies": { @@ -4382,13 +4384,14 @@ "devDependencies": { "@redis/test-utils": "*", "@types/sinon": "^10.0.15", - "sinon": "^15.1.0" + "sinon": "^15.2.0" }, "engines": { "node": ">=16" } }, "packages/graph": { + "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { @@ -4399,6 +4402,7 @@ } }, "packages/json": { + "name": "@redis/json", "version": "1.0.4", "license": "MIT", "devDependencies": { @@ -4447,6 +4451,7 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "packages/search": { + "name": "@redis/search", "version": "1.1.3", "license": "MIT", "devDependencies": { @@ -4457,6 +4462,7 @@ } }, "packages/test-utils": { + "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.24", "yargs": "^17.7.2" @@ -4507,6 +4513,7 @@ } }, "packages/time-series": { + "name": "@redis/time-series", "version": "1.0.4", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 27e6c63d60b..13a7781197f 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,14 @@ "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node16": "^1.0.4", "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", "gh-pages": "^5.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "typedoc": "^0.24.8", + "typescript": "^5.1.3" } } diff --git a/packages/client/package.json b/packages/client/package.json index 374cbcae98b..7e652d2182d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -18,7 +18,7 @@ "devDependencies": { "@redis/test-utils": "*", "@types/sinon": "^10.0.15", - "sinon": "^15.1.0" + "sinon": "^15.2.0" }, "engines": { "node": ">=16" From 1bda2400e5343f7f3e5745fbdede2001b9de34d6 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 26 Jun 2023 19:00:35 -0400 Subject: [PATCH 146/325] Release client@2.0.0-next.2 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 7e652d2182d..8300468496b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From ea2d9d2a77768f8c63263535ab059617622417d2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 28 Jun 2023 11:40:46 -0400 Subject: [PATCH 147/325] stream commands + some more --- docs/scan-iterators.md | 1 + docs/todo.md | 15 - docs/v4-to-v5.md | 5 + packages/client/lib/RESP/types.ts | 4 +- packages/client/lib/commands/BITPOS.ts | 4 +- packages/client/lib/commands/LASTSAVE.spec.ts | 5 +- packages/client/lib/commands/LPOS_COUNT.ts | 4 +- packages/client/lib/commands/SADD.ts | 7 +- packages/client/lib/commands/SDIFF.ts | 8 +- packages/client/lib/commands/SDIFFSTORE.ts | 7 +- packages/client/lib/commands/SINTER.ts | 8 +- packages/client/lib/commands/SINTERCARD.ts | 6 +- packages/client/lib/commands/XACK.spec.ts | 10 +- packages/client/lib/commands/XAUTOCLAIM.ts | 86 +++--- .../client/lib/commands/XAUTOCLAIM_JUSTID.ts | 46 +-- packages/client/lib/commands/XCLAIM.spec.ts | 178 ++++++------ packages/client/lib/commands/XCLAIM.ts | 102 +++---- .../client/lib/commands/XCLAIM_JUSTID.spec.ts | 41 +-- packages/client/lib/commands/XCLAIM_JUSTID.ts | 24 +- .../client/lib/commands/XGROUP_CREATE.spec.ts | 70 +++-- packages/client/lib/commands/XGROUP_CREATE.ts | 46 +-- .../commands/XGROUP_CREATECONSUMER.spec.ts | 45 +-- .../lib/commands/XGROUP_CREATECONSUMER.ts | 25 +- .../lib/commands/XGROUP_DELCONSUMER.spec.ts | 43 +-- .../client/lib/commands/XGROUP_DELCONSUMER.ts | 15 + .../lib/commands/XGROUP_DESTROY.spec.ts | 43 +-- .../client/lib/commands/XGROUP_DESTROY.ts | 23 +- .../client/lib/commands/XGROUP_SETID.spec.ts | 43 +-- packages/client/lib/commands/XGROUP_SETID.ts | 33 ++- .../lib/commands/XINFO_CONSUMERS.spec.ts | 71 ++--- .../client/lib/commands/XINFO_CONSUMERS.ts | 55 ++-- .../client/lib/commands/XINFO_GROUPS.spec.ts | 80 +++--- packages/client/lib/commands/XINFO_GROUPS.ts | 54 ++-- .../client/lib/commands/XINFO_STREAM.spec.ts | 100 ++----- packages/client/lib/commands/XINFO_STREAM.ts | 77 +++++ packages/client/lib/commands/XPENDING.spec.ts | 112 ++++---- packages/client/lib/commands/XPENDING.ts | 70 ++--- .../lib/commands/XPENDING_RANGE.spec.ts | 108 +++---- .../client/lib/commands/XPENDING_RANGE.ts | 67 ++++- packages/client/lib/commands/XRANGE.spec.ts | 63 +++-- packages/client/lib/commands/XRANGE.ts | 45 +-- packages/client/lib/commands/XREAD.spec.ts | 198 ++++++------- packages/client/lib/commands/XREAD.ts | 99 ++++--- .../client/lib/commands/XREADGROUP.spec.ts | 266 ++++++++---------- packages/client/lib/commands/XREADGROUP.ts | 103 +++---- .../client/lib/commands/XREVRANGE.spec.ts | 63 +++-- packages/client/lib/commands/XREVRANGE.ts | 39 +-- packages/client/lib/commands/XSETID.ts | 2 + packages/client/lib/commands/XTRIM.ts | 4 +- .../lib/commands/generic-transformers.ts | 50 ++-- packages/client/lib/commands/index.ts | 120 +++++++- test/package-lock.json | 200 +------------ test/package.json | 6 +- test/test.js | 35 +-- 54 files changed, 1546 insertions(+), 1488 deletions(-) diff --git a/docs/scan-iterators.md b/docs/scan-iterators.md index cfb7545e58f..f8e317fcef7 100644 --- a/docs/scan-iterators.md +++ b/docs/scan-iterators.md @@ -22,6 +22,7 @@ You can override the default options by providing a configuration object: ```typescript client.scanIterator({ + cursor: 0, // 0 by default TYPE: 'string', // `SCAN` only MATCH: 'patter*', COUNT: 100 diff --git a/docs/todo.md b/docs/todo.md index 157a7c8eafd..c6abedcf413 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,21 +1,6 @@ -# Client - - Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie? Docs: - [v4 to v5](./v4-to-v5.md) - Legacy mode - [Command Options](./command-options.md) - [RESP](./RESP.md) - -# Server - -- `HEXISTS`: accepts one field only, should be the same as `EXISTS` - -`String` -> `Double`: -- `INCRBYFLOAT` -- `HINCRBYFLOAT` -- `GEODIST` - -`Number` -> `Boolean`: -- `HSETNX` (deprecated) -- `SCRIPT EXISTS` diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 5d4e2956a2a..91d88c066e7 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -169,6 +169,11 @@ Some command arguments/replies have changed to align more closely to data types - `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] - `TIME`: `Date` -> `[unixTimestamp: string, microseconds: string]` - `ZMPOP`: `{ elements: Array<{ member: string; score: number; }>; }` -> `{ members: Array<{ value: string; score: number; }>; }` to match other sorted set commands (e.g. `ZRANGE`, `ZSCAN`) +- `XGROUP_CREATECONSUMER`: [^boolean-to-number] +- `XGROUP_DESTROY`: [^boolean-to-number] +- `XINFO GROUPS`: `lastDeliveredId` -> `last-delivered-id` [^map-keys] +- `XINFO STREAM`: `radixTreeKeys` -> `radix-tree-keys`, `radixTreeNodes` -> `radix-tree-nodes`, `lastGeneratedId` -> `last-generated-id`, `maxDeletedEntryId` -> `max-deleted-entry-id`, `entriesAdded` -> `entries-added`, `recordedFirstEntryId` -> `recorded-first-entry-id`, `firstEntry` -> `first-entry`, `lastEntry` -> `last-entry` +- `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record }>; }>` -> `Record }>>` [^enum-to-constants]: TODO diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 4816f39d5a1..53f4d8a7427 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -6,7 +6,7 @@ export type RESP_TYPES = typeof RESP_TYPES; export type RespTypes = RESP_TYPES[keyof RESP_TYPES]; -type RespType< +export type RespType< RESP_TYPE extends RespTypes, DEFAULT, TYPES = never, @@ -114,7 +114,7 @@ type MapKeyValue = [key: BlobStringReply, value: unknown]; type MapTuples = Array; export type TuplesToMapReply = RespType< - RESP_TYPES['MAP'], + RESP_TYPES['MAP'], { [P in T[number] as P[0] extends BlobStringReply ? S : never]: P[1]; }, diff --git a/packages/client/lib/commands/BITPOS.ts b/packages/client/lib/commands/BITPOS.ts index 5f8a1031a45..5d6276dffc0 100644 --- a/packages/client/lib/commands/BITPOS.ts +++ b/packages/client/lib/commands/BITPOS.ts @@ -13,11 +13,11 @@ export default { ) { const args = ['BITPOS', key, bit.toString()]; - if (typeof start === 'number') { + if (start !== undefined) { args.push(start.toString()); } - if (typeof end === 'number') { + if (end !== undefined) { args.push(end.toString()); } diff --git a/packages/client/lib/commands/LASTSAVE.spec.ts b/packages/client/lib/commands/LASTSAVE.spec.ts index db282374a97..224ad364d9b 100644 --- a/packages/client/lib/commands/LASTSAVE.spec.ts +++ b/packages/client/lib/commands/LASTSAVE.spec.ts @@ -11,6 +11,9 @@ describe('LASTSAVE', () => { }); testUtils.testWithClient('client.lastSave', async client => { - assert.ok(typeof await client.lastSave() === 'number'); + assert.equal( + typeof await client.lastSave(), + 'number' + ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LPOS_COUNT.ts b/packages/client/lib/commands/LPOS_COUNT.ts index 91bf602f39c..1b057cff1f6 100644 --- a/packages/client/lib/commands/LPOS_COUNT.ts +++ b/packages/client/lib/commands/LPOS_COUNT.ts @@ -12,13 +12,13 @@ export default { ) { const args = ['LPOS', key, element]; - if (typeof options?.RANK === 'number') { + if (options?.RANK !== undefined) { args.push('RANK', options.RANK.toString()); } args.push('COUNT', count.toString()); - if (typeof options?.MAXLEN === 'number') { + if (options?.MAXLEN !== undefined) { args.push('MAXLEN', options.MAXLEN.toString()); } diff --git a/packages/client/lib/commands/SADD.ts b/packages/client/lib/commands/SADD.ts index d3f164e7af7..2ff5e9263c3 100644 --- a/packages/client/lib/commands/SADD.ts +++ b/packages/client/lib/commands/SADD.ts @@ -1,12 +1,9 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, - transformArguments( - key: RedisArgument, - members: Array | RedisArgument - ) { + transformArguments(key: RedisArgument, members: RedisVariadicArgument) { return pushVariadicArguments(['SADD', key], members); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/SDIFF.ts b/packages/client/lib/commands/SDIFF.ts index 895a48da260..918cbf7fa15 100644 --- a/packages/client/lib/commands/SDIFF.ts +++ b/packages/client/lib/commands/SDIFF.ts @@ -1,12 +1,10 @@ -import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments( - keys: Array | RedisArgument - ) { + transformArguments(keys: RedisVariadicArgument) { return pushVariadicArguments(['SDIFF'], keys); }, transformReply: undefined as unknown as () => ArrayReply diff --git a/packages/client/lib/commands/SDIFFSTORE.ts b/packages/client/lib/commands/SDIFFSTORE.ts index 526469d69ba..15f0ccb499a 100644 --- a/packages/client/lib/commands/SDIFFSTORE.ts +++ b/packages/client/lib/commands/SDIFFSTORE.ts @@ -1,12 +1,9 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, - transformArguments( - destination: RedisArgument, - keys: Array | RedisArgument - ) { + transformArguments(destination: RedisArgument, keys: RedisVariadicArgument) { return pushVariadicArguments(['SDIFFSTORE', destination], keys); }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/client/lib/commands/SINTER.ts b/packages/client/lib/commands/SINTER.ts index d5c0fbc98d6..f3f27de2e38 100644 --- a/packages/client/lib/commands/SINTER.ts +++ b/packages/client/lib/commands/SINTER.ts @@ -1,12 +1,10 @@ -import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments( - keys: Array | RedisArgument - ) { + transformArguments(keys: RedisVariadicArgument) { return pushVariadicArguments(['SINTER'], keys); }, transformReply: undefined as unknown as () => ArrayReply diff --git a/packages/client/lib/commands/SINTERCARD.ts b/packages/client/lib/commands/SINTERCARD.ts index 41d4626249e..626bc1048c3 100644 --- a/packages/client/lib/commands/SINTERCARD.ts +++ b/packages/client/lib/commands/SINTERCARD.ts @@ -1,5 +1,5 @@ -import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushVariadicArgument } from './generic-transformers'; +import { NumberReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers'; export interface SInterCardOptions { LIMIT?: number; @@ -9,7 +9,7 @@ export default { FIRST_KEY_INDEX: 2, IS_READ_ONLY: true, transformArguments( - keys: Array | RedisArgument, + keys: RedisVariadicArgument, options?: SInterCardOptions | number // `number` for backwards compatibility ) { const args = pushVariadicArgument(['SINTERCARD'], keys); diff --git a/packages/client/lib/commands/XACK.spec.ts b/packages/client/lib/commands/XACK.spec.ts index dd44debe2a1..35eed370893 100644 --- a/packages/client/lib/commands/XACK.spec.ts +++ b/packages/client/lib/commands/XACK.spec.ts @@ -6,22 +6,22 @@ describe('XACK', () => { describe('transformArguments', () => { it('string', () => { assert.deepEqual( - XACK.transformArguments('key', 'group', '1-0'), - ['XACK', 'key', 'group', '1-0'] + XACK.transformArguments('key', 'group', '0-0'), + ['XACK', 'key', 'group', '0-0'] ); }); it('array', () => { assert.deepEqual( - XACK.transformArguments('key', 'group', ['1-0', '2-0']), - ['XACK', 'key', 'group', '1-0', '2-0'] + XACK.transformArguments('key', 'group', ['0-0', '1-0']), + ['XACK', 'key', 'group', '0-0', '1-0'] ); }); }); testUtils.testAll('xAck', async client => { assert.equal( - await client.xAck('key', 'group', '1-0'), + await client.xAck('key', 'group', '0-0'), 0 ); }, { diff --git a/packages/client/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts index c32c3baf8d9..b7a04734a3f 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.ts @@ -1,39 +1,47 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { StreamMessagesReply, transformStreamMessagesReply } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// export interface XAutoClaimOptions { -// COUNT?: number; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// consumer: RedisCommandArgument, -// minIdleTime: number, -// start: string, -// options?: XAutoClaimOptions -// ): RedisCommandArguments { -// const args = ['XAUTOCLAIM', key, group, consumer, minIdleTime.toString(), start]; - -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// return args; -// } - -// type XAutoClaimRawReply = [RedisCommandArgument, Array]; - -// interface XAutoClaimReply { -// nextId: RedisCommandArgument; -// messages: StreamMessagesReply; -// } - -// export function transformReply(reply: XAutoClaimRawReply): XAutoClaimReply { -// return { -// nextId: reply[0], -// messages: transformStreamMessagesReply(reply[1]) -// }; -// } +import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types'; +import { StreamMessagesRawReply, transformStreamMessagesReply } from './generic-transformers'; + +export interface XAutoClaimOptions { + COUNT?: number; +} + +export type XAutoClaimRawReply = TuplesReply<[ + nextId: BlobStringReply, + messages: StreamMessagesRawReply, + deletedMessages: ArrayReply +]>; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + consumer: RedisArgument, + minIdleTime: number, + start: RedisArgument, + options?: XAutoClaimOptions + ) { + const args = [ + 'XAUTOCLAIM', + key, + group, + consumer, + minIdleTime.toString(), + start + ]; + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; + }, + transformReply(reply: XAutoClaimRawReply) { + return { + nextId: reply[0], + messages: transformStreamMessagesReply(reply[1]), + deletedMessages: reply[2] + }; + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts index 3f6374d9850..2dc0961bc24 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts @@ -1,25 +1,25 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformArguments as transformXAutoClaimArguments } from './XAUTOCLAIM'; +import { TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types'; +import XAUTOCLAIM from './XAUTOCLAIM'; -// export { FIRST_KEY_INDEX } from './XAUTOCLAIM'; +type XAutoClaimJustIdRawReply = TuplesReply<[ + nextId: BlobStringReply, + messages: ArrayReply, + deletedMessages: ArrayReply +]>; -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformXAutoClaimArguments(...args), -// 'JUSTID' -// ]; -// } - -// type XAutoClaimJustIdRawReply = [RedisCommandArgument, Array]; - -// interface XAutoClaimJustIdReply { -// nextId: RedisCommandArgument; -// messages: Array; -// } - -// export function transformReply(reply: XAutoClaimJustIdRawReply): XAutoClaimJustIdReply { -// return { -// nextId: reply[0], -// messages: reply[1] -// }; -// } +export default { + FIRST_KEY_INDEX: XAUTOCLAIM.FIRST_KEY_INDEX, + IS_READ_ONLY: XAUTOCLAIM.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = XAUTOCLAIM.transformArguments(...args); + redisArgs.push('JUSTID'); + return redisArgs; + }, + transformReply(reply: XAutoClaimJustIdRawReply) { + return { + nextId: reply[0], + messages: reply[1], + deletedMessages: reply[2] + }; + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XCLAIM.spec.ts b/packages/client/lib/commands/XCLAIM.spec.ts index a9f6879cfa1..ffe2deeaaeb 100644 --- a/packages/client/lib/commands/XCLAIM.spec.ts +++ b/packages/client/lib/commands/XCLAIM.spec.ts @@ -1,90 +1,106 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XCLAIM'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XCLAIM from './XCLAIM'; -// describe('XCLAIM', () => { -// describe('transformArguments', () => { -// it('single id (string)', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0'), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0'] -// ); -// }); +describe('XCLAIM', () => { + describe('transformArguments', () => { + it('single id (string)', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0'), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0'] + ); + }); -// it('multiple ids (array)', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0'] -// ); -// }); + it('multiple ids (array)', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0'] + ); + }); -// it('with IDLE', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// IDLE: 1 -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1'] -// ); -// }); + it('with IDLE', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + IDLE: 1 + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1'] + ); + }); + + describe('with TIME', () => { + it('number', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + TIME: 1 + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1'] + ); + }); + + it('Date', () => { + const d = new Date(); + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + TIME: d + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()] + ); + }); + }); -// it('with TIME (number)', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// TIME: 1 -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1'] -// ); -// }); + it('with RETRYCOUNT', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + RETRYCOUNT: 1 + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1'] + ); + }); -// it('with TIME (date)', () => { -// const d = new Date(); -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// TIME: d -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()] -// ); -// }); + it('with FORCE', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + FORCE: true + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE'] + ); + }); -// it('with RETRYCOUNT', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// RETRYCOUNT: 1 -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1'] -// ); -// }); + it('with LASTID', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + LASTID: '0-0' + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'LASTID', '0-0'] + ); + }); -// it('with FORCE', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// FORCE: true -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE'] -// ); -// }); + it('with IDLE, TIME, RETRYCOUNT, FORCE, LASTID', () => { + assert.deepEqual( + XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + IDLE: 1, + TIME: 1, + RETRYCOUNT: 1, + FORCE: true, + LASTID: '0-0' + }), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE', 'LASTID', '0-0'] + ); + }); + }); -// it('with IDLE, TIME, RETRYCOUNT, FORCE, JUSTID', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// IDLE: 1, -// TIME: 1, -// RETRYCOUNT: 1, -// FORCE: true -// }), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE'] -// ); -// }); -// }); + // TODO: test with messages + testUtils.testAll('xClaim', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xClaim('key', 'group', 'consumer', 1, '0-0') + ]); -// testUtils.testWithClient('client.xClaim', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); - -// assert.deepEqual( -// await client.xClaim('key', 'group', 'consumer', 1, '0-0'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.deepEqual(reply, []); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts index 6c1328441aa..2c04123976e 100644 --- a/packages/client/lib/commands/XCLAIM.ts +++ b/packages/client/lib/commands/XCLAIM.ts @@ -1,48 +1,54 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 1; - -// export interface XClaimOptions { -// IDLE?: number; -// TIME?: number | Date; -// RETRYCOUNT?: number; -// FORCE?: true; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// consumer: RedisCommandArgument, -// minIdleTime: number, -// id: RedisCommandArgument | Array, -// options?: XClaimOptions -// ): RedisCommandArguments { -// const args = pushVariadicArguments( -// ['XCLAIM', key, group, consumer, minIdleTime.toString()], -// id -// ); - -// if (options?.IDLE) { -// args.push('IDLE', options.IDLE.toString()); -// } - -// if (options?.TIME) { -// args.push( -// 'TIME', -// (typeof options.TIME === 'number' ? options.TIME : options.TIME.getTime()).toString() -// ); -// } - -// if (options?.RETRYCOUNT) { -// args.push('RETRYCOUNT', options.RETRYCOUNT.toString()); -// } - -// if (options?.FORCE) { -// args.push('FORCE'); -// } - -// return args; -// } - -// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +import { RedisArgument, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments, transformStreamMessagesReply } from './generic-transformers'; + +export interface XClaimOptions { + IDLE?: number; + TIME?: number | Date; + RETRYCOUNT?: number; + FORCE?: boolean; + LASTID?: RedisArgument; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + consumer: RedisArgument, + minIdleTime: number, + id: RedisVariadicArgument, + options?: XClaimOptions + ) { + const args = pushVariadicArguments( + ['XCLAIM', key, group, consumer, minIdleTime.toString()], + id + ); + + if (options?.IDLE !== undefined) { + args.push('IDLE', options.IDLE.toString()); + } + + if (options?.TIME !== undefined) { + args.push( + 'TIME', + (options.TIME instanceof Date ? options.TIME.getTime() : options.TIME).toString() + ); + } + + if (options?.RETRYCOUNT !== undefined) { + args.push('RETRYCOUNT', options.RETRYCOUNT.toString()); + } + + if (options?.FORCE) { + args.push('FORCE'); + } + + if (options?.LASTID !== undefined) { + args.push('LASTID', options.LASTID); + } + + return args; + }, + transformReply: transformStreamMessagesReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts index 88fe59084b5..3110293e856 100644 --- a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts @@ -1,23 +1,24 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XCLAIM_JUSTID'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XCLAIM_JUSTID from './XCLAIM_JUSTID'; -// describe('XCLAIM JUSTID', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0'), -// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] -// ); -// }); +describe('XCLAIM JUSTID', () => { + it('transformArguments', () => { + assert.deepEqual( + XCLAIM_JUSTID.transformArguments('key', 'group', 'consumer', 1, '0-0'), + ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] + ); + }); -// testUtils.testWithClient('client.xClaimJustId', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + // TODO: test with messages + testUtils.testWithClient('client.xClaimJustId', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xClaimJustId('key', 'group', 'consumer', 1, '0-0') + ]); -// assert.deepEqual( -// await client.xClaimJustId('key', 'group', 'consumer', 1, '0-0'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.deepEqual(reply, []); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/XCLAIM_JUSTID.ts b/packages/client/lib/commands/XCLAIM_JUSTID.ts index 7c011e692fc..6200c9106e1 100644 --- a/packages/client/lib/commands/XCLAIM_JUSTID.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.ts @@ -1,13 +1,13 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { transformArguments as transformXClaimArguments } from './XCLAIM'; +import { ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import XCLAIM from './XCLAIM'; -// export { FIRST_KEY_INDEX } from './XCLAIM'; - -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformXClaimArguments(...args), -// 'JUSTID' -// ]; -// } - -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: XCLAIM.FIRST_KEY_INDEX, + IS_READ_ONLY: XCLAIM.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = XCLAIM.transformArguments(...args); + redisArgs.push('JUSTID'); + return redisArgs; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XGROUP_CREATE.spec.ts b/packages/client/lib/commands/XGROUP_CREATE.spec.ts index 831db73e682..3428f052512 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.spec.ts @@ -1,32 +1,44 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XGROUP_CREATE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './XGROUP_CREATE'; -// describe('XGROUP CREATE', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '$'), -// ['XGROUP', 'CREATE', 'key', 'group', '$'] -// ); -// }); +describe('XGROUP CREATE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', 'group', '$'), + ['XGROUP', 'CREATE', 'key', 'group', '$'] + ); + }); -// it('with MKSTREAM', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '$', { -// MKSTREAM: true -// }), -// ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM'] -// ); -// }); -// }); + it('with MKSTREAM', () => { + assert.deepEqual( + transformArguments('key', 'group', '$', { + MKSTREAM: true + }), + ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM'] + ); + }); -// testUtils.testWithClient('client.xGroupCreate', async client => { -// assert.equal( -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// 'OK' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + it('with ENTRIESREAD', () => { + assert.deepEqual( + transformArguments('key', 'group', '$', { + ENTRIESREAD: 1 + }), + ['XGROUP', 'CREATE', 'key', 'group', '$', 'ENTRIESREAD', '1'] + ); + }); + }); + + testUtils.testAll('xGroupCreate', async client => { + assert.equal( + await client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + 'OK' + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XGROUP_CREATE.ts b/packages/client/lib/commands/XGROUP_CREATE.ts index def2bf39eb3..a04fcbeb044 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.ts @@ -1,24 +1,34 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; +export interface XGroupCreateOptions { + MKSTREAM?: boolean; + /** + * added in 7.0 + */ + ENTRIESREAD?: number; +} -// interface XGroupCreateOptions { -// MKSTREAM?: true; -// } +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + id: RedisArgument, + options?: XGroupCreateOptions + ) { + const args = ['XGROUP', 'CREATE', key, group, id]; -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// id: RedisCommandArgument, -// options?: XGroupCreateOptions -// ): RedisCommandArguments { -// const args = ['XGROUP', 'CREATE', key, group, id]; + if (options?.MKSTREAM) { + args.push('MKSTREAM'); + } -// if (options?.MKSTREAM) { -// args.push('MKSTREAM'); -// } + if (options?.ENTRIESREAD) { + args.push('ENTRIESREAD', options.ENTRIESREAD.toString()); + } -// return args; -// } + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -// export declare function transformReply(): RedisCommandArgument; diff --git a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts index 1338b8837a6..e959462c220 100644 --- a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts @@ -1,25 +1,28 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XGROUP_CREATECONSUMER'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XGROUP_CREATECONSUMER from './XGROUP_CREATECONSUMER'; -// describe('XGROUP CREATECONSUMER', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('XGROUP CREATECONSUMER', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer'), -// ['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer'] -// ); -// }); + it('transformArguments', () => { + assert.deepEqual( + XGROUP_CREATECONSUMER.transformArguments('key', 'group', 'consumer'), + ['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer'] + ); + }); -// testUtils.testWithClient('client.xGroupCreateConsumer', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + testUtils.testAll('xGroupCreateConsumer', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer') + ]); -// assert.equal( -// await client.xGroupCreateConsumer('key', 'group', 'consumer'), -// true -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts index 8fb9ad2ad3a..8fd21ca60de 100644 --- a/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.ts @@ -1,13 +1,14 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, Command, NumberReply } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// consumer: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XGROUP', 'CREATECONSUMER', key, group, consumer]; -// } - -// export { transformBooleanReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + consumer: RedisArgument + ) { + return ['XGROUP', 'CREATECONSUMER', key, group, consumer]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts index c1704b56192..7ec59f90c70 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts @@ -1,23 +1,26 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XGROUP_DELCONSUMER'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XGROUP_DELCONSUMER from './XGROUP_DELCONSUMER'; -// describe('XGROUP DELCONSUMER', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer'), -// ['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer'] -// ); -// }); +describe('XGROUP DELCONSUMER', () => { + it('transformArguments', () => { + assert.deepEqual( + XGROUP_DELCONSUMER.transformArguments('key', 'group', 'consumer'), + ['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer'] + ); + }); -// testUtils.testWithClient('client.xGroupDelConsumer', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + testUtils.testAll('xGroupDelConsumer', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupDelConsumer('key', 'group', 'consumer') + ]); -// assert.equal( -// await client.xGroupDelConsumer('key', 'group', 'consumer'), -// 0 -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(reply, 0); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts index ad54beaf9dc..bb10174e1c4 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts @@ -11,3 +11,18 @@ // } // export declare function transformReply(): number; + +import { RedisArgument, NumberReply, Command } from '../RESP/types'; + +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + consumer: RedisArgument + ) { + return ['XGROUP', 'DELCONSUMER', key, group, consumer]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts index 3e729337aee..4d7bd9ad2ed 100644 --- a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts @@ -1,23 +1,26 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XGROUP_DESTROY'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XGROUP_DESTROY from './XGROUP_DESTROY'; -// describe('XGROUP DESTROY', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group'), -// ['XGROUP', 'DESTROY', 'key', 'group'] -// ); -// }); +describe('XGROUP DESTROY', () => { + it('transformArguments', () => { + assert.deepEqual( + XGROUP_DESTROY.transformArguments('key', 'group'), + ['XGROUP', 'DESTROY', 'key', 'group'] + ); + }); -// testUtils.testWithClient('client.xGroupDestroy', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + testUtils.testAll('xGroupDestroy', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupDestroy('key', 'group') + ]); -// assert.equal( -// await client.xGroupDestroy('key', 'group'), -// true -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XGROUP_DESTROY.ts b/packages/client/lib/commands/XGROUP_DESTROY.ts index 077afba4dc7..6c14d9ae2bd 100644 --- a/packages/client/lib/commands/XGROUP_DESTROY.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.ts @@ -1,12 +1,13 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XGROUP', 'DESTROY', key, group]; -// } - -// export { transformBooleanReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument + ) { + return ['XGROUP', 'DESTROY', key, group]; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XGROUP_SETID.spec.ts b/packages/client/lib/commands/XGROUP_SETID.spec.ts index 6f05802ab00..e0d920627c2 100644 --- a/packages/client/lib/commands/XGROUP_SETID.spec.ts +++ b/packages/client/lib/commands/XGROUP_SETID.spec.ts @@ -1,23 +1,26 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XGROUP_SETID'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XGROUP_SETID from './XGROUP_SETID'; -// describe('XGROUP SETID', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '0'), -// ['XGROUP', 'SETID', 'key', 'group', '0'] -// ); -// }); +describe('XGROUP SETID', () => { + it('transformArguments', () => { + assert.deepEqual( + XGROUP_SETID.transformArguments('key', 'group', '0'), + ['XGROUP', 'SETID', 'key', 'group', '0'] + ); + }); -// testUtils.testWithClient('client.xGroupSetId', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + testUtils.testAll('xGroupSetId', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupSetId('key', 'group', '0') + ]); -// assert.equal( -// await client.xGroupSetId('key', 'group', '0'), -// 'OK' -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(reply, 'OK'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XGROUP_SETID.ts b/packages/client/lib/commands/XGROUP_SETID.ts index 65e1e257fb1..a23b4144335 100644 --- a/packages/client/lib/commands/XGROUP_SETID.ts +++ b/packages/client/lib/commands/XGROUP_SETID.ts @@ -1,13 +1,26 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; +export interface XGroupSetIdOptions { + /** added in 7.0 */ + ENTRIESREAD?: number; +} -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// id: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XGROUP', 'SETID', key, group, id]; -// } +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + group: RedisArgument, + id: RedisArgument, + options?: XGroupSetIdOptions + ) { + const args = ['XGROUP', 'SETID', key, group, id]; -// export declare function transformReply(): RedisCommandArgument; + if (options?.ENTRIESREAD) { + args.push('ENTRIESREAD', options.ENTRIESREAD.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts index 64f926dec14..e57ed72d8ea 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts @@ -1,43 +1,34 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './XINFO_CONSUMERS'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XINFO_CONSUMERS from './XINFO_CONSUMERS'; -// describe('XINFO CONSUMERS', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group'), -// ['XINFO', 'CONSUMERS', 'key', 'group'] -// ); -// }); +describe('XINFO CONSUMERS', () => { + it('transformArguments', () => { + assert.deepEqual( + XINFO_CONSUMERS.transformArguments('key', 'group'), + ['XINFO', 'CONSUMERS', 'key', 'group'] + ); + }); -// it('transformReply', () => { -// assert.deepEqual( -// transformReply([ -// ['name', 'Alice', 'pending', 1, 'idle', 9104628, 'inactive', 9281221], -// ['name', 'Bob', 'pending', 1, 'idle', 83841983, 'inactive', 7213871] -// ]), -// [{ -// name: 'Alice', -// pending: 1, -// idle: 9104628, -// inactive: 9281221, -// }, { -// name: 'Bob', -// pending: 1, -// idle: 83841983, -// inactive: 7213871, -// }] -// ); -// }); + testUtils.testAll('xInfoConsumers', async client => { + const [, , reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer'), + client.xInfoConsumers('key', 'group') + ]); -// testUtils.testWithClient('client.xInfoConsumers', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); - -// assert.deepEqual( -// await client.xInfoConsumers('key', 'group'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + for (const consumer of reply) { + assert.equal(typeof consumer.name, 'string'); + assert.equal(typeof consumer.pending, 'number'); + assert.equal(typeof consumer.idle, 'number'); + if (testUtils.isVersionGreaterThan([7, 2])) { + assert.equal(typeof consumer.inactive, 'number'); + } + } + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.ts b/packages/client/lib/commands/XINFO_CONSUMERS.ts index c6b3b99f180..81da67d161f 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.ts @@ -1,28 +1,31 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; +export type XInfoConsumersReply = ArrayReply, BlobStringReply], + [BlobStringReply<'pending'>, NumberReply], + [BlobStringReply<'idle'>, NumberReply], + /** added in 7.2 */ + [BlobStringReply<'inactive'>, NumberReply] +]>>; -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XINFO', 'CONSUMERS', key, group]; -// } - -// type XInfoConsumersReply = Array<{ -// name: RedisCommandArgument; -// pending: number; -// idle: number; -// inactive: number; -// }>; - -// export function transformReply(rawReply: Array): XInfoConsumersReply { -// return rawReply.map(consumer => ({ -// name: consumer[1], -// pending: consumer[3], -// idle: consumer[5], -// inactive: consumer[7] -// })); -// } +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + group: RedisArgument + ) { + return ['XINFO', 'CONSUMERS', key, group]; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply.map(consumer => ({ + name: consumer[1], + pending: consumer[3], + idle: consumer[5], + inactive: consumer[7] + })); + }, + 3: undefined as unknown as () => XInfoConsumersReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts index 7380251db6d..7ac02972d6b 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -1,48 +1,36 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './XINFO_GROUPS'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XINFO_GROUPS from './XINFO_GROUPS'; -// describe('XINFO GROUPS', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['XINFO', 'GROUPS', 'key'] -// ); -// }); +describe('XINFO GROUPS', () => { + it('transformArguments', () => { + assert.deepEqual( + XINFO_GROUPS.transformArguments('key'), + ['XINFO', 'GROUPS', 'key'] + ); + }); -// it('transformReply', () => { -// assert.deepEqual( -// transformReply([ -// ['name', 'mygroup', 'consumers', 2, 'pending', 2, 'last-delivered-id', '1588152489012-0'], -// ['name', 'some-other-group', 'consumers', 1, 'pending', 0, 'last-delivered-id', '1588152498034-0'] -// ]), -// [{ -// name: 'mygroup', -// consumers: 2, -// pending: 2, -// lastDeliveredId: '1588152489012-0' -// }, { -// name: 'some-other-group', -// consumers: 1, -// pending: 0, -// lastDeliveredId: '1588152498034-0' -// }] -// ); -// }); - -// testUtils.testWithClient('client.xInfoGroups', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); - -// assert.deepEqual( -// await client.xInfoGroups('key'), -// [{ -// name: 'group', -// consumers: 0, -// pending: 0, -// lastDeliveredId: '0-0' -// }] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xInfoGroups', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xInfoGroups('key') + ]); + + assert.deepEqual( + reply, + [{ + name: 'group', + consumers: 0, + pending: 0, + 'last-delivered-id': '0-0', + 'entries-read': null, + lag: 0 + }] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XINFO_GROUPS.ts b/packages/client/lib/commands/XINFO_GROUPS.ts index 4dac9eed857..e2e566d0e28 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.ts @@ -1,25 +1,33 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command, NullReply } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 2; +export type XInfoGroupsReply = ArrayReply, BlobStringReply], + [BlobStringReply<'consumers'>, NumberReply], + [BlobStringReply<'pending'>, NumberReply], + [BlobStringReply<'last-delivered-id'>, NumberReply], + /** added in 7.0 */ + [BlobStringReply<'entries-read'>, NumberReply | NullReply], + /** added in 7.0 */ + [BlobStringReply<'lag'>, NumberReply], +]>>; -// export const IS_READ_ONLY = true; - -// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { -// return ['XINFO', 'GROUPS', key]; -// } - -// type XInfoGroupsReply = Array<{ -// name: RedisCommandArgument; -// consumers: number; -// pending: number; -// lastDeliveredId: RedisCommandArgument; -// }>; - -// export function transformReply(rawReply: Array): XInfoGroupsReply { -// return rawReply.map(group => ({ -// name: group[1], -// consumers: group[3], -// pending: group[5], -// lastDeliveredId: group[7] -// })); -// } +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['XINFO', 'GROUPS', key]; + }, + transformReply: { + 2: (reply: Resp2Reply) => { + return reply.map(group => ({ + name: group[1], + consumers: group[3], + pending: group[5], + 'last-delivered-id': group[7], + 'entries-read': group[9], + lag: group[11] + })); + }, + 3: undefined as unknown as () => XInfoGroupsReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts index a73c4607080..0c13f27c416 100644 --- a/packages/client/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -1,72 +1,34 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, transformReply } from './XINFO_STREAM'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XINFO_STREAM from './XINFO_STREAM'; -// describe('XINFO STREAM', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['XINFO', 'STREAM', 'key'] -// ); -// }); +describe('XINFO STREAM', () => { + it('transformArguments', () => { + assert.deepEqual( + XINFO_STREAM.transformArguments('key'), + ['XINFO', 'STREAM', 'key'] + ); + }); -// it('transformReply', () => { -// assert.deepEqual( -// transformReply([ -// 'length', 2, -// 'radix-tree-keys', 1, -// 'radix-tree-nodes', 2, -// 'last-generated-id', '1538385846314-0', -// 'groups', 2, -// 'first-entry', ['1538385820729-0', ['foo', 'bar']], -// 'last-entry', ['1538385846314-0', ['field', 'value']] -// ]), -// { -// length: 2, -// radixTreeKeys: 1, -// radixTreeNodes: 2, -// groups: 2, -// lastGeneratedId: '1538385846314-0', -// firstEntry: { -// id: '1538385820729-0', -// message: Object.create(null, { -// foo: { -// value: 'bar', -// configurable: true, -// enumerable: true -// } -// }) -// }, -// lastEntry: { -// id: '1538385846314-0', -// message: Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// } -// } -// ); -// }); + testUtils.testAll('xInfoStream', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xInfoStream('key') + ]); -// testUtils.testWithClient('client.xInfoStream', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); - -// assert.deepEqual( -// await client.xInfoStream('key'), -// { -// length: 0, -// radixTreeKeys: 0, -// radixTreeNodes: 1, -// groups: 1, -// lastGeneratedId: '0-0', -// firstEntry: null, -// lastEntry: null -// } -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.deepEqual(reply, { + length: 0, + radixTreeKeys: 0, + radixTreeNodes: 1, + groups: 1, + lastGeneratedId: '0-0', + firstEntry: null, + lastEntry: null + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index 32fb83fe0a8..2dde1ea1a48 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -62,3 +62,80 @@ // return parsedReply as XInfoStreamReply; // } + +import { TuplesToMapReply, BlobStringReply, NumberReply, NullReply, Resp2Reply, Command, RespType, RESP_TYPES, RedisArgument } from '../RESP/types'; +import { StreamMessageRawReply, transformStreamMessageReply } from './generic-transformers'; + +export type XInfoStreamRawReply = TuplesToMapReply<[ + [BlobStringReply<'length'>, NumberReply], + [BlobStringReply<'radix-tree-keys'>, NumberReply], + [BlobStringReply<'radix-tree-nodes'>, NumberReply], + [BlobStringReply<'last-generated-id'>, BlobStringReply], + [BlobStringReply<'max-deleted-entry-id'>, BlobStringReply], + [BlobStringReply<'entries-added'>, NumberReply], + [BlobStringReply<'recorded-first-entry-id'>, BlobStringReply], + [BlobStringReply<'groups'>, NumberReply], + [BlobStringReply<'first-entry'>, StreamMessageRawReply | NullReply], + [BlobStringReply<'last-entry'>, StreamMessageRawReply | NullReply] +]>; + +export type XInfoStreamReply = TuplesToMapReply<[ + [BlobStringReply<'length'>, NumberReply], + [BlobStringReply<'radix-tree-keys'>, NumberReply], + [BlobStringReply<'radix-tree-nodes'>, NumberReply], + [BlobStringReply<'last-generated-id'>, BlobStringReply], + [BlobStringReply<'max-deleted-entry-id'>, BlobStringReply], + [BlobStringReply<'entries-added'>, NumberReply], + [BlobStringReply<'recorded-first-entry-id'>, BlobStringReply], + [BlobStringReply<'groups'>, NumberReply], + [BlobStringReply<'first-entry'>, ReturnType | NullReply], + [BlobStringReply<'last-entry'>, ReturnType | NullReply] +]>; + +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['XINFO', 'STREAM', key]; + }, + transformReply: { + 2(reply: Resp2Reply) { + return { + length: reply[1], + 'radix-tree-keys': reply[3], + 'radix-tree-nodes': reply[5], + 'last-generated-id': reply[7], + 'max-deleted-entry-id': reply[9], + 'entries-added': reply[11], + 'recorded-first-entry-id': reply[13], + groups: reply[15], + 'first-entry': transformEntry(reply[17]), + 'last-entry': transformEntry(reply[19]) + }; + }, + 3(reply: any) { // TODO: is there a "type safe" way to do it? + if (reply instanceof Map) { + reply.set( + 'first-entry', + transformEntry(reply.get('first-entry')) + ); + reply.set( + 'last-entry', + transformEntry(reply.get('last-entry')) + ); + } else if (reply instanceof Array) { + reply[17] = transformEntry(reply[17]); + reply[19] = transformEntry(reply[19]); + } else { + reply['first-entry'] = transformEntry(reply['first-entry']); + reply['last-entry'] = transformEntry(reply['last-entry']); + } + + return reply as XInfoStreamReply; + } + } +} as const satisfies Command; + +function transformEntry(entry: StreamMessageRawReply | NullReply) { + return entry === null ? null : transformStreamMessageReply(entry); +} diff --git a/packages/client/lib/commands/XPENDING.spec.ts b/packages/client/lib/commands/XPENDING.spec.ts index bfa36d01e34..993245a5d82 100644 --- a/packages/client/lib/commands/XPENDING.spec.ts +++ b/packages/client/lib/commands/XPENDING.spec.ts @@ -1,62 +1,60 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XPENDING'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XPENDING from './XPENDING'; -// describe('XPENDING', () => { -// describe('transformArguments', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group'), -// ['XPENDING', 'key', 'group'] -// ); -// }); -// }); +describe('XPENDING', () => { + describe('transformArguments', () => { + it('transformArguments', () => { + assert.deepEqual( + XPENDING.transformArguments('key', 'group'), + ['XPENDING', 'key', 'group'] + ); + }); + }); -// describe('client.xPending', () => { -// testUtils.testWithClient('simple', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + describe('client.xPending', () => { + testUtils.testWithClient('simple', async client => { + const [, reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xPending('key', 'group') + ]); -// assert.deepEqual( -// await client.xPending('key', 'group'), -// { -// pending: 0, -// firstId: null, -// lastId: null, -// consumers: null -// } -// ); -// }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, { + pending: 0, + firstId: null, + lastId: null, + consumers: null + }); + }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('with consumers', async client => { -// const [,, id] = await Promise.all([ -// client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// client.xGroupCreateConsumer('key', 'group', 'consumer'), -// client.xAdd('key', '*', { field: 'value' }), -// client.xReadGroup('group', 'consumer', { -// key: 'key', -// id: '>' -// }) -// ]); + testUtils.testWithClient('with consumers', async client => { + const [, , id, , reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer'), + client.xAdd('key', '*', { field: 'value' }), + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }), + client.xPending('key', 'group') + ]); -// assert.deepEqual( -// await client.xPending('key', 'group'), -// { -// pending: 1, -// firstId: id, -// lastId: id, -// consumers: [{ -// name: 'consumer', -// deliveriesCounter: 1 -// }] -// } -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [6, 2] -// }); -// }); -// }); + assert.deepEqual(reply, { + pending: 1, + firstId: id, + lastId: id, + consumers: [{ + name: 'consumer', + deliveriesCounter: 1 + }] + }); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] + }); + }); +}); diff --git a/packages/client/lib/commands/XPENDING.ts b/packages/client/lib/commands/XPENDING.ts index 215295afd25..efe07ceefb6 100644 --- a/packages/client/lib/commands/XPENDING.ts +++ b/packages/client/lib/commands/XPENDING.ts @@ -1,44 +1,30 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, BlobStringReply, NullReply, TuplesReply, NumberReply, Command, ArrayReply } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; +type XPendingRawReply = TuplesReply<[ + pending: NumberReply, + firstId: BlobStringReply | NullReply, + lastId: BlobStringReply | NullReply, + consumers: ArrayReply> | NullReply +]>; -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XPENDING', key, group]; -// } - -// type XPendingRawReply = [ -// pending: number, -// firstId: RedisCommandArgument | null, -// lastId: RedisCommandArgument | null, -// consumers: Array<[ -// name: RedisCommandArgument, -// deliveriesCounter: RedisCommandArgument -// ]> | null -// ]; - -// interface XPendingReply { -// pending: number; -// firstId: RedisCommandArgument | null; -// lastId: RedisCommandArgument | null; -// consumers: Array<{ -// name: RedisCommandArgument; -// deliveriesCounter: number; -// }> | null; -// } - -// export function transformReply(reply: XPendingRawReply): XPendingReply { -// return { -// pending: reply[0], -// firstId: reply[1], -// lastId: reply[2], -// consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({ -// name, -// deliveriesCounter: Number(deliveriesCounter) -// })) -// }; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, group: RedisArgument) { + return ['XPENDING', key, group]; + }, + transformReply(reply: XPendingRawReply) { + return { + pending: reply[0], + firstId: reply[1], + lastId: reply[2], + consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({ + name, + deliveriesCounter: Number(deliveriesCounter) + })) + } + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index b08f71d88a2..2f2d75b40fe 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -1,53 +1,67 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XPENDING_RANGE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XPENDING_RANGE from './XPENDING_RANGE'; -// describe('XPENDING RANGE', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '-', '+', 1), -// ['XPENDING', 'key', 'group', '-', '+', '1'] -// ); -// }); +describe('XPENDING RANGE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1), + ['XPENDING', 'key', 'group', '-', '+', '1'] + ); + }); -// it('with IDLE', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '-', '+', 1, { -// IDLE: 1, -// }), -// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1'] -// ); -// }); + it('with IDLE', () => { + assert.deepEqual( + XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, { + IDLE: 1, + }), + ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1'] + ); + }); -// it('with consumer', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '-', '+', 1, { -// consumer: 'consumer' -// }), -// ['XPENDING', 'key', 'group', '-', '+', '1', 'consumer'] -// ); -// }); + it('with consumer', () => { + assert.deepEqual( + XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, { + consumer: 'consumer' + }), + ['XPENDING', 'key', 'group', '-', '+', '1', 'consumer'] + ); + }); -// it('with IDLE, consumer', () => { -// assert.deepEqual( -// transformArguments('key', 'group', '-', '+', 1, { -// IDLE: 1, -// consumer: 'consumer' -// }), -// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer'] -// ); -// }); -// }); + it('with IDLE, consumer', () => { + assert.deepEqual( + XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, { + IDLE: 1, + consumer: 'consumer' + }), + ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer'] + ); + }); + }); -// testUtils.testWithClient('client.xPendingRange', async client => { -// await client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }); + testUtils.testAll('xPendingRange', async client => { + const [, , id, , reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer'), + client.xAdd('key', '*', { field: 'value' }), + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }), + client.xPendingRange('key', 'group', '-', '+', 1) + ]); -// assert.deepEqual( -// await client.xPendingRange('key', 'group', '-', '+', 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.ok(Array.isArray(reply)); + assert.equal(reply.length, 1); + assert.equal(reply[0].id, id); + assert.equal(reply[0].consumer, 'consumer'); + assert.equal(typeof reply[0].millisecondsSinceLastDelivery, 'number'); + assert.equal(reply[0].deliveriesCounter, '1'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts index 37d95efd4f8..9ca37dae9c9 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.ts @@ -32,19 +32,7 @@ // return args; // } -// type XPendingRangeRawReply = Array<[ -// id: RedisCommandArgument, -// consumer: RedisCommandArgument, -// millisecondsSinceLastDelivery: number, -// deliveriesCounter: number -// ]>; - -// type XPendingRangeReply = Array<{ -// id: RedisCommandArgument; -// owner: RedisCommandArgument; -// millisecondsSinceLastDelivery: number; -// deliveriesCounter: number; -// }>; + // export function transformReply(reply: XPendingRangeRawReply): XPendingRangeReply { // return reply.map(([id, owner, millisecondsSinceLastDelivery, deliveriesCounter]) => ({ @@ -54,3 +42,56 @@ // deliveriesCounter // })); // } + +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; + +export interface XPendingRangeOptions { + IDLE?: number; + consumer?: RedisArgument; +} + +type XPendingRangeRawReply = ArrayReply>; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + group: RedisArgument, + start: RedisArgument, + end: RedisArgument, + count: number, + options?: XPendingRangeOptions + ) { + const args = ['XPENDING', key, group]; + + if (options?.IDLE !== undefined) { + args.push('IDLE', options.IDLE.toString()); + } + + args.push( + start, + end, + count.toString() + ); + + if (options?.consumer) { + args.push(options.consumer); + } + + return args; + }, + transformReply(reply: XPendingRangeRawReply) { + return reply.map(pending => ({ + id: pending[0], + consumer: pending[1], + millisecondsSinceLastDelivery: pending[2], + deliveriesCounter: pending[3] + })); + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts index 4d937c4e32a..dfcc0590641 100644 --- a/packages/client/lib/commands/XRANGE.spec.ts +++ b/packages/client/lib/commands/XRANGE.spec.ts @@ -1,30 +1,39 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XRANGE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XRANGE from './XRANGE'; -// describe('XRANGE', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', '-', '+'), -// ['XRANGE', 'key', '-', '+'] -// ); -// }); +describe('XRANGE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XRANGE.transformArguments('key', '-', '+'), + ['XRANGE', 'key', '-', '+'] + ); + }); -// it('with COUNT', () => { -// assert.deepEqual( -// transformArguments('key', '-', '+', { -// COUNT: 1 -// }), -// ['XRANGE', 'key', '-', '+', 'COUNT', '1'] -// ); -// }); -// }); + it('with COUNT', () => { + assert.deepEqual( + XRANGE.transformArguments('key', '-', '+', { + COUNT: 1 + }), + ['XRANGE', 'key', '-', '+', 'COUNT', '1'] + ); + }); + }); -// testUtils.testWithClient('client.xRange', async client => { -// assert.deepEqual( -// await client.xRange('key', '+', '-'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xRange', async client => { + const message = { field: 'value' }, + [id, reply] = await Promise.all([ + client.xAdd('key', '*', message), + client.xRange('key', '-', '+') + ]); + + assert.deepEqual(reply, [{ + id, + message + }]); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XRANGE.ts b/packages/client/lib/commands/XRANGE.ts index 1f3cf1d856e..1eed1e12b94 100644 --- a/packages/client/lib/commands/XRANGE.ts +++ b/packages/client/lib/commands/XRANGE.ts @@ -1,26 +1,29 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, Command } from '../RESP/types'; +import { transformStreamMessagesReply } from './generic-transformers'; -// export const FIRST_KEY_INDEX = 1; +export interface XRangeOptions { + COUNT?: number; +} -// export const IS_READ_ONLY = true; +export function transformXRangeArguments( + command: RedisArgument, + key: RedisArgument, + start: RedisArgument, + end: RedisArgument, + options?: XRangeOptions +) { + const args = [command, key, start, end]; -// interface XRangeOptions { -// COUNT?: number; -// } + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } -// export function transformArguments( -// key: RedisCommandArgument, -// start: RedisCommandArgument, -// end: RedisCommandArgument, -// options?: XRangeOptions -// ): RedisCommandArguments { -// const args = ['XRANGE', key, start, end]; + return args; +} -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// return args; -// } - -// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: transformXRangeArguments.bind(undefined, 'XRANGE'), + transformReply: transformStreamMessagesReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XREAD.spec.ts b/packages/client/lib/commands/XREAD.spec.ts index 13aa35b83fc..c707d6ef527 100644 --- a/packages/client/lib/commands/XREAD.spec.ts +++ b/packages/client/lib/commands/XREAD.spec.ts @@ -1,103 +1,111 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { FIRST_KEY_INDEX, transformArguments } from './XREAD'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XREAD from './XREAD'; -// describe('XREAD', () => { -// describe('FIRST_KEY_INDEX', () => { -// it('single stream', () => { -// assert.equal( -// FIRST_KEY_INDEX({ key: 'key', id: '' }), -// 'key' -// ); -// }); +describe('XREAD', () => { + describe('FIRST_KEY_INDEX', () => { + it('single stream', () => { + assert.equal( + XREAD.FIRST_KEY_INDEX({ + key: 'key', + id: '' + }), + 'key' + ); + }); -// it('multiple streams', () => { -// assert.equal( -// FIRST_KEY_INDEX([{ key: '1', id: '' }, { key: '2', id: '' }]), -// '1' -// ); -// }); -// }); + it('multiple streams', () => { + assert.equal( + XREAD.FIRST_KEY_INDEX([{ + key: '1', + id: '' + }, { + key: '2', + id: '' + }]), + '1' + ); + }); + }); -// describe('transformArguments', () => { -// it('single stream', () => { -// assert.deepEqual( -// transformArguments({ -// key: 'key', -// id: '0' -// }), -// ['XREAD', 'STREAMS', 'key', '0'] -// ); -// }); + describe('transformArguments', () => { + it('single stream', () => { + assert.deepEqual( + XREAD.transformArguments({ + key: 'key', + id: '0-0' + }), + ['XREAD', 'STREAMS', 'key', '0-0'] + ); + }); -// it('multiple streams', () => { -// assert.deepEqual( -// transformArguments([{ -// key: '1', -// id: '0' -// }, { -// key: '2', -// id: '0' -// }]), -// ['XREAD', 'STREAMS', '1', '2', '0', '0'] -// ); -// }); + it('multiple streams', () => { + assert.deepEqual( + XREAD.transformArguments([{ + key: '1', + id: '0-0' + }, { + key: '2', + id: '0-0' + }]), + ['XREAD', 'STREAMS', '1', '2', '0-0', '0-0'] + ); + }); -// it('with COUNT', () => { -// assert.deepEqual( -// transformArguments({ -// key: 'key', -// id: '0' -// }, { -// COUNT: 1 -// }), -// ['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0'] -// ); -// }); + it('with COUNT', () => { + assert.deepEqual( + XREAD.transformArguments({ + key: 'key', + id: '0-0' + }, { + COUNT: 1 + }), + ['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0-0'] + ); + }); -// it('with BLOCK', () => { -// assert.deepEqual( -// transformArguments({ -// key: 'key', -// id: '0' -// }, { -// BLOCK: 0 -// }), -// ['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0'] -// ); -// }); + it('with BLOCK', () => { + assert.deepEqual( + XREAD.transformArguments({ + key: 'key', + id: '0-0' + }, { + BLOCK: 0 + }), + ['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0-0'] + ); + }); -// it('with COUNT, BLOCK', () => { -// assert.deepEqual( -// transformArguments({ -// key: 'key', -// id: '0' -// }, { -// COUNT: 1, -// BLOCK: 0 -// }), -// ['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0'] -// ); -// }); -// }); + it('with COUNT, BLOCK', () => { + assert.deepEqual( + XREAD.transformArguments({ + key: 'key', + id: '0-0' + }, { + COUNT: 1, + BLOCK: 0 + }), + ['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0-0'] + ); + }); + }); -// testUtils.testWithClient('client.xRead', async client => { -// assert.equal( -// await client.xRead({ -// key: 'key', -// id: '0' -// }), -// null -// ); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithCluster('cluster.xRead', async cluster => { -// assert.equal( -// await cluster.xRead({ -// key: 'key', -// id: '0' -// }), -// null -// ); -// }, GLOBAL.CLUSTERS.OPEN); -// }); + // TODO + // testUtils.testAll('client.xRead', async client => { + // const message = { field: 'value' }, + // [, reply] = await Promise.all([ + // client.xAdd('key', '*', message), + // client.xRead({ + // key: 'key', + // id: '0-0' + // }) + // ]) + // assert.equal( + // await client.xRead({ + // key: 'key', + // id: '0' + // }), + // null + // ); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/XREAD.ts b/packages/client/lib/commands/XREAD.ts index f58972b1f65..2c1aa3d8277 100644 --- a/packages/client/lib/commands/XREAD.ts +++ b/packages/client/lib/commands/XREAD.ts @@ -1,46 +1,55 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { Command, RedisArgument } from '../RESP/types'; + +export interface XReadStream { + key: RedisArgument; + id: RedisArgument; +} + +export type XReadStreams = Array | XReadStream; + +export function pushXReadStreams(args: Array, streams: XReadStreams) { + args.push('STREAMS'); + + if (Array.isArray(streams)) { + const keysStart = args.length, + idsStart = keysStart + streams.length; + for (let i = 0; i < streams.length; i++) { + const stream = streams[i]; + args[keysStart + i] = stream.key; + args[idsStart + i] = stream.id; + } + } else { + args.push(streams.key, streams.id); + } +} + +export interface XReadOptions { + COUNT?: number; + BLOCK?: number; +} + +export default { + FIRST_KEY_INDEX(streams: XReadStreams) { + return Array.isArray(streams) ? streams[0].key : streams.key; + }, + IS_READ_ONLY: true, + transformArguments(streams: XReadStreams, options?: XReadOptions) { + const args: Array = ['XREAD']; + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + if (options?.BLOCK !== undefined) { + args.push('BLOCK', options.BLOCK.toString()); + } + + pushXReadStreams(args, streams); + + return args; + }, + // export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; + // TODO + transformReply: undefined as unknown as () => unknown +} as const satisfies Command; -// export const FIRST_KEY_INDEX = (streams: Array | XReadStream): RedisCommandArgument => { -// return Array.isArray(streams) ? streams[0].key : streams.key; -// }; - -// export const IS_READ_ONLY = true; - -// interface XReadStream { -// key: RedisCommandArgument; -// id: RedisCommandArgument; -// } - -// interface XReadOptions { -// COUNT?: number; -// BLOCK?: number; -// } - -// export function transformArguments( -// streams: Array | XReadStream, -// options?: XReadOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = ['XREAD']; - -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// if (typeof options?.BLOCK === 'number') { -// args.push('BLOCK', options.BLOCK.toString()); -// } - -// args.push('STREAMS'); - -// const streamsArray = Array.isArray(streams) ? streams : [streams], -// argsLength = args.length; -// for (let i = 0; i < streamsArray.length; i++) { -// const stream = streamsArray[i]; -// args[argsLength + i] = stream.key; -// args[argsLength + streamsArray.length + i] = stream.id; -// } - -// return args; -// } - -// export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XREADGROUP.spec.ts b/packages/client/lib/commands/XREADGROUP.spec.ts index 1cccdb79e65..ee23689add5 100644 --- a/packages/client/lib/commands/XREADGROUP.spec.ts +++ b/packages/client/lib/commands/XREADGROUP.spec.ts @@ -1,153 +1,137 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { FIRST_KEY_INDEX, transformArguments } from './XREADGROUP'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XREADGROUP from './XREADGROUP'; -// describe('XREADGROUP', () => { -// describe('FIRST_KEY_INDEX', () => { -// it('single stream', () => { -// assert.equal( -// FIRST_KEY_INDEX('', '', { key: 'key', id: '' }), -// 'key' -// ); -// }); +describe('XREADGROUP', () => { + describe('FIRST_KEY_INDEX', () => { + it('single stream', () => { + assert.equal( + XREADGROUP.FIRST_KEY_INDEX('', '', { key: 'key', id: '' }), + 'key' + ); + }); -// it('multiple streams', () => { -// assert.equal( -// FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]), -// '1' -// ); -// }); -// }); + it('multiple streams', () => { + assert.equal( + XREADGROUP.FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]), + '1' + ); + }); + }); -// describe('transformArguments', () => { -// it('single stream', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', { -// key: 'key', -// id: '0' -// }), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0'] -// ); -// }); + describe('transformArguments', () => { + it('single stream', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', { + key: 'key', + id: '0-0' + }), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0-0'] + ); + }); -// it('multiple streams', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', [{ -// key: '1', -// id: '0' -// }, { -// key: '2', -// id: '0' -// }]), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0', '0'] -// ); -// }); + it('multiple streams', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', [{ + key: '1', + id: '0-0' + }, { + key: '2', + id: '0-0' + }]), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0-0', '0-0'] + ); + }); -// it('with COUNT', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', { -// key: 'key', -// id: '0' -// }, { -// COUNT: 1 -// }), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0'] -// ); -// }); + it('with COUNT', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', { + key: 'key', + id: '0-0' + }, { + COUNT: 1 + }), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0-0'] + ); + }); -// it('with BLOCK', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', { -// key: 'key', -// id: '0' -// }, { -// BLOCK: 0 -// }), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0'] -// ); -// }); + it('with BLOCK', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', { + key: 'key', + id: '0-0' + }, { + BLOCK: 0 + }), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0-0'] + ); + }); -// it('with NOACK', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', { -// key: 'key', -// id: '0' -// }, { -// NOACK: true -// }), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0'] -// ); -// }); + it('with NOACK', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', { + key: 'key', + id: '0-0' + }, { + NOACK: true + }), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0-0'] + ); + }); -// it('with COUNT, BLOCK, NOACK', () => { -// assert.deepEqual( -// transformArguments('group', 'consumer', { -// key: 'key', -// id: '0' -// }, { -// COUNT: 1, -// BLOCK: 0, -// NOACK: true -// }), -// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0'] -// ); -// }); -// }); + it('with COUNT, BLOCK, NOACK', () => { + assert.deepEqual( + XREADGROUP.transformArguments('group', 'consumer', { + key: 'key', + id: '0-0' + }, { + COUNT: 1, + BLOCK: 0, + NOACK: true + }), + ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0-0'] + ); + }); + }); -// describe('client.xReadGroup', () => { -// testUtils.testWithClient('null', async client => { -// const [, readGroupReply] = await Promise.all([ -// client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// client.xReadGroup('group', 'consumer', { -// key: 'key', -// id: '>' -// }) -// ]); + // testUtils.testAll('xReadGroup - null', async client => { + // const [, readGroupReply] = await Promise.all([ + // client.xGroupCreate('key', 'group', '$', { + // MKSTREAM: true + // }), + // client.xReadGroup('group', 'consumer', { + // key: 'key', + // id: '>' + // }) + // ]); -// assert.equal(readGroupReply, null); -// }, GLOBAL.SERVERS.OPEN); + // assert.equal(readGroupReply, null); + // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('with a message', async client => { -// const [, id, readGroupReply] = await Promise.all([ -// client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// client.xAdd('key', '*', { field: 'value' }), -// client.xReadGroup('group', 'consumer', { -// key: 'key', -// id: '>' -// }) -// ]); + // testUtils.testAll('xReadGroup - with a message', async client => { + // const [, id, readGroupReply] = await Promise.all([ + // client.xGroupCreate('key', 'group', '$', { + // MKSTREAM: true + // }), + // client.xAdd('key', '*', { field: 'value' }), + // client.xReadGroup('group', 'consumer', { + // key: 'key', + // id: '>' + // }) + // ]); -// assert.deepEqual(readGroupReply, [{ -// name: 'key', -// messages: [{ -// id, -// message: Object.create(null, { -// field: { -// value: 'value', -// configurable: true, -// enumerable: true -// } -// }) -// }] -// }]); -// }, GLOBAL.SERVERS.OPEN); -// }); - -// testUtils.testWithCluster('cluster.xReadGroup', async cluster => { -// const [, readGroupReply] = await Promise.all([ -// cluster.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// cluster.xReadGroup('group', 'consumer', { -// key: 'key', -// id: '>' -// }) -// ]); - -// assert.equal(readGroupReply, null); -// }, GLOBAL.CLUSTERS.OPEN); -// }); + // assert.deepEqual(readGroupReply, [{ + // name: 'key', + // messages: [{ + // id, + // message: Object.create(null, { + // field: { + // value: 'value', + // configurable: true, + // enumerable: true + // } + // }) + // }] + // }]); + // }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/XREADGROUP.ts b/packages/client/lib/commands/XREADGROUP.ts index 40064934cd6..f1a2782208f 100644 --- a/packages/client/lib/commands/XREADGROUP.ts +++ b/packages/client/lib/commands/XREADGROUP.ts @@ -1,57 +1,46 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export interface XReadGroupStream { -// key: RedisCommandArgument; -// id: RedisCommandArgument; -// } - -// export interface XReadGroupOptions { -// COUNT?: number; -// BLOCK?: number; -// NOACK?: true; -// } - -// export const FIRST_KEY_INDEX = ( -// _group: RedisCommandArgument, -// _consumer: RedisCommandArgument, -// streams: Array | XReadGroupStream -// ): RedisCommandArgument => { -// return Array.isArray(streams) ? streams[0].key : streams.key; -// }; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// group: RedisCommandArgument, -// consumer: RedisCommandArgument, -// streams: Array | XReadGroupStream, -// options?: XReadGroupOptions -// ): RedisCommandArguments { -// const args = ['XREADGROUP', 'GROUP', group, consumer]; - -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// if (typeof options?.BLOCK === 'number') { -// args.push('BLOCK', options.BLOCK.toString()); -// } - -// if (options?.NOACK) { -// args.push('NOACK'); -// } - -// args.push('STREAMS'); - -// const streamsArray = Array.isArray(streams) ? streams : [streams], -// argsLength = args.length; -// for (let i = 0; i < streamsArray.length; i++) { -// const stream = streamsArray[i]; -// args[argsLength + i] = stream.key; -// args[argsLength + streamsArray.length + i] = stream.id; -// } - -// return args; -// } - -// export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; +import { Command, RedisArgument } from '../RESP/types'; +import XREAD, { XReadStreams, pushXReadStreams } from './XREAD'; + +export interface XReadGroupOptions { + COUNT?: number; + BLOCK?: number; + NOACK?: boolean; +} + +export default { + FIRST_KEY_INDEX( + _group: RedisArgument, + _consumer: RedisArgument, + streams: XReadStreams + ) { + return XREAD.FIRST_KEY_INDEX(streams); + }, + IS_READ_ONLY: true, + transformArguments( + group: RedisArgument, + consumer: RedisArgument, + streams: XReadStreams, + options?: XReadGroupOptions + ) { + const args = ['XREADGROUP', group, consumer]; + + if (options?.COUNT !== undefined) { + args.push('COUNT', options.COUNT.toString()); + } + + if (options?.BLOCK !== undefined) { + args.push('BLOCK', options.BLOCK.toString()); + } + + if (options?.NOACK) { + args.push('NOACK'); + } + + pushXReadStreams(args, streams); + + return args; + }, + // export { transformStreamsMessagesReply as transformReply } from './generic-transformers'; + // TODO + transformReply: undefined as unknown as () => unknown +} as const satisfies Command; diff --git a/packages/client/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts index 344edd62e58..f935f3bcdd8 100644 --- a/packages/client/lib/commands/XREVRANGE.spec.ts +++ b/packages/client/lib/commands/XREVRANGE.spec.ts @@ -1,30 +1,39 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XREVRANGE'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XREVRANGE from './XREVRANGE'; -// describe('XREVRANGE', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', '-', '+'), -// ['XREVRANGE', 'key', '-', '+'] -// ); -// }); +describe('XREVRANGE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XREVRANGE.transformArguments('key', '-', '+'), + ['XREVRANGE', 'key', '-', '+'] + ); + }); -// it('with COUNT', () => { -// assert.deepEqual( -// transformArguments('key', '-', '+', { -// COUNT: 1 -// }), -// ['XREVRANGE', 'key', '-', '+', 'COUNT', '1'] -// ); -// }); -// }); + it('with COUNT', () => { + assert.deepEqual( + XREVRANGE.transformArguments('key', '-', '+', { + COUNT: 1 + }), + ['XREVRANGE', 'key', '-', '+', 'COUNT', '1'] + ); + }); + }); -// testUtils.testWithClient('client.xRevRange', async client => { -// assert.deepEqual( -// await client.xRevRange('key', '+', '-'), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('xRevRange', async client => { + const message = { field: 'value' }, + [id, reply] = await Promise.all([ + client.xAdd('key', '*', message), + client.xRevRange('key', '-', '+') + ]); + + assert.deepEqual(reply, [{ + id, + message + }]); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XREVRANGE.ts b/packages/client/lib/commands/XREVRANGE.ts index de095dc0297..86e4d8abc9e 100644 --- a/packages/client/lib/commands/XREVRANGE.ts +++ b/packages/client/lib/commands/XREVRANGE.ts @@ -1,26 +1,13 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// interface XRangeRevOptions { -// COUNT?: number; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// start: RedisCommandArgument, -// end: RedisCommandArgument, -// options?: XRangeRevOptions -// ): RedisCommandArguments { -// const args = ['XREVRANGE', key, start, end]; - -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// return args; -// } - -// export { transformStreamMessagesReply as transformReply } from './generic-transformers'; +import { Command } from '../RESP/types'; +import XRANGE, { transformXRangeArguments } from './XRANGE'; + +export interface XRevRangeOptions { + COUNT?: number; +} + +export default { + FIRST_KEY_INDEX: XRANGE.FIRST_KEY_INDEX, + IS_READ_ONLY: XRANGE.IS_READ_ONLY, + transformArguments: transformXRangeArguments.bind(undefined, 'XREVRANGE'), + transformReply: XRANGE.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/XSETID.ts b/packages/client/lib/commands/XSETID.ts index bd3a8fd0bc1..a2ac8af0011 100644 --- a/packages/client/lib/commands/XSETID.ts +++ b/packages/client/lib/commands/XSETID.ts @@ -1,6 +1,8 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export interface XSetIdOptions { + /** added in 7.0 */ ENTRIESADDED?: number; + /** added in 7.0 */ MAXDELETEDID?: RedisArgument; } diff --git a/packages/client/lib/commands/XTRIM.ts b/packages/client/lib/commands/XTRIM.ts index edbb11f3ea0..0512323a32a 100644 --- a/packages/client/lib/commands/XTRIM.ts +++ b/packages/client/lib/commands/XTRIM.ts @@ -2,6 +2,7 @@ import { NumberReply, Command, RedisArgument } from '../RESP/types'; export interface XTrimOptions { strategyModifier?: '=' | '~'; + /** added in 6.2 */ LIMIT?: number; } @@ -12,7 +13,8 @@ export default { key: RedisArgument, strategy: 'MAXLEN' | 'MINID', threshold: number, - options?: XTrimOptions) { + options?: XTrimOptions + ) { const args = ['XTRIM', key, strategy]; if (options?.strategyModifier) { diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 03884ac44ad..8298a966d8a 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -58,39 +58,37 @@ export function transformTuplesReply( return message; } -export interface StreamMessageReply { - id: RedisArgument; - message: Record; -} - -export type StreamMessagesReply = Array; +export type StreamMessageRawReply = TuplesReply<[ + id: BlobStringReply, + message: ArrayReply +]>; -export function transformStreamMessagesReply(reply: Array): StreamMessagesReply { - const messages = []; +export function transformStreamMessageReply([id, message]: StreamMessageRawReply) { + return { + id, + message: transformTuplesReply(message) + }; +} - for (const [id, message] of reply) { - messages.push({ - id, - message: transformTuplesReply(message) - }); - } +export type StreamMessagesRawReply = ArrayReply; - return messages; +export function transformStreamMessagesReply(reply: StreamMessagesRawReply) { + return reply.map(transformStreamMessageReply); } -export type StreamsMessagesReply = Array<{ - name: RedisArgument; - messages: StreamMessagesReply; -}> | null; +// export type StreamsMessagesReply = Array<{ +// name: RedisArgument; +// messages: StreamMessagesReply; +// }> | null; -export function transformStreamsMessagesReply(reply: Array | null): StreamsMessagesReply | null { - if (reply === null) return null; +// export function transformStreamsMessagesReply(reply: Array | null): StreamsMessagesReply | null { +// if (reply === null) return null; - return reply.map(([name, rawMessages]) => ({ - name, - messages: transformStreamMessagesReply(rawMessages) - })); -} +// return reply.map(([name, rawMessages]) => ({ +// name, +// messages: transformStreamMessagesReply(rawMessages) +// })); +// } export interface SortedSetMember { value: RedisArgument; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 6537d899133..cca2f9f128b 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -253,10 +253,28 @@ import WATCH from './WATCH'; import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; +import XAUTOCLAIM_JUSTID from './XAUTOCLAIM_JUSTID'; +import XAUTOCLAIM from './XAUTOCLAIM'; +import XCLAIM_JUSTID from './XCLAIM_JUSTID'; +import XCLAIM from './XCLAIM'; import XDEL from './XDEL'; +import XGROUP_CREATE from './XGROUP_CREATE'; +import XGROUP_CREATECONSUMER from './XGROUP_CREATECONSUMER'; +import XGROUP_DELCONSUMER from './XGROUP_DELCONSUMER'; +import XGROUP_DESTROY from './XGROUP_DESTROY'; +import XGROUP_SETID from './XGROUP_SETID'; +import XINFO_CONSUMERS from './XINFO_CONSUMERS'; +import XINFO_GROUPS from './XINFO_GROUPS'; +import XINFO_STREAM from './XINFO_STREAM'; +import XLEN from './XLEN'; +import XPENDING_RANGE from './XPENDING_RANGE'; +import XPENDING from './XPENDING'; +import XRANGE from './XRANGE'; +import XREAD from './XREAD'; +import XREADGROUP from './XREADGROUP'; +import XREVRANGE from './XREVRANGE'; import XSETID from './XSETID'; import XTRIM from './XTRIM'; -import XLEN from './XLEN'; import ZADD_INCR from './ZADD_INCR'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; @@ -554,10 +572,28 @@ type WATCH = typeof import('./WATCH').default; type XACK = typeof import('./XACK').default; type XADD_NOMKSTREAM = typeof import('./XADD_NOMKSTREAM').default; type XADD = typeof import('./XADD').default; +type XAUTOCLAIM_JUSTID = typeof import('./XAUTOCLAIM_JUSTID').default; +type XAUTOCLAIM = typeof import('./XAUTOCLAIM').default; +type XCLAIM_JUSTID = typeof import('./XCLAIM_JUSTID').default; +type XCLAIM = typeof import('./XCLAIM').default; type XDEL = typeof import('./XDEL').default; +type XGROUP_CREATE = typeof import('./XGROUP_CREATE').default; +type XGROUP_CREATECONSUMER = typeof import('./XGROUP_CREATECONSUMER').default; +type XGROUP_DELCONSUMER = typeof import('./XGROUP_DELCONSUMER').default; +type XGROUP_DESTROY = typeof import('./XGROUP_DESTROY').default; +type XGROUP_SETID = typeof import('./XGROUP_SETID').default; +type XINFO_CONSUMERS = typeof import('./XINFO_CONSUMERS').default; +type XINFO_GROUPS = typeof import('./XINFO_GROUPS').default; +type XINFO_STREAM = typeof import('./XINFO_STREAM').default; +type XLEN = typeof import('./XLEN').default; +type XPENDING_RANGE = typeof import('./XPENDING_RANGE').default; +type XPENDING = typeof import('./XPENDING').default; +type XRANGE = typeof import('./XRANGE').default; +type XREAD = typeof import('./XREAD').default; +type XREADGROUP = typeof import('./XREADGROUP').default; +type XREVRANGE = typeof import('./XREVRANGE').default; type XSETID = typeof import('./XSETID').default; type XTRIM = typeof import('./XTRIM').default; -type XLEN = typeof import('./XLEN').default; type ZADD_INCR = typeof import('./ZADD_INCR').default; type ZADD = typeof import('./ZADD').default; type ZCARD = typeof import('./ZCARD').default; @@ -1112,14 +1148,50 @@ type Commands = { xAddNoMkStream: XADD_NOMKSTREAM; XADD: XADD; xAdd: XADD; + XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID; + xAutoClaimJustId: XAUTOCLAIM_JUSTID; + XAUTOCLAIM: XAUTOCLAIM; + xAutoClaim: XAUTOCLAIM; + XCLAIM_JUSTID: XCLAIM_JUSTID; + xClaimJustId: XCLAIM_JUSTID; + XCLAIM: XCLAIM; + xClaim: XCLAIM; XDEL: XDEL; xDel: XDEL; + XGROUP_CREATE: XGROUP_CREATE; + xGroupCreate: XGROUP_CREATE; + XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER; + xGroupCreateConsumer: XGROUP_CREATECONSUMER; + XGROUP_DELCONSUMER: XGROUP_DELCONSUMER; + xGroupDelConsumer: XGROUP_DELCONSUMER; + XGROUP_DESTROY: XGROUP_DESTROY; + xGroupDestroy: XGROUP_DESTROY; + XGROUP_SETID: XGROUP_SETID; + xGroupSetId: XGROUP_SETID; + XINFO_CONSUMERS: XINFO_CONSUMERS; + xInfoConsumers: XINFO_CONSUMERS; + XINFO_GROUPS: XINFO_GROUPS; + xInfoGroups: XINFO_GROUPS; + XINFO_STREAM: XINFO_STREAM; + xInfoStream: XINFO_STREAM; + XLEN: XLEN; + xLen: XLEN; + XPENDING_RANGE: XPENDING_RANGE; + xPendingRange: XPENDING_RANGE; + XPENDING: XPENDING; + xPending: XPENDING; + XRANGE: XRANGE; + xRange: XRANGE; + XREAD: XREAD; + xRead: XREAD; + XREADGROUP: XREADGROUP; + xReadGroup: XREADGROUP; + XREVRANGE: XREVRANGE; + xRevRange: XREVRANGE; XSETID: XSETID; xSetId: XSETID; XTRIM: XTRIM; xTrim: XTRIM; - XLEN: XLEN; - xLen: XLEN; ZADD_INCR: ZADD_INCR; zAddIncr: ZADD_INCR; ZADD: ZADD; @@ -1715,14 +1787,50 @@ export default { xAddNoMkStream: XADD_NOMKSTREAM, XADD, xAdd: XADD, + XAUTOCLAIM_JUSTID, + xAutoClaimJustId: XAUTOCLAIM_JUSTID, + XAUTOCLAIM, + xAutoClaim: XAUTOCLAIM, + XCLAIM_JUSTID, + xClaimJustId: XCLAIM_JUSTID, + XCLAIM, + xClaim: XCLAIM, XDEL, xDel: XDEL, + XGROUP_CREATE, + xGroupCreate: XGROUP_CREATE, + XGROUP_CREATECONSUMER, + xGroupCreateConsumer: XGROUP_CREATECONSUMER, + XGROUP_DELCONSUMER, + xGroupDelConsumer: XGROUP_DELCONSUMER, + XGROUP_DESTROY, + xGroupDestroy: XGROUP_DESTROY, + XGROUP_SETID, + xGroupSetId: XGROUP_SETID, + XINFO_CONSUMERS, + xInfoConsumers: XINFO_CONSUMERS, + XINFO_GROUPS, + xInfoGroups: XINFO_GROUPS, + XINFO_STREAM, + xInfoStream: XINFO_STREAM, + XLEN, + xLen: XLEN, + XPENDING_RANGE, + xPendingRange: XPENDING_RANGE, + XPENDING, + xPending: XPENDING, + XRANGE, + xRange: XRANGE, + XREAD, + xRead: XREAD, + XREADGROUP, + xReadGroup: XREADGROUP, + XREVRANGE, + xRevRange: XREVRANGE, XSETID, xSetId: XSETID, XTRIM, xTrim: XTRIM, - XLEN, - xLen: XLEN, ZADD_INCR, zAddIncr: ZADD_INCR, ZADD, diff --git a/test/package-lock.json b/test/package-lock.json index 2419e2490cf..878a92a6ad2 100644 --- a/test/package-lock.json +++ b/test/package-lock.json @@ -9,69 +9,19 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@redis/client": "^1.5.7", - "ioredis": "^5.3.2", - "local": "file:../packages/client", - "redis": "^4.6.6", - "redis-om": "^0.3.6" - } - }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "next" } }, "node_modules/@redis/client": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz", - "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==", + "version": "2.0.0-next.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-2.0.0-next.2.tgz", + "integrity": "sha512-+sf9n+PBHac2xXSofSX0x79cYa5H4ighu80F993q4H1T109ZthFNGBmg33DfwfPrDMKc256qTXvsb0lCqzwMmg==", "dependencies": { "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" + "generic-pool": "3.9.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/graph": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", - "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", - "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz", - "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", - "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node": ">=16" } }, "node_modules/cluster-key-slot": { @@ -82,30 +32,6 @@ "node": ">=0.10.0" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -113,120 +39,6 @@ "engines": { "node": ">= 4" } - }, - "node_modules/ioredis": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", - "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", - "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, - "node_modules/local": { - "name": "@redis/client", - "version": "2.0.0-next.1", - "resolved": "file:../packages/client", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/redis": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz", - "integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==", - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.5.7", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.2", - "@redis/time-series": "1.0.4" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-om": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/redis-om/-/redis-om-0.3.6.tgz", - "integrity": "sha512-WRmrAm1n1EQIQbEwbfqpceuxHgr7LKOZ471c/KGxyOTVFFm53E0S7vFSZA7a1Jnga7aHTOYqLhhMWE0lKKdsNw==", - "dependencies": { - "redis": "^4.0.4", - "ulid": "^2.3.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "node_modules/ulid": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", - "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", - "bin": { - "ulid": "bin/cli.js" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/test/package.json b/test/package.json index f7fbbbf5d16..23ca20e0589 100644 --- a/test/package.json +++ b/test/package.json @@ -10,10 +10,6 @@ "author": "", "license": "ISC", "dependencies": { - "@redis/client": "^1.5.7", - "ioredis": "^5.3.2", - "local": "file:../packages/client", - "redis": "^4.6.6", - "redis-om": "^0.3.6" + "@redis/client": "next" } } diff --git a/test/test.js b/test/test.js index 8d9b54bc278..f9b83cae7aa 100644 --- a/test/test.js +++ b/test/test.js @@ -1,26 +1,21 @@ -import { createClient } from '@redis/client'; -import { setTimeout } from 'node:timers/promises'; +import { RESP_TYPES, createClient } from '@redis/client'; -const client = createClient(); +const client = createClient({ + RESP: 3, + commandOptions: { + typeMapping: { + [RESP_TYPES.MAP]: Map + } + } +}); client.on('error', err => console.error(err)); await client.connect(); -await client.set('key', 'a'.repeat(1_000)); - -throw 'a'; - -while (true) { - const promises = []; - for (let i = 0; i < 20_000; i++) { - promises.push(client.sendCommand(['HMSET', `aa${i.toString()}`, 'txt1', Math.random().toString()])); - } - - await Promise.all(promises); - console.log( - await client.dbSize(), - (await client.info('MEMORY')).split('\n')[1] - ); +console.log( + await client.flushAll(), + await client.hSet('key', 'field', 'value'), + await client.hGetAll('key') +) - await setTimeout(1000); -} +client.destroy(); From c109fbf751f79791ff4412ee8fe037adb426273c Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 29 Jun 2023 14:39:49 -0400 Subject: [PATCH 148/325] wip --- packages/client/lib/commands/BGSAVE.spec.ts | 4 +- packages/client/lib/commands/BLMOVE.spec.ts | 62 +++++----- packages/client/lib/commands/BLMPOP.spec.ts | 63 ++++++---- packages/client/lib/commands/BLMPOP.ts | 11 +- packages/client/lib/commands/BLPOP.spec.ts | 109 ++++++------------ packages/client/lib/commands/BLPOP.ts | 2 +- packages/client/lib/commands/BRPOP.spec.ts | 109 ++++++------------ .../client/lib/commands/BRPOPLPUSH.spec.ts | 73 ++++++------ packages/client/lib/commands/BZMPOP.spec.ts | 69 +++++++---- packages/client/lib/commands/BZMPOP.ts | 45 ++------ packages/client/lib/commands/BZPOPMAX.spec.ts | 96 +++++++-------- packages/client/lib/commands/BZPOPMAX.ts | 66 ++++++----- packages/client/lib/commands/BZPOPMIN.spec.ts | 96 +++++++-------- packages/client/lib/commands/BZPOPMIN.ts | 27 ++--- packages/client/lib/commands/HGETALL.spec.ts | 3 +- packages/client/lib/commands/LMPOP.spec.ts | 19 ++- packages/client/lib/commands/LMPOP.ts | 19 +-- .../client/lib/commands/XAUTOCLAIM.spec.ts | 91 +++++++++------ .../lib/commands/XAUTOCLAIM_JUSTID.spec.ts | 60 +++++----- .../client/lib/commands/XGROUP_CREATE.spec.ts | 10 +- .../client/lib/commands/XGROUP_DELCONSUMER.ts | 14 --- .../client/lib/commands/XINFO_STREAM.spec.ts | 13 ++- packages/client/lib/commands/XINFO_STREAM.ts | 65 ----------- .../lib/commands/XPENDING_RANGE.spec.ts | 2 +- .../client/lib/commands/XPENDING_RANGE.ts | 45 -------- packages/client/lib/commands/XRANGE.spec.ts | 16 ++- packages/client/lib/commands/XREADGROUP.ts | 2 +- .../client/lib/commands/XREVRANGE.spec.ts | 16 ++- packages/client/lib/commands/ZADD.spec.ts | 2 +- .../client/lib/commands/ZADD_INCR.spec.ts | 2 +- packages/client/lib/commands/ZMPOP.ts | 37 +++--- packages/client/lib/commands/ZPOPMAX.ts | 22 +++- .../client/lib/commands/ZPOPMAX_COUNT.spec.ts | 7 +- packages/client/lib/commands/ZPOPMIN.ts | 22 +--- .../client/lib/commands/ZPOPMIN_COUNT.spec.ts | 5 +- packages/client/lib/commands/index.ts | 18 +++ 36 files changed, 593 insertions(+), 729 deletions(-) diff --git a/packages/client/lib/commands/BGSAVE.spec.ts b/packages/client/lib/commands/BGSAVE.spec.ts index b8e82e21278..51817cbc0fb 100644 --- a/packages/client/lib/commands/BGSAVE.spec.ts +++ b/packages/client/lib/commands/BGSAVE.spec.ts @@ -23,7 +23,9 @@ describe('BGSAVE', () => { testUtils.testWithClient('client.bgSave', async client => { assert.equal( - typeof await client.bgSave(), + typeof await client.bgSave({ + SCHEDULE: true // using `SCHEDULE` to make sure it won't throw an error + }), 'string' ); }, GLOBAL.SERVERS.OPEN); diff --git a/packages/client/lib/commands/BLMOVE.spec.ts b/packages/client/lib/commands/BLMOVE.spec.ts index 3b86c1ec91e..3afda7f8a01 100644 --- a/packages/client/lib/commands/BLMOVE.spec.ts +++ b/packages/client/lib/commands/BLMOVE.spec.ts @@ -1,43 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BLMOVE'; -import { commandOptions } from '../../index'; +import BLMOVE from './BLMOVE'; describe('BLMOVE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination', 'LEFT', 'RIGHT', 0), - ['BLMOVE', 'source', 'destination', 'LEFT', 'RIGHT', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BLMOVE.transformArguments('source', 'destination', 'LEFT', 'RIGHT', 0), + ['BLMOVE', 'source', 'destination', 'LEFT', 'RIGHT', '0'] + ); + }); - testUtils.testWithClient('client.blMove', async client => { - const [blMoveReply] = await Promise.all([ - client.blMove(commandOptions({ - isolated: true - }), 'source', 'destination', 'LEFT', 'RIGHT', 0), - client.lPush('source', 'element') - ]); + testUtils.testAll('blMove - null', async client => { + assert.equal( + await client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', Number.MIN_VALUE), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); - assert.equal( - blMoveReply, - 'element' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.blMove', async cluster => { - const [blMoveReply] = await Promise.all([ - cluster.blMove(commandOptions({ - isolated: true - }), '{tag}source', '{tag}destination', 'LEFT', 'RIGHT', 0), - cluster.lPush('{tag}source', 'element') - ]); - - assert.equal( - blMoveReply, - 'element' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('blMove - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('{tag}source', 'element'), + client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', Number.MIN_VALUE) + ]); + assert.equal(reply, 'element'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts index 15853a771b0..6e87446ca81 100644 --- a/packages/client/lib/commands/BLMPOP.spec.ts +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -1,32 +1,49 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BLMPOP'; +import BLMPOP from './BLMPOP'; describe('BLMPOP', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(0, 'key', 'LEFT'), - ['BLMPOP', '0', '1', 'key', 'LEFT'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + BLMPOP.transformArguments(0, 'key', 'LEFT'), + ['BLMPOP', '0', '1', 'key', 'LEFT'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments(0, 'key', 'LEFT', { - COUNT: 2 - }), - ['BLMPOP', '0', '1', 'key', 'LEFT', 'COUNT', '2'] - ); - }); + it('with COUNT', () => { + assert.deepEqual( + BLMPOP.transformArguments(0, 'key', 'LEFT', { + COUNT: 1 + }), + ['BLMPOP', '0', '1', 'key', 'LEFT', 'COUNT', '1'] + ); }); + }); + + testUtils.testAll('blmPop - null', async client => { + assert.equal( + await client.blmPop(Number.MIN_VALUE, 'key', 'RIGHT'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); - testUtils.testWithClient('client.blmPop', async client => { - assert.deepEqual( - await client.blmPop(1, 'key', 'RIGHT'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('blmPop - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('key', 'element'), + client.blmPop(Number.MIN_VALUE, 'key', 'RIGHT') + ]); + assert.deepEqual(reply, [ + 'key', + ['element'] + ]); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BLMPOP.ts b/packages/client/lib/commands/BLMPOP.ts index 971b87edeff..3122e908600 100644 --- a/packages/client/lib/commands/BLMPOP.ts +++ b/packages/client/lib/commands/BLMPOP.ts @@ -1,21 +1,16 @@ import { Command } from '../RESP/types'; -import { ListSide, RedisVariadicArgument } from './generic-transformers'; -import LMPOP, { LMPopOptions, transformLMPopArguments } from './LMPOP'; +import LMPOP, { LMPopArguments, transformLMPopArguments } from './LMPOP'; export default { FIRST_KEY_INDEX: 3, IS_READ_ONLY: false, transformArguments( timeout: number, - keys: RedisVariadicArgument, - side: ListSide, - options?: LMPopOptions + ...args: LMPopArguments ) { return transformLMPopArguments( ['BLMPOP', timeout.toString()], - keys, - side, - options + ...args ); }, transformReply: LMPOP.transformReply diff --git a/packages/client/lib/commands/BLPOP.spec.ts b/packages/client/lib/commands/BLPOP.spec.ts index 84920c851e1..35b9d95396a 100644 --- a/packages/client/lib/commands/BLPOP.spec.ts +++ b/packages/client/lib/commands/BLPOP.spec.ts @@ -1,79 +1,46 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './BLPOP'; -import { commandOptions } from '../../index'; +import BLPOP from './BLPOP'; describe('BLPOP', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments('key', 0), - ['BLPOP', 'key', '0'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments(['key1', 'key2'], 0), - ['BLPOP', 'key1', 'key2', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + BLPOP.transformArguments('key', 0), + ['BLPOP', 'key', '0'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.equal( - transformReply(null), - null - ); - }); - - it('member', () => { - assert.deepEqual( - transformReply(['key', 'element']), - { - key: 'key', - element: 'element' - } - ); - }); + it('multiple', () => { + assert.deepEqual( + BLPOP.transformArguments(['1', '2'], 0), + ['BLPOP', '1', '2', '0'] + ); }); - - testUtils.testWithClient('client.blPop', async client => { - const [ blPopReply ] = await Promise.all([ - client.blPop( - commandOptions({ isolated: true }), - 'key', - 1 - ), - client.lPush('key', 'element'), - ]); - - assert.deepEqual( - blPopReply, - { - key: 'key', - element: 'element' - } - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.blPop', async cluster => { - const [ blPopReply ] = await Promise.all([ - cluster.blPop( - commandOptions({ isolated: true }), - 'key', - 1 - ), - cluster.lPush('key', 'element') - ]); - - assert.deepEqual( - blPopReply, - { - key: 'key', - element: 'element' - } - ); - }, GLOBAL.CLUSTERS.OPEN); + }); + + testUtils.testAll('blPop - null', async client => { + assert.equal( + await client.blPop('key', Number.MIN_VALUE), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('blPop - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('key', 'element'), + client.blPop('key', 1) + ]); + + assert.deepEqual(reply, { + key: 'key', + element: 'element' + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BLPOP.ts b/packages/client/lib/commands/BLPOP.ts index e96617e21d4..c40a18b3c80 100644 --- a/packages/client/lib/commands/BLPOP.ts +++ b/packages/client/lib/commands/BLPOP.ts @@ -8,7 +8,7 @@ export default { key: RedisVariadicArgument, timeout: number ) { - const args = pushVariadicArguments(['BRPOP'], key); + const args = pushVariadicArguments(['BLPOP'], key); args.push(timeout.toString()); return args; }, diff --git a/packages/client/lib/commands/BRPOP.spec.ts b/packages/client/lib/commands/BRPOP.spec.ts index fc203e1abdf..f484036acad 100644 --- a/packages/client/lib/commands/BRPOP.spec.ts +++ b/packages/client/lib/commands/BRPOP.spec.ts @@ -1,79 +1,46 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './BRPOP'; -import { commandOptions } from '../../index'; +import BRPOP from './BRPOP'; describe('BRPOP', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments('key', 0), - ['BRPOP', 'key', '0'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments(['key1', 'key2'], 0), - ['BRPOP', 'key1', 'key2', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + BRPOP.transformArguments('key', 0), + ['BRPOP', 'key', '0'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.equal( - transformReply(null), - null - ); - }); - - it('member', () => { - assert.deepEqual( - transformReply(['key', 'element']), - { - key: 'key', - element: 'element' - } - ); - }); + it('multiple', () => { + assert.deepEqual( + BRPOP.transformArguments(['1', '2'], 0), + ['BRPOP', '1', '2', '0'] + ); }); - - testUtils.testWithClient('client.brPop', async client => { - const [ brPopReply ] = await Promise.all([ - client.brPop( - commandOptions({ isolated: true }), - 'key', - 1 - ), - client.lPush('key', 'element'), - ]); - - assert.deepEqual( - brPopReply, - { - key: 'key', - element: 'element' - } - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.brPop', async cluster => { - const [ brPopReply ] = await Promise.all([ - cluster.brPop( - commandOptions({ isolated: true }), - 'key', - 1 - ), - cluster.lPush('key', 'element'), - ]); - - assert.deepEqual( - brPopReply, - { - key: 'key', - element: 'element' - } - ); - }, GLOBAL.CLUSTERS.OPEN); + }); + + testUtils.testAll('brPop - null', async client => { + assert.equal( + await client.brPop('key', Number.MIN_VALUE), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('brPopblPop - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('key', 'element'), + client.brPop('key', 1) + ]); + + assert.deepEqual(reply, { + key: 'key', + element: 'element' + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BRPOPLPUSH.spec.ts b/packages/client/lib/commands/BRPOPLPUSH.spec.ts index 214af4553ac..1c1484868bd 100644 --- a/packages/client/lib/commands/BRPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/BRPOPLPUSH.spec.ts @@ -1,47 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BRPOPLPUSH'; -import { commandOptions } from '../../index'; +import BRPOPLPUSH from './BRPOPLPUSH'; describe('BRPOPLPUSH', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination', 0), - ['BRPOPLPUSH', 'source', 'destination', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BRPOPLPUSH.transformArguments('source', 'destination', 0), + ['BRPOPLPUSH', 'source', 'destination', '0'] + ); + }); - testUtils.testWithClient('client.brPopLPush', async client => { - const [ popReply ] = await Promise.all([ - client.brPopLPush( - commandOptions({ isolated: true }), - 'source', - 'destination', - 0 - ), - client.lPush('source', 'element') - ]); + testUtils.testAll('brPopLPush - null', async client => { + assert.equal( + await client.brPopLPush( + '{tag}source', + '{tag}destination', + Number.MIN_VALUE + ), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); - assert.equal( - popReply, - 'element' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('brPopLPush - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('{tag}source', 'element'), + client.brPopLPush( + '{tag}source', + '{tag}destination', + 0 + ) + ]); - testUtils.testWithCluster('cluster.brPopLPush', async cluster => { - const [ popReply ] = await Promise.all([ - cluster.brPopLPush( - commandOptions({ isolated: true }), - '{tag}source', - '{tag}destination', - 0 - ), - cluster.lPush('{tag}source', 'element') - ]); - - assert.equal( - popReply, - 'element' - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply, 'element'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BZMPOP.spec.ts b/packages/client/lib/commands/BZMPOP.spec.ts index 0e381c114f2..60bc3fe4712 100644 --- a/packages/client/lib/commands/BZMPOP.spec.ts +++ b/packages/client/lib/commands/BZMPOP.spec.ts @@ -1,32 +1,55 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './BZMPOP'; +import BZMPOP from './BZMPOP'; describe('BZMPOP', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(0, 'key', 'MIN'), - ['BZMPOP', '0', '1', 'key', 'MIN'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + BZMPOP.transformArguments(0, 'key', 'MIN'), + ['BZMPOP', '0', '1', 'key', 'MIN'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments(0, 'key', 'MIN', { - COUNT: 2 - }), - ['BZMPOP', '0', '1', 'key', 'MIN', 'COUNT', '2'] - ); - }); + it('with COUNT', () => { + assert.deepEqual( + BZMPOP.transformArguments(0, 'key', 'MIN', { + COUNT: 2 + }), + ['BZMPOP', '0', '1', 'key', 'MIN', 'COUNT', '2'] + ); }); + }); + + testUtils.testAll('bzmPop - null', async client => { + assert.equal( + await client.bzmPop(Number.MIN_VALUE, 'key', 'MAX'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); - testUtils.testWithClient('client.bzmPop', async client => { - assert.deepEqual( - await client.bzmPop(1, 'key', 'MAX'), - null - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bzmPop - with member', async client => { + const key = 'key', + member = { + value: 'a', + score: 1 + }, + [, reply] = await Promise.all([ + client.zAdd(key, member), + client.bzmPop(Number.MIN_VALUE, key, 'MAX') + ]); + + assert.deepEqual(reply, { + key, + members: [member] + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BZMPOP.ts b/packages/client/lib/commands/BZMPOP.ts index b043d5fcf64..030aa20c66b 100644 --- a/packages/client/lib/commands/BZMPOP.ts +++ b/packages/client/lib/commands/BZMPOP.ts @@ -1,34 +1,11 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { SortedSetSide, transformZMPopArguments, ZMPopOptions } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 3; - -// export function transformArguments( -// timeout: number, -// keys: RedisCommandArgument | Array, -// side: SortedSetSide, -// options?: ZMPopOptions -// ): RedisCommandArguments { -// return transformZMPopArguments( -// ['BZMPOP', timeout.toString()], -// keys, -// side, -// options -// ); -// } - -// export { transformReply } from './ZMPOP'; - - -// import { Command } from '../RESP/types'; -// import ZMPOP from './ZMPOP'; - -// export default { -// FIRST_KEY_INDEX: 3, -// IS_READ_ONLY: false, -// transformArguments() { -// return ['BZMPOP']; -// }, -// transformReply: ZMPOP.transformReply -// } as const satisfies Command; - +import { Command } from '../RESP/types'; +import ZMPOP, { ZMPopArguments, transformZMPopArguments } from './ZMPOP'; + +export default { + FIRST_KEY_INDEX: 3, + IS_READ_ONLY: false, + transformArguments(timeout: number, ...args: ZMPopArguments) { + return transformZMPopArguments(['BZMPOP', timeout.toString()], ...args); + }, + transformReply: ZMPOP.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/BZPOPMAX.spec.ts b/packages/client/lib/commands/BZPOPMAX.spec.ts index d5c17437122..64fb6b85b7d 100644 --- a/packages/client/lib/commands/BZPOPMAX.spec.ts +++ b/packages/client/lib/commands/BZPOPMAX.spec.ts @@ -1,65 +1,51 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './BZPOPMAX'; -import { commandOptions } from '../../index'; +import BZPOPMAX from './BZPOPMAX'; describe('BZPOPMAX', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments('key', 0), - ['BZPOPMAX', 'key', '0'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments(['1', '2'], 0), - ['BZPOPMAX', '1', '2', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + BZPOPMAX.transformArguments('key', 0), + ['BZPOPMAX', 'key', '0'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.equal( - transformReply(null), - null - ); - }); - - it('member', () => { - assert.deepEqual( - transformReply(['key', 'value', '1']), - { - key: 'key', - value: 'value', - score: 1 - } - ); - }); + it('multiple', () => { + assert.deepEqual( + BZPOPMAX.transformArguments(['1', '2'], 0), + ['BZPOPMAX', '1', '2', '0'] + ); }); + }); - testUtils.testWithClient('client.bzPopMax', async client => { - const [ bzPopMaxReply ] = await Promise.all([ - client.bzPopMax( - commandOptions({ isolated: true }), - 'key', - 1 - ), - client.zAdd('key', [{ - value: '1', - score: 1 - }]) - ]); + testUtils.testAll('bzPopMax - null', async client => { + assert.equal( + await client.bzPopMax('key', Number.MIN_VALUE), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); - assert.deepEqual( - bzPopMaxReply, - { - key: 'key', - value: '1', - score: 1 - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bzPopMax - with member', async client => { + const key = 'key', + member = { + value: 'a', + score: 1 + }, + [, reply] = await Promise.all([ + client.zAdd(key, member), + client.bzPopMax(key, Number.MIN_VALUE) + ]); + + assert.deepEqual(reply, { + key, + ...member + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BZPOPMAX.ts b/packages/client/lib/commands/BZPOPMAX.ts index 250bc982b45..64059f1f784 100644 --- a/packages/client/lib/commands/BZPOPMAX.ts +++ b/packages/client/lib/commands/BZPOPMAX.ts @@ -1,29 +1,39 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments, transformDoubleReply, ZMember } from './generic-transformers'; +import { RedisArgument, Command, NullReply, TuplesReply, BlobStringReply, DoubleReply } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; + +export function transformBZPopArguments( + command: RedisArgument, + key: RedisVariadicArgument, + timeout: number +) { + const args = pushVariadicArguments([command], key); + args.push(timeout.toString()); + return args; +} + +export type BZPopArguments = typeof transformBZPopArguments extends (_: any, ...args: infer T) => any ? T : never; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(...args: BZPopArguments) { + return transformBZPopArguments('BZPOPMAX', ...args); + }, + transformReply: { + 2: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, BlobStringReply]>) => { + return reply === null ? null : { + key: reply[0], + value: reply[1], + score: Number(reply[2]) + }; + }, + 3: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, DoubleReply]>) => { + return reply === null ? null : { + key: reply[0], + value: reply[1], + score: reply[2] + }; + } + } +} as const satisfies Command; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument | Array, -// timeout: number -// ): RedisCommandArguments { -// const args = pushVariadicArguments(['BZPOPMAX'], key); - -// args.push(timeout.toString()); - -// return args; -// } - -// type ZMemberRawReply = [key: RedisCommandArgument, value: RedisCommandArgument, score: RedisCommandArgument] | null; - -// type BZPopMaxReply = (ZMember & { key: RedisCommandArgument }) | null; - -// export function transformReply(reply: ZMemberRawReply): BZPopMaxReply | null { -// if (!reply) return null; - -// return { -// key: reply[0], -// value: reply[1], -// score: transformDoubleReply(reply[2]) -// }; -// } diff --git a/packages/client/lib/commands/BZPOPMIN.spec.ts b/packages/client/lib/commands/BZPOPMIN.spec.ts index 0573a4ac898..399c8f30b96 100644 --- a/packages/client/lib/commands/BZPOPMIN.spec.ts +++ b/packages/client/lib/commands/BZPOPMIN.spec.ts @@ -1,65 +1,51 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './BZPOPMIN'; -import { commandOptions } from '../../index'; +import BZPOPMIN from './BZPOPMIN'; describe('BZPOPMIN', () => { - describe('transformArguments', () => { - it('single', () => { - assert.deepEqual( - transformArguments('key', 0), - ['BZPOPMIN', 'key', '0'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments(['1', '2'], 0), - ['BZPOPMIN', '1', '2', '0'] - ); - }); + describe('transformArguments', () => { + it('single', () => { + assert.deepEqual( + BZPOPMIN.transformArguments('key', 0), + ['BZPOPMIN', 'key', '0'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.equal( - transformReply(null), - null - ); - }); - - it('member', () => { - assert.deepEqual( - transformReply(['key', 'value', '1']), - { - key: 'key', - value: 'value', - score: 1 - } - ); - }); + it('multiple', () => { + assert.deepEqual( + BZPOPMIN.transformArguments(['1', '2'], 0), + ['BZPOPMIN', '1', '2', '0'] + ); }); + }); - testUtils.testWithClient('client.bzPopMin', async client => { - const [ bzPopMinReply ] = await Promise.all([ - client.bzPopMin( - commandOptions({ isolated: true }), - 'key', - 1 - ), - client.zAdd('key', [{ - value: '1', - score: 1 - }]) - ]); + testUtils.testAll('bzPopMin - null', async client => { + assert.equal( + await client.bzPopMin('key', Number.MIN_VALUE), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); - assert.deepEqual( - bzPopMinReply, - { - key: 'key', - value: '1', - score: 1 - } - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('bzPopMin - with member', async client => { + const key = 'key', + member = { + value: 'a', + score: 1 + }, + [, reply] = await Promise.all([ + client.zAdd(key, member), + client.bzPopMin(key, Number.MIN_VALUE) + ]); + + assert.deepEqual(reply, { + key, + ...member + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/BZPOPMIN.ts b/packages/client/lib/commands/BZPOPMIN.ts index 967633697a4..f27e623528e 100644 --- a/packages/client/lib/commands/BZPOPMIN.ts +++ b/packages/client/lib/commands/BZPOPMIN.ts @@ -1,17 +1,12 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { pushVariadicArguments } from './generic-transformers'; +import { Command } from '../RESP/types'; +import BZPOPMAX, { BZPopArguments, transformBZPopArguments } from './BZPOPMAX'; + +export default { + FIRST_KEY_INDEX: BZPOPMAX.FIRST_KEY_INDEX, + IS_READ_ONLY: BZPOPMAX.IS_READ_ONLY, + transformArguments(...args: BZPopArguments) { + return transformBZPopArguments('BZPOPMIN', ...args); + }, + transformReply: BZPOPMAX.transformReply +} as const satisfies Command; -// export const FIRST_KEY_INDEX = 1; - -// export function transformArguments( -// key: RedisCommandArgument | Array, -// timeout: number -// ): RedisCommandArguments { -// const args = pushVariadicArguments(['BZPOPMIN'], key); - -// args.push(timeout.toString()); - -// return args; -// } - -// export { transformReply } from './BZPOPMAX'; diff --git a/packages/client/lib/commands/HGETALL.spec.ts b/packages/client/lib/commands/HGETALL.spec.ts index 9a9a30feaf8..28e1dacf834 100644 --- a/packages/client/lib/commands/HGETALL.spec.ts +++ b/packages/client/lib/commands/HGETALL.spec.ts @@ -23,8 +23,7 @@ describe('HGETALL', () => { Object.create(null, { field: { value: 'value', - enumerable: true, - writable: true + enumerable: true } }) ); diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts index ae9c2b69260..78a0cdd9cce 100644 --- a/packages/client/lib/commands/LMPOP.spec.ts +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -23,8 +23,8 @@ describe('LMPOP', () => { }); }); - testUtils.testAll('lmPop', async client => { - assert.deepEqual( + testUtils.testAll('lmPop - null', async client => { + assert.equal( await client.lmPop('key', 'RIGHT'), null ); @@ -32,4 +32,19 @@ describe('LMPOP', () => { client: GLOBAL.SERVERS.OPEN, cluster: GLOBAL.SERVERS.OPEN }); + + testUtils.testAll('lmPop - with member', async client => { + const [, reply] = await Promise.all([ + client.lPush('key', 'element'), + client.lmPop('key', 'RIGHT') + ]); + + assert.deepEqual(reply, [ + 'key', + ['element'] + ]); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.SERVERS.OPEN + }); }); diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts index b828f47f066..49f7272ec46 100644 --- a/packages/client/lib/commands/LMPOP.ts +++ b/packages/client/lib/commands/LMPOP.ts @@ -11,31 +11,24 @@ export function transformLMPopArguments( side: ListSide, options?: LMPopOptions ): CommandArguments { - pushVariadicArgument(args, keys); + args = pushVariadicArgument(args, keys); args.push(side); - if (options?.COUNT) { + if (options?.COUNT !== undefined) { args.push('COUNT', options.COUNT.toString()); } return args; } +export type LMPopArguments = typeof transformLMPopArguments extends (_: any, ...args: infer T) => any ? T : never; + export default { FIRST_KEY_INDEX: 2, IS_READ_ONLY: false, - transformArguments( - keys: RedisVariadicArgument, - side: ListSide, - options?: LMPopOptions - ) { - return transformLMPopArguments( - ['LMPOP'], - keys, - side, - options - ); + transformArguments(...args: LMPopArguments) { + return transformLMPopArguments(['LMPOP'], ...args); }, transformReply: undefined as unknown as () => NullReply | TuplesReply<[ key: BlobStringReply, diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index 80382db8d22..bb4b1d65942 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -1,42 +1,59 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XAUTOCLAIM'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XAUTOCLAIM from './XAUTOCLAIM'; -// describe('XAUTOCLAIM', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('XAUTOCLAIM', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0'), -// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0'] -// ); -// }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + XAUTOCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0'), + ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0'] + ); + }); -// it('with COUNT', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0', { -// COUNT: 1 -// }), -// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'COUNT', '1'] -// ); -// }); -// }); + it('with COUNT', () => { + assert.deepEqual( + XAUTOCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', { + COUNT: 1 + }), + ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'COUNT', '1'] + ); + }); + }); -// testUtils.testWithClient('client.xAutoClaim', async client => { -// await Promise.all([ -// client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// client.xGroupCreateConsumer('key', 'group', 'consumer'), -// ]); + testUtils.testAll('xAutoClaim', async client => { + const message = Object.create(null, { + field: { + value: 'value', + enumerable: true + } + }); -// assert.deepEqual( -// await client.xAutoClaim('key', 'group', 'consumer', 1, '0-0'), -// { -// nextId: '0-0', -// messages: [] -// } -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + const [, , id, , reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer'), + client.xAdd('key', '*', message), + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }), + client.xAutoClaim('key', 'group', 'consumer', 0, '0-0') + ]); + + assert.deepEqual(reply, { + nextId: '0-0', + messages: [{ + id, + message + }], + deletedMessages: testUtils.isVersionGreaterThan([7, 0]) ? [] : undefined + }); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts index ed7b80cabfc..872d19100f1 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts @@ -1,31 +1,37 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './XAUTOCLAIM_JUSTID'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import XAUTOCLAIM_JUSTID from './XAUTOCLAIM_JUSTID'; -// describe('XAUTOCLAIM JUSTID', () => { -// testUtils.isVersionGreaterThanHook([6, 2]); +describe('XAUTOCLAIM JUSTID', () => { + testUtils.isVersionGreaterThanHook([6, 2]); -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key', 'group', 'consumer', 1, '0-0'), -// ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] -// ); -// }); + it('transformArguments', () => { + assert.deepEqual( + XAUTOCLAIM_JUSTID.transformArguments('key', 'group', 'consumer', 1, '0-0'), + ['XAUTOCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID'] + ); + }); -// testUtils.testWithClient('client.xAutoClaimJustId', async client => { -// await Promise.all([ -// client.xGroupCreate('key', 'group', '$', { -// MKSTREAM: true -// }), -// client.xGroupCreateConsumer('key', 'group', 'consumer'), -// ]); + testUtils.testWithClient('client.xAutoClaimJustId', async client => { + const [, , id, , reply] = await Promise.all([ + client.xGroupCreate('key', 'group', '$', { + MKSTREAM: true + }), + client.xGroupCreateConsumer('key', 'group', 'consumer'), + client.xAdd('key', '*', { + field: 'value' + }), + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }), + client.xAutoClaimJustId('key', 'group', 'consumer', 0, '0-0') + ]); -// assert.deepEqual( -// await client.xAutoClaimJustId('key', 'group', 'consumer', 1, '0-0'), -// { -// nextId: '0-0', -// messages: [] -// } -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.deepEqual(reply, { + nextId: '0-0', + messages: [id], + deletedMessages: testUtils.isVersionGreaterThan([7, 0]) ? [] : undefined + }); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/XGROUP_CREATE.spec.ts b/packages/client/lib/commands/XGROUP_CREATE.spec.ts index 3428f052512..8dee9b5fda7 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './XGROUP_CREATE'; +import XGROUP_CREATE from './XGROUP_CREATE'; describe('XGROUP CREATE', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( - transformArguments('key', 'group', '$'), + XGROUP_CREATE.transformArguments('key', 'group', '$'), ['XGROUP', 'CREATE', 'key', 'group', '$'] ); }); it('with MKSTREAM', () => { assert.deepEqual( - transformArguments('key', 'group', '$', { + XGROUP_CREATE.transformArguments('key', 'group', '$', { MKSTREAM: true }), ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM'] @@ -22,7 +22,7 @@ describe('XGROUP CREATE', () => { it('with ENTRIESREAD', () => { assert.deepEqual( - transformArguments('key', 'group', '$', { + XGROUP_CREATE.transformArguments('key', 'group', '$', { ENTRIESREAD: 1 }), ['XGROUP', 'CREATE', 'key', 'group', '$', 'ENTRIESREAD', '1'] @@ -39,6 +39,6 @@ describe('XGROUP CREATE', () => { ); }, { client: GLOBAL.SERVERS.OPEN, - cluster: GLOBAL.SERVERS.OPEN + cluster: GLOBAL.CLUSTERS.OPEN }); }); diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts index bb10174e1c4..53007270e05 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.ts @@ -1,17 +1,3 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 2; - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// consumer: RedisCommandArgument -// ): RedisCommandArguments { -// return ['XGROUP', 'DELCONSUMER', key, group, consumer]; -// } - -// export declare function transformReply(): number; - import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { diff --git a/packages/client/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts index 0c13f27c416..99370fb97f1 100644 --- a/packages/client/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -20,12 +20,15 @@ describe('XINFO STREAM', () => { assert.deepEqual(reply, { length: 0, - radixTreeKeys: 0, - radixTreeNodes: 1, + 'radix-tree-keys': 0, + 'radix-tree-nodes': 1, + 'last-generated-id': '0-0', + 'max-deleted-entry-id': '0-0', + 'entries-added': 0, + 'recorded-first-entry-id': '0-0', groups: 1, - lastGeneratedId: '0-0', - firstEntry: null, - lastEntry: null + 'first-entry': null, + 'last-entry': null }); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index 2dde1ea1a48..00b6b0aa4e3 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -1,68 +1,3 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { StreamMessageReply, transformTuplesReply } from './generic-transformers'; - -// export const FIRST_KEY_INDEX = 2; - -// export const IS_READ_ONLY = true; - -// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { -// return ['XINFO', 'STREAM', key]; -// } - -// interface XInfoStreamReply { -// length: number; -// radixTreeKeys: number; -// radixTreeNodes: number; -// groups: number; -// lastGeneratedId: RedisCommandArgument; -// firstEntry: StreamMessageReply | null; -// lastEntry: StreamMessageReply | null; -// } - -// export function transformReply(rawReply: Array): XInfoStreamReply { -// const parsedReply: Partial = {}; - -// for (let i = 0; i < rawReply.length; i+= 2) { -// switch (rawReply[i]) { -// case 'length': -// parsedReply.length = rawReply[i + 1]; -// break; - -// case 'radix-tree-keys': -// parsedReply.radixTreeKeys = rawReply[i + 1]; -// break; - -// case 'radix-tree-nodes': -// parsedReply.radixTreeNodes = rawReply[i + 1]; -// break; - -// case 'groups': -// parsedReply.groups = rawReply[i + 1]; -// break; - -// case 'last-generated-id': -// parsedReply.lastGeneratedId = rawReply[i + 1]; -// break; - -// case 'first-entry': -// parsedReply.firstEntry = rawReply[i + 1] ? { -// id: rawReply[i + 1][0], -// message: transformTuplesReply(rawReply[i + 1][1]) -// } : null; -// break; - -// case 'last-entry': -// parsedReply.lastEntry = rawReply[i + 1] ? { -// id: rawReply[i + 1][0], -// message: transformTuplesReply(rawReply[i + 1][1]) -// } : null; -// break; -// } -// } - -// return parsedReply as XInfoStreamReply; -// } - import { TuplesToMapReply, BlobStringReply, NumberReply, NullReply, Resp2Reply, Command, RespType, RESP_TYPES, RedisArgument } from '../RESP/types'; import { StreamMessageRawReply, transformStreamMessageReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index 2f2d75b40fe..ef25b9840cc 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -59,7 +59,7 @@ describe('XPENDING RANGE', () => { assert.equal(reply[0].id, id); assert.equal(reply[0].consumer, 'consumer'); assert.equal(typeof reply[0].millisecondsSinceLastDelivery, 'number'); - assert.equal(reply[0].deliveriesCounter, '1'); + assert.equal(reply[0].deliveriesCounter, 1); }, { client: GLOBAL.SERVERS.OPEN, cluster: GLOBAL.CLUSTERS.OPEN diff --git a/packages/client/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts index 9ca37dae9c9..4fdf9b2b119 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.ts @@ -1,48 +1,3 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; - -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// interface XPendingRangeOptions { -// IDLE?: number; -// consumer?: RedisCommandArgument; -// } - -// export function transformArguments( -// key: RedisCommandArgument, -// group: RedisCommandArgument, -// start: string, -// end: string, -// count: number, -// options?: XPendingRangeOptions -// ): RedisCommandArguments { -// const args = ['XPENDING', key, group]; - -// if (options?.IDLE) { -// args.push('IDLE', options.IDLE.toString()); -// } - -// args.push(start, end, count.toString()); - -// if (options?.consumer) { -// args.push(options.consumer); -// } - -// return args; -// } - - - -// export function transformReply(reply: XPendingRangeRawReply): XPendingRangeReply { -// return reply.map(([id, owner, millisecondsSinceLastDelivery, deliveriesCounter]) => ({ -// id, -// owner, -// millisecondsSinceLastDelivery, -// deliveriesCounter -// })); -// } - import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; export interface XPendingRangeOptions { diff --git a/packages/client/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts index dfcc0590641..5557b04c8fe 100644 --- a/packages/client/lib/commands/XRANGE.spec.ts +++ b/packages/client/lib/commands/XRANGE.spec.ts @@ -22,11 +22,17 @@ describe('XRANGE', () => { }); testUtils.testAll('xRange', async client => { - const message = { field: 'value' }, - [id, reply] = await Promise.all([ - client.xAdd('key', '*', message), - client.xRange('key', '-', '+') - ]); + const message = Object.create(null, { + field: { + value: 'value', + enumerable: true + } + }); + + const [id, reply] = await Promise.all([ + client.xAdd('key', '*', message), + client.xRange('key', '-', '+') + ]); assert.deepEqual(reply, [{ id, diff --git a/packages/client/lib/commands/XREADGROUP.ts b/packages/client/lib/commands/XREADGROUP.ts index f1a2782208f..0396f3a93e9 100644 --- a/packages/client/lib/commands/XREADGROUP.ts +++ b/packages/client/lib/commands/XREADGROUP.ts @@ -22,7 +22,7 @@ export default { streams: XReadStreams, options?: XReadGroupOptions ) { - const args = ['XREADGROUP', group, consumer]; + const args = ['XREADGROUP', 'GROUP', group, consumer]; if (options?.COUNT !== undefined) { args.push('COUNT', options.COUNT.toString()); diff --git a/packages/client/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts index f935f3bcdd8..448018a2b98 100644 --- a/packages/client/lib/commands/XREVRANGE.spec.ts +++ b/packages/client/lib/commands/XREVRANGE.spec.ts @@ -22,11 +22,17 @@ describe('XREVRANGE', () => { }); testUtils.testAll('xRevRange', async client => { - const message = { field: 'value' }, - [id, reply] = await Promise.all([ - client.xAdd('key', '*', message), - client.xRevRange('key', '-', '+') - ]); + const message = Object.create(null, { + field: { + value: 'value', + enumerable: true + } + }); + + const [id, reply] = await Promise.all([ + client.xAdd('key', '*', message), + client.xRange('key', '-', '+') + ]); assert.deepEqual(reply, [{ id, diff --git a/packages/client/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts index 9f684237e11..4ca25ee0eee 100644 --- a/packages/client/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -133,7 +133,7 @@ describe('ZADD', () => { testUtils.testAll('zAdd', async client => { assert.equal( await client.zAdd('key', { - value: '1', + value: 'a', score: 1 }), 1 diff --git a/packages/client/lib/commands/ZADD_INCR.spec.ts b/packages/client/lib/commands/ZADD_INCR.spec.ts index b2fab832ee6..f014160d2e2 100644 --- a/packages/client/lib/commands/ZADD_INCR.spec.ts +++ b/packages/client/lib/commands/ZADD_INCR.spec.ts @@ -81,7 +81,7 @@ describe('ZADD INCR', () => { testUtils.testAll('zAddIncr', async client => { assert.equal( await client.zAddIncr('key', { - value: '1', + value: 'a', score: 1 }), 1 diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts index 6484277ae85..6960006173b 100644 --- a/packages/client/lib/commands/ZMPOP.ts +++ b/packages/client/lib/commands/ZMPOP.ts @@ -1,4 +1,4 @@ -import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; +import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command, RedisArgument } from '../RESP/types'; import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply } from './generic-transformers'; export interface ZMPopOptions { @@ -13,23 +13,30 @@ export type ZMPopRawReply = NullReply | TuplesReply<[ ]>> ]>; -export default { - FIRST_KEY_INDEX: 2, - IS_READ_ONLY: false, - transformArguments( - keys: RedisVariadicArgument, - side: SortedSetSide, - options?: ZMPopOptions - ) { - const args = pushVariadicArgument(['ZMPOP'], keys); +export function transformZMPopArguments( + args: Array, + keys: RedisVariadicArgument, + side: SortedSetSide, + options?: ZMPopOptions +) { + args = pushVariadicArgument(args, keys); + + args.push(side); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } - args.push(side); + return args; +} - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +export type ZMPopArguments = typeof transformZMPopArguments extends (_: any, ...args: infer T) => any ? T : never; - return args; +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments(...args: ZMPopArguments) { + return transformZMPopArguments(['ZMPOP'], ...args); }, transformReply: { 2: (reply: Resp2Reply) => { diff --git a/packages/client/lib/commands/ZPOPMAX.ts b/packages/client/lib/commands/ZPOPMAX.ts index 4e1d476c41b..fb4d2d958b7 100644 --- a/packages/client/lib/commands/ZPOPMAX.ts +++ b/packages/client/lib/commands/ZPOPMAX.ts @@ -1,5 +1,4 @@ -import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; -import ZPOPMIN from './ZPOPMIN'; +import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -7,5 +6,22 @@ export default { transformArguments(key: RedisArgument) { return ['ZPOPMAX', key]; }, - transformReply: ZPOPMIN.transformReply + transformReply: { + 2: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, BlobStringReply]>) => { + if (reply.length === 0) return null; + + return { + value: reply[0], + score: Number(reply[1]) + }; + }, + 3: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, DoubleReply]>) => { + if (reply.length === 0) return null; + + return { + value: reply[0], + score: reply[1] + }; + } + } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts index 222dcf43f86..0806b5977d1 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts @@ -14,14 +14,17 @@ describe('ZPOPMAX COUNT', () => { const members = [{ value: '1', score: 1 + }, { + value: '2', + score: 2 }]; const [ , reply] = await Promise.all([ client.zAdd('key', members), - client.zPopMaxCount('key', 1) + client.zPopMaxCount('key', members.length) ]); - assert.deepEqual(reply, members); + assert.deepEqual(reply, members.reverse()); }, { client: GLOBAL.SERVERS.OPEN, cluster: GLOBAL.SERVERS.OPEN diff --git a/packages/client/lib/commands/ZPOPMIN.ts b/packages/client/lib/commands/ZPOPMIN.ts index 42f428ada31..b9da85cc974 100644 --- a/packages/client/lib/commands/ZPOPMIN.ts +++ b/packages/client/lib/commands/ZPOPMIN.ts @@ -1,4 +1,5 @@ -import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, Command } from '../RESP/types'; +import ZPOPMAX from './ZPOPMAX'; export default { FIRST_KEY_INDEX: 1, @@ -6,22 +7,5 @@ export default { transformArguments(key: RedisArgument) { return ['ZPOPMIN', key]; }, - transformReply: { - 2: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, BlobStringReply]>) => { - if (reply.length === 0) return null; - - return { - value: reply[0], - score: Number(reply[1]) - }; - }, - 3: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, DoubleReply]>) => { - if (reply.length === 0) return null; - - return { - value: reply[0], - score: reply[1] - }; - } - } + transformReply: ZPOPMAX.transformReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts index fc19ba2b9cd..2b2f12b3487 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts @@ -14,11 +14,14 @@ describe('ZPOPMIN COUNT', () => { const members = [{ value: '1', score: 1 + }, { + value: '2', + score: 2 }]; const [ , reply] = await Promise.all([ client.zAdd('key', members), - client.zPopMinCount('key', 1) + client.zPopMinCount('key', members.length) ]); assert.deepEqual(reply, members); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index cca2f9f128b..cc98529c59f 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -26,6 +26,9 @@ import BLMPOP from './BLMPOP'; import BLPOP from './BLPOP'; import BRPOP from './BRPOP'; import BRPOPLPUSH from './BRPOPLPUSH'; +import BZMPOP from './BZMPOP'; +import BZPOPMAX from './BZPOPMAX'; +import BZPOPMIN from './BZPOPMIN'; import CLIENT_CACHING from './CLIENT_CACHING'; import CLIENT_GETNAME from './CLIENT_GETNAME'; import CLIENT_GETREDIR from './CLIENT_GETREDIR'; @@ -345,6 +348,9 @@ type BLMPOP = typeof import('./BLMPOP').default; type BLPOP = typeof import('./BLPOP').default; type BRPOP = typeof import('./BRPOP').default; type BRPOPLPUSH = typeof import('./BRPOPLPUSH').default; +type BZMPOP = typeof import('./BZMPOP').default; +type BZPOPMAX = typeof import('./BZPOPMAX').default; +type BZPOPMIN = typeof import('./BZPOPMIN').default; type CLIENT_CACHING = typeof import('./CLIENT_CACHING').default; type CLIENT_GETNAME = typeof import('./CLIENT_GETNAME').default; type CLIENT_GETREDIR = typeof import('./CLIENT_GETREDIR').default; @@ -692,6 +698,12 @@ type Commands = { brPop: BRPOP; BRPOPLPUSH: BRPOPLPUSH; brPopLPush: BRPOPLPUSH; + BZMPOP: BZMPOP; + bzmPop: BZMPOP; + BZPOPMAX: BZPOPMAX; + bzPopMax: BZPOPMAX; + BZPOPMIN: BZPOPMIN; + bzPopMin: BZPOPMIN; CLIENT_CACHING: CLIENT_CACHING; clientCaching: CLIENT_CACHING; CLIENT_GETNAME: CLIENT_GETNAME; @@ -1331,6 +1343,12 @@ export default { brPop: BRPOP, BRPOPLPUSH, brPopLPush: BRPOPLPUSH, + BZMPOP, + bzmPop: BZMPOP, + BZPOPMAX, + bzPopMax: BZPOPMAX, + BZPOPMIN, + bzPopMin: BZPOPMIN, CLIENT_CACHING, clientCaching: CLIENT_CACHING, CLIENT_GETNAME, From de7e2b85c49ae2d40ea8a020029efb12d1eb84e3 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 29 Jun 2023 15:22:57 -0400 Subject: [PATCH 149/325] wip --- packages/client/lib/client/commands-queue.ts | 48 +++++++++++--------- packages/client/lib/client/index.ts | 12 +++-- packages/client/lib/client/socket.ts | 4 +- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 58699174cd3..8caa2f178a9 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -16,7 +16,7 @@ export interface CommandOptions { typeMapping?: T; } -export interface CommandWaitingToBeSent extends CommandWaitingForReply { +export interface CommandToWrite extends CommandWaitingForReply { args: CommandArguments; chainId?: symbol; abort?: { @@ -43,7 +43,7 @@ const RESP2_PUSH_TYPE_MAPPING = { export default class RedisCommandsQueue { private readonly _maxLength: number | null | undefined; - private readonly _waitingToBeSent = new DoublyLinkedList(); + private readonly _toWrite = new DoublyLinkedList(); private readonly _waitingForReply = new SinglyLinkedList(); private readonly _onShardedChannelMoved: OnShardedChannelMoved; @@ -153,15 +153,15 @@ export default class RedisCommandsQueue { } addCommand(args: CommandArguments, options?: CommandOptions): Promise { - if (this._maxLength && this._waitingToBeSent.length + this._waitingForReply.length >= this._maxLength) { + if (this._maxLength && this._toWrite.length + this._waitingForReply.length >= this._maxLength) { return Promise.reject(new Error('The queue is full')); } else if (options?.abortSignal?.aborted) { return Promise.reject(new AbortError()); } return new Promise((resolve, reject) => { - let node: DoublyLinkedNode; - const value: CommandWaitingToBeSent = { + let node: DoublyLinkedNode; + const value: CommandToWrite = { args, chainId: options?.chainId, typeMapping: options?.typeMapping, @@ -175,7 +175,7 @@ export default class RedisCommandsQueue { value.abort = { signal, listener: () => { - this._waitingToBeSent.remove(node); + this._toWrite.remove(node); value.reject(new AbortError()); } }; @@ -183,8 +183,8 @@ export default class RedisCommandsQueue { } node = options?.asap ? - this._waitingToBeSent.unshift(value) : - this._waitingToBeSent.push(value); + this._toWrite.unshift(value) : + this._toWrite.push(value); }); } @@ -243,7 +243,7 @@ export default class RedisCommandsQueue { if (command === undefined) return; return new Promise((resolve, reject) => { - this._waitingToBeSent.push({ + this._toWrite.push({ args: command.args, channelsCounter: command.channelsCounter, typeMapping: PUSH_TYPE_MAPPING, @@ -259,15 +259,19 @@ export default class RedisCommandsQueue { }); } - *waitingToBeSent() { - let toSend = this._waitingToBeSent.shift(); + isWaitingToWrite() { + return this._toWrite.length > 0; + } + + *commandsToWrite() { + let toSend = this._toWrite.shift(); while (toSend) { let encoded: CommandArguments; try { encoded = encodeCommand(toSend.args); } catch (err) { toSend.reject(err); - toSend = this._waitingToBeSent.shift(); + toSend = this._toWrite.shift(); continue; } @@ -283,7 +287,7 @@ export default class RedisCommandsQueue { this._waitingForReply.push(toSend); this._chainInExecution = toSend.chainId; yield encoded; - toSend = this._waitingToBeSent.shift(); + toSend = this._toWrite.shift(); } } @@ -294,11 +298,11 @@ export default class RedisCommandsQueue { this._waitingForReply.reset(); } - private static _removeAbortListener(command: CommandWaitingToBeSent) { + private static _removeAbortListener(command: CommandToWrite) { command.abort!.signal.removeEventListener('abort', command.abort!.listener); } - private static _flushWaitingToBeSent(toBeSent: CommandWaitingToBeSent, err: Error) { + private static _flushToWrite(toBeSent: CommandToWrite, err: Error) { if (toBeSent.abort) { RedisCommandsQueue._removeAbortListener(toBeSent); } @@ -314,9 +318,9 @@ export default class RedisCommandsQueue { if (!this._chainInExecution) return; - while (this._waitingToBeSent.head?.value.chainId === this._chainInExecution) { - RedisCommandsQueue._flushWaitingToBeSent( - this._waitingToBeSent.shift()!, + while (this._toWrite.head?.value.chainId === this._chainInExecution) { + RedisCommandsQueue._flushToWrite( + this._toWrite.shift()!, err ); } @@ -328,15 +332,15 @@ export default class RedisCommandsQueue { this.decoder.reset(); this._pubSub.reset(); this._flushWaitingForReply(err); - for (const node of this._waitingToBeSent) { - RedisCommandsQueue._flushWaitingToBeSent(node, err); + for (const node of this._toWrite) { + RedisCommandsQueue._flushToWrite(node, err); } - this._waitingToBeSent.reset(); + this._toWrite.reset(); } isEmpty() { return ( - this._waitingToBeSent.length === 0 && + this._toWrite.length === 0 && this._waitingForReply.length === 0 ); } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 3d43ae55b8b..d53f8bec604 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -440,10 +440,10 @@ export default class RedisClient< .on('ready', () => { this.emit('ready'); this._setPingTimer(); - this._scheduleWrite(); + this._maybeScheduleWrite(); }) .on('reconnecting', () => this.emit('reconnecting')) - .on('drain', () => this._scheduleWrite()) + .on('drain', () => this._maybeScheduleWrite()) .on('end', () => this.emit('end')); } @@ -706,7 +706,7 @@ export default class RedisClient< } private _write() { - this._socket.write(this._queue.waitingToBeSent()); + this._socket.write(this._queue.commandsToWrite()); } private _scheduledWrite?: NodeJS.Immediate; @@ -720,6 +720,12 @@ export default class RedisClient< }); } + private _maybeScheduleWrite() { + if (!this._queue.isWaitingToWrite()) return; + + this._scheduleWrite(); + } + /** * @internal */ diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index a841828c3a9..86c99233933 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -229,9 +229,7 @@ export default class RedisSocket extends EventEmitter { } write(iterator: IterableIterator>): void { - if (!this._socket) { - throw new ClientClosedError(); - } + if (!this._socket) return; this._socket.cork(); for (const args of iterator) { From 935b9cbb60478f8189799bc452f754fee06db776 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:17:51 -0400 Subject: [PATCH 150/325] fix ADD --- packages/time-series/lib/commands/ADD.spec.ts | 134 +++++++++--------- packages/time-series/lib/commands/ADD.ts | 59 ++++---- 2 files changed, 100 insertions(+), 93 deletions(-) diff --git a/packages/time-series/lib/commands/ADD.spec.ts b/packages/time-series/lib/commands/ADD.spec.ts index 94ad30627f8..898f42ee772 100644 --- a/packages/time-series/lib/commands/ADD.spec.ts +++ b/packages/time-series/lib/commands/ADD.spec.ts @@ -1,80 +1,80 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ADD'; +import ADD from './ADD'; import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.'; -describe('ADD', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', '*', 1), - ['TS.ADD', 'key', '*', '1'] - ); - }); +describe('TS.ADD', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1), + ['TS.ADD', 'key', '*', '1'] + ); + }); - it('with RETENTION', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - RETENTION: 1 - }), - ['TS.ADD', 'key', '*', '1', 'RETENTION', '1'] - ); - }); + it('with RETENTION', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + RETENTION: 1 + }), + ['TS.ADD', 'key', '*', '1', 'RETENTION', '1'] + ); + }); - it('with ENCODING', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - ENCODING: TimeSeriesEncoding.UNCOMPRESSED - }), - ['TS.ADD', 'key', '*', '1', 'ENCODING', 'UNCOMPRESSED'] - ); - }); + it('with ENCODING', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + ENCODING: TimeSeriesEncoding.UNCOMPRESSED + }), + ['TS.ADD', 'key', '*', '1', 'ENCODING', 'UNCOMPRESSED'] + ); + }); - it('with CHUNK_SIZE', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - CHUNK_SIZE: 1 - }), - ['TS.ADD', 'key', '*', '1', 'CHUNK_SIZE', '1'] - ); - }); + it('with CHUNK_SIZE', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + CHUNK_SIZE: 1 + }), + ['TS.ADD', 'key', '*', '1', 'CHUNK_SIZE', '1'] + ); + }); - it('with ON_DUPLICATE', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK - }), - ['TS.ADD', 'key', '*', '1', 'ON_DUPLICATE', 'BLOCK'] - ); - }); + it('with ON_DUPLICATE', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK + }), + ['TS.ADD', 'key', '*', '1', 'ON_DUPLICATE', 'BLOCK'] + ); + }); - it('with LABELS', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - LABELS: { label: 'value' } - }), - ['TS.ADD', 'key', '*', '1', 'LABELS', 'label', 'value'] - ); - }); + it('with LABELS', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + LABELS: { label: 'value' } + }), + ['TS.ADD', 'key', '*', '1', 'LABELS', 'label', 'value'] + ); + }); - it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS', () => { - assert.deepEqual( - transformArguments('key', '*', 1, { - RETENTION: 1, - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, - CHUNK_SIZE: 1, - ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } - }), - ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value'] - ); - }); + it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + RETENTION: 1, + ENCODING: TimeSeriesEncoding.UNCOMPRESSED, + CHUNK_SIZE: 1, + ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK, + LABELS: { label: 'value' } + }), + ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value'] + ); }); + }); - testUtils.testWithClient('client.ts.add', async client => { - assert.equal( - await client.ts.add('key', 0, 1), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.ts.add', async client => { + assert.equal( + await client.ts.add('key', 0, 1), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/ADD.ts b/packages/time-series/lib/commands/ADD.ts index 1988a964513..b40a6912ca8 100644 --- a/packages/time-series/lib/commands/ADD.ts +++ b/packages/time-series/lib/commands/ADD.ts @@ -1,31 +1,38 @@ +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; import { - transformTimestampArgument, - pushRetentionArgument, - TimeSeriesEncoding, - pushEncodingArgument, - pushChunkSizeArgument, - TimeSeriesDuplicatePolicies, - Labels, - pushLabelsArgument, - Timestamp, + transformTimestampArgument, + pushRetentionArgument, + TimeSeriesEncoding, + pushEncodingArgument, + pushChunkSizeArgument, + TimeSeriesDuplicatePolicies, + Labels, + pushLabelsArgument, + Timestamp } from '.'; -interface AddOptions { - RETENTION?: number; - ENCODING?: TimeSeriesEncoding; - CHUNK_SIZE?: number; - ON_DUPLICATE?: TimeSeriesDuplicatePolicies; - LABELS?: Labels; +export interface TsAddOptions { + RETENTION?: number; + ENCODING?: TimeSeriesEncoding; + CHUNK_SIZE?: number; + ON_DUPLICATE?: TimeSeriesDuplicatePolicies; + LABELS?: Labels; } -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string, timestamp: Timestamp, value: number, options?: AddOptions): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + timestamp: Timestamp, + value: number, + options?: TsAddOptions + ) { const args = [ - 'TS.ADD', - key, - transformTimestampArgument(timestamp), - value.toString() + 'TS.ADD', + key, + transformTimestampArgument(timestamp), + value.toString() ]; pushRetentionArgument(args, options?.RETENTION); @@ -35,12 +42,12 @@ export function transformArguments(key: string, timestamp: Timestamp, value: num pushChunkSizeArgument(args, options?.CHUNK_SIZE); if (options?.ON_DUPLICATE) { - args.push('ON_DUPLICATE', options.ON_DUPLICATE); + args.push('ON_DUPLICATE', options.ON_DUPLICATE); } pushLabelsArgument(args, options?.LABELS); return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From 59e2e6d626124e4b4be4d682b0046b4c6b23461a Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:18:03 -0400 Subject: [PATCH 151/325] fix ALTER --- .../time-series/lib/commands/ALTER.spec.ts | 118 +++++++++--------- packages/time-series/lib/commands/ALTER.ts | 24 ++-- 2 files changed, 72 insertions(+), 70 deletions(-) diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index cd066533aa4..0a7d7cb2caa 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -1,72 +1,72 @@ import { strict as assert } from 'assert'; import { TimeSeriesDuplicatePolicies } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ALTER'; +import ALTER from './ALTER'; -describe('ALTER', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key'), - ['TS.ALTER', 'key'] - ); - }); +describe('TS.ALTER', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + ALTER.transformArguments('key'), + ['TS.ALTER', 'key'] + ); + }); - it('with RETENTION', () => { - assert.deepEqual( - transformArguments('key', { - RETENTION: 1 - }), - ['TS.ALTER', 'key', 'RETENTION', '1'] - ); - }); + it('with RETENTION', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + RETENTION: 1 + }), + ['TS.ALTER', 'key', 'RETENTION', '1'] + ); + }); - it('with CHUNK_SIZE', () => { - assert.deepEqual( - transformArguments('key', { - CHUNK_SIZE: 1 - }), - ['TS.ALTER', 'key', 'CHUNK_SIZE', '1'] - ); - }); + it('with CHUNK_SIZE', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + CHUNK_SIZE: 1 + }), + ['TS.ALTER', 'key', 'CHUNK_SIZE', '1'] + ); + }); - it('with DUPLICATE_POLICY', () => { - assert.deepEqual( - transformArguments('key', { - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK - }), - ['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK'] - ); - }); + it('with DUPLICATE_POLICY', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK + }), + ['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK'] + ); + }); - it('with LABELS', () => { - assert.deepEqual( - transformArguments('key', { - LABELS: { label: 'value' } - }), - ['TS.ALTER', 'key', 'LABELS', 'label', 'value'] - ); - }); + it('with LABELS', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + LABELS: { label: 'value' } + }), + ['TS.ALTER', 'key', 'LABELS', 'label', 'value'] + ); + }); - it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { - assert.deepEqual( - transformArguments('key', { - RETENTION: 1, - CHUNK_SIZE: 1, - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } - }), - ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] - ); - }); + it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + RETENTION: 1, + CHUNK_SIZE: 1, + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, + LABELS: { label: 'value' } + }), + ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ); }); + }); - testUtils.testWithClient('client.ts.alter', async client => { - await client.ts.create('key'); + testUtils.testWithClient('client.ts.alter', async client => { + await client.ts.create('key'); - assert.equal( - await client.ts.alter('key', { RETENTION: 1 }), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ts.alter('key', { RETENTION: 1 }), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/ALTER.ts b/packages/time-series/lib/commands/ALTER.ts index 7b9e1e774c6..bf4e4d528c3 100644 --- a/packages/time-series/lib/commands/ALTER.ts +++ b/packages/time-series/lib/commands/ALTER.ts @@ -1,15 +1,17 @@ import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -interface AlterOptions { - RETENTION?: number; - CHUNK_SIZE?: number; - DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; - LABELS?: Labels; +export interface TsAlterOptions { + RETENTION?: number; + CHUNK_SIZE?: number; + DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; + LABELS?: Labels; } -export function transformArguments(key: string, options?: AlterOptions): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, options?: TsAlterOptions) { const args = ['TS.ALTER', key]; pushRetentionArgument(args, options?.RETENTION); @@ -21,6 +23,6 @@ export function transformArguments(key: string, options?: AlterOptions): Array SimpleStringReply<'OK'> +} as const satisfies Command; From a021506bb3bce190514990be74a7b21107d5ed88 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:18:26 -0400 Subject: [PATCH 152/325] fix DECRBY --- .../time-series/lib/commands/DECRBY.spec.ts | 136 +++++++++--------- packages/time-series/lib/commands/DECRBY.ts | 15 +- 2 files changed, 76 insertions(+), 75 deletions(-) diff --git a/packages/time-series/lib/commands/DECRBY.spec.ts b/packages/time-series/lib/commands/DECRBY.spec.ts index 345e651404b..8efa09ce42a 100644 --- a/packages/time-series/lib/commands/DECRBY.spec.ts +++ b/packages/time-series/lib/commands/DECRBY.spec.ts @@ -1,81 +1,81 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DECRBY'; +import DECRBY from './DECRBY'; describe('DECRBY', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', 1), - ['TS.DECRBY', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1), + ['TS.DECRBY', 'key', '1'] + ); + }); - it('with TIMESTAMP', () => { - assert.deepEqual( - transformArguments('key', 1, { - TIMESTAMP: '*' - }), - ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*'] - ); - }); + it('with TIMESTAMP', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + TIMESTAMP: '*' + }), + ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*'] + ); + }); - it('with RETENTION', () => { - assert.deepEqual( - transformArguments('key', 1, { - RETENTION: 1 - }), - ['TS.DECRBY', 'key', '1', 'RETENTION', '1'] - ); - }); + it('with RETENTION', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + RETENTION: 1 + }), + ['TS.DECRBY', 'key', '1', 'RETENTION', '1'] + ); + }); - it('with UNCOMPRESSED', () => { - assert.deepEqual( - transformArguments('key', 1, { - UNCOMPRESSED: true - }), - ['TS.DECRBY', 'key', '1', 'UNCOMPRESSED'] - ); - }); + it('with UNCOMPRESSED', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + UNCOMPRESSED: true + }), + ['TS.DECRBY', 'key', '1', 'UNCOMPRESSED'] + ); + }); - it('with CHUNK_SIZE', () => { - assert.deepEqual( - transformArguments('key', 1, { - CHUNK_SIZE: 100 - }), - ['TS.DECRBY', 'key', '1', 'CHUNK_SIZE', '100'] - ); - }); + it('with CHUNK_SIZE', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + CHUNK_SIZE: 100 + }), + ['TS.DECRBY', 'key', '1', 'CHUNK_SIZE', '100'] + ); + }); - it('with LABELS', () => { - assert.deepEqual( - transformArguments('key', 1, { - LABELS: { label: 'value' } - }), - ['TS.DECRBY', 'key', '1', 'LABELS', 'label', 'value'] - ); - }); + it('with LABELS', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + LABELS: { label: 'value' } + }), + ['TS.DECRBY', 'key', '1', 'LABELS', 'label', 'value'] + ); + }); - it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { - assert.deepEqual( - transformArguments('key', 1, { - TIMESTAMP: '*', - RETENTION: 1, - UNCOMPRESSED: true, - CHUNK_SIZE: 2, - LABELS: { label: 'value' } - }), - ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value'] - ); - }); + it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + TIMESTAMP: '*', + RETENTION: 1, + UNCOMPRESSED: true, + CHUNK_SIZE: 2, + LABELS: { label: 'value' } + }), + ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value'] + ); }); + }); - testUtils.testWithClient('client.ts.decrBy', async client => { - assert.equal( - await client.ts.decrBy('key', 1, { - TIMESTAMP: 0 - }), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.ts.decrBy', async client => { + assert.equal( + await client.ts.decrBy('key', 1, { + TIMESTAMP: 0 + }), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/DECRBY.ts b/packages/time-series/lib/commands/DECRBY.ts index 07b5b6f45c0..181568d1a85 100644 --- a/packages/time-series/lib/commands/DECRBY.ts +++ b/packages/time-series/lib/commands/DECRBY.ts @@ -1,10 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { IncrDecrOptions, transformIncrDecrArguments } from '.'; +import { RedisArgument, Command, NumberReply } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string, value: number, options?: IncrDecrOptions): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { return transformIncrDecrArguments('TS.DECRBY', key, value, options); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From fc8a14d55d444c54990b4540b881673afbd888bc Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:18:38 -0400 Subject: [PATCH 153/325] fix DEL --- packages/time-series/lib/commands/DEL.spec.ts | 28 +++++++++---------- packages/time-series/lib/commands/DEL.ts | 23 +++++++-------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/packages/time-series/lib/commands/DEL.spec.ts b/packages/time-series/lib/commands/DEL.spec.ts index 0fc4b465807..a0fdabedd65 100644 --- a/packages/time-series/lib/commands/DEL.spec.ts +++ b/packages/time-series/lib/commands/DEL.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DEL'; +import DEL from './DEL'; describe('DEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '-', '+'), - ['TS.DEL', 'key', '-', '+'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DEL.transformArguments('key', '-', '+'), + ['TS.DEL', 'key', '-', '+'] + ); + }); - testUtils.testWithClient('client.ts.del', async client => { - await client.ts.create('key'); + testUtils.testWithClient('client.ts.del', async client => { + await client.ts.create('key'); - assert.equal( - await client.ts.del('key', '-', '+'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ts.del('key', '-', '+'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/DEL.ts b/packages/time-series/lib/commands/DEL.ts index 347954c21de..26c3e610f17 100644 --- a/packages/time-series/lib/commands/DEL.ts +++ b/packages/time-series/lib/commands/DEL.ts @@ -1,15 +1,16 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { Timestamp, transformTimestampArgument } from '.'; +import { RedisArgument, NumberReply, Command, } from '@redis/client/dist/lib/RESP/types'; -export const FIRTS_KEY_INDEX = 1; - -export function transformArguments(key: string, fromTimestamp: Timestamp, toTimestamp: Timestamp): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, fromTimestamp: Timestamp, toTimestamp: Timestamp) { return [ - 'TS.DEL', - key, - transformTimestampArgument(fromTimestamp), - transformTimestampArgument(toTimestamp) + 'TS.DEL', + key, + transformTimestampArgument(fromTimestamp), + transformTimestampArgument(toTimestamp) ]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From fba3c0a85d6a51e891c81b81ab67d739b42c7f43 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:18:55 -0400 Subject: [PATCH 154/325] fix INCRBY --- .../time-series/lib/commands/INCRBY.spec.ts | 154 +++++++++--------- packages/time-series/lib/commands/INCRBY.ts | 15 +- 2 files changed, 85 insertions(+), 84 deletions(-) diff --git a/packages/time-series/lib/commands/INCRBY.spec.ts b/packages/time-series/lib/commands/INCRBY.spec.ts index acaa4cd3329..0745a1d26fa 100644 --- a/packages/time-series/lib/commands/INCRBY.spec.ts +++ b/packages/time-series/lib/commands/INCRBY.spec.ts @@ -1,91 +1,91 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './INCRBY'; +import INCRBY from './INCRBY'; describe('INCRBY', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', 1), - ['TS.INCRBY', 'key', '1'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1), + ['TS.INCRBY', 'key', '1'] + ); + }); - it('with TIMESTAMP', () => { - assert.deepEqual( - transformArguments('key', 1, { - TIMESTAMP: '*' - }), - ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*'] - ); - }); + it('with TIMESTAMP', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + TIMESTAMP: '*' + }), + ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*'] + ); + }); - it('with RETENTION', () => { - assert.deepEqual( - transformArguments('key', 1, { - RETENTION: 1 - }), - ['TS.INCRBY', 'key', '1', 'RETENTION', '1'] - ); - }); + it('with RETENTION', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + RETENTION: 1 + }), + ['TS.INCRBY', 'key', '1', 'RETENTION', '1'] + ); + }); - it('with UNCOMPRESSED', () => { - assert.deepEqual( - transformArguments('key', 1, { - UNCOMPRESSED: true - }), - ['TS.INCRBY', 'key', '1', 'UNCOMPRESSED'] - ); - }); + it('with UNCOMPRESSED', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + UNCOMPRESSED: true + }), + ['TS.INCRBY', 'key', '1', 'UNCOMPRESSED'] + ); + }); - it('without UNCOMPRESSED', () => { - assert.deepEqual( - transformArguments('key', 1, { - UNCOMPRESSED: false - }), - ['TS.INCRBY', 'key', '1'] - ); - }); + it('without UNCOMPRESSED', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + UNCOMPRESSED: false + }), + ['TS.INCRBY', 'key', '1'] + ); + }); - it('with CHUNK_SIZE', () => { - assert.deepEqual( - transformArguments('key', 1, { - CHUNK_SIZE: 1 - }), - ['TS.INCRBY', 'key', '1', 'CHUNK_SIZE', '1'] - ); - }); + it('with CHUNK_SIZE', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + CHUNK_SIZE: 1 + }), + ['TS.INCRBY', 'key', '1', 'CHUNK_SIZE', '1'] + ); + }); - it('with LABELS', () => { - assert.deepEqual( - transformArguments('key', 1, { - LABELS: { label: 'value' } - }), - ['TS.INCRBY', 'key', '1', 'LABELS', 'label', 'value'] - ); - }); + it('with LABELS', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + LABELS: { label: 'value' } + }), + ['TS.INCRBY', 'key', '1', 'LABELS', 'label', 'value'] + ); + }); - it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { - assert.deepEqual( - transformArguments('key', 1, { - TIMESTAMP: '*', - RETENTION: 1, - UNCOMPRESSED: true, - CHUNK_SIZE: 1, - LABELS: { label: 'value' } - }), - ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', - 'CHUNK_SIZE', '1', 'LABELS', 'label', 'value'] - ); - }); + it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + TIMESTAMP: '*', + RETENTION: 1, + UNCOMPRESSED: true, + CHUNK_SIZE: 1, + LABELS: { label: 'value' } + }), + ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', + 'CHUNK_SIZE', '1', 'LABELS', 'label', 'value'] + ); }); + }); - testUtils.testWithClient('client.ts.incrBy', async client => { - assert.equal( - await client.ts.incrBy('key', 1, { - TIMESTAMP: 0 - }), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.ts.incrBy', async client => { + assert.equal( + await client.ts.incrBy('key', 1, { + TIMESTAMP: 0 + }), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/INCRBY.ts b/packages/time-series/lib/commands/INCRBY.ts index 1f96801305f..413c33643ac 100644 --- a/packages/time-series/lib/commands/INCRBY.ts +++ b/packages/time-series/lib/commands/INCRBY.ts @@ -1,10 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { IncrDecrOptions, transformIncrDecrArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string, value: number, options?: IncrDecrOptions): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { return transformIncrDecrArguments('TS.INCRBY', key, value, options); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From 7f562bce437b697a797149a65f72daa1e354fba5 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:19:38 -0400 Subject: [PATCH 155/325] fix GET --- packages/time-series/lib/commands/GET.spec.ts | 70 +++++++++---------- packages/time-series/lib/commands/GET.ts | 42 ++++++----- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/packages/time-series/lib/commands/GET.spec.ts b/packages/time-series/lib/commands/GET.spec.ts index 29634cd775a..3af57f75102 100644 --- a/packages/time-series/lib/commands/GET.spec.ts +++ b/packages/time-series/lib/commands/GET.spec.ts @@ -1,46 +1,46 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GET'; +import GET from './GET'; describe('GET', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key'), - ['TS.GET', 'key'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + GET.transformArguments('key'), + ['TS.GET', 'key'] + ); + }); - it('with LATEST', () => { - assert.deepEqual( - transformArguments('key', { - LATEST: true - }), - ['TS.GET', 'key', 'LATEST'] - ); - }); + it('with LATEST', () => { + assert.deepEqual( + GET.transformArguments('key', { + LATEST: true + }), + ['TS.GET', 'key', 'LATEST'] + ); }); + }); - describe('client.ts.get', () => { - testUtils.testWithClient('null', async client => { - await client.ts.create('key'); + describe('client.ts.get', () => { + testUtils.testWithClient('null', async client => { + await client.ts.create('key'); - assert.equal( - await client.ts.get('key'), - null - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ts.get('key'), + null + ); + }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('with samples', async client => { - await client.ts.add('key', 0, 1); + testUtils.testWithClient('with samples', async client => { + await client.ts.add('key', 0, 1); - assert.deepEqual( - await client.ts.get('key'), - { - timestamp: 0, - value: 1 - } - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.deepEqual( + await client.ts.get('key'), + { + timestamp: 0, + value: 1 + } + ); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/time-series/lib/commands/GET.ts b/packages/time-series/lib/commands/GET.ts index 6d74f97c9cd..e2de752a0df 100644 --- a/packages/time-series/lib/commands/GET.ts +++ b/packages/time-series/lib/commands/GET.ts @@ -1,20 +1,30 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushLatestArgument, SampleRawReply, SampleReply, transformSampleReply } from '.'; +import { RedisArgument, TuplesReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; +import { pushLatestArgument } from '.'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -interface GetOptions { - LATEST?: boolean; +export interface TsGetOptions { + LATEST?: boolean; } -export function transformArguments(key: string, options?: GetOptions): RedisCommandArguments { - return pushLatestArgument(['TS.GET', key], options?.LATEST); -} +export type TsGetReply = TuplesReply<[]> | TuplesReply<[NumberReply, DoubleReply]>; -export function transformReply(reply: [] | SampleRawReply): null | SampleReply { - if (reply.length === 0) return null; - - return transformSampleReply(reply); -} +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, options?: TsGetOptions) { + return pushLatestArgument(['TS.GET', key], options?.LATEST); + }, + transformReply: { + 2(reply: Resp2Reply) { + return reply.length === 0 ? null : { + timestamp: reply[0], + value: Number(reply[1]) + }; + }, + 3(reply: TsGetReply) { + return reply.length === 0 ? null : { + timestamp: reply[0], + value: reply[1] + }; + } + } +} as const satisfies Command; From cac51e5edba9141992336edb4625af216b3dbf9c Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:40:49 -0400 Subject: [PATCH 156/325] fix CREATE --- .../time-series/lib/commands/CREATE.spec.ts | 132 +++++++++--------- packages/time-series/lib/commands/CREATE.ts | 44 +++--- 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/packages/time-series/lib/commands/CREATE.spec.ts b/packages/time-series/lib/commands/CREATE.spec.ts index fe1da99b096..33717b607c8 100644 --- a/packages/time-series/lib/commands/CREATE.spec.ts +++ b/packages/time-series/lib/commands/CREATE.spec.ts @@ -1,80 +1,80 @@ import { strict as assert } from 'assert'; import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CREATE'; +import CREATE from './CREATE'; describe('CREATE', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key'), - ['TS.CREATE', 'key'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + CREATE.transformArguments('key'), + ['TS.CREATE', 'key'] + ); + }); - it('with RETENTION', () => { - assert.deepEqual( - transformArguments('key', { - RETENTION: 1 - }), - ['TS.CREATE', 'key', 'RETENTION', '1'] - ); - }); + it('with RETENTION', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + RETENTION: 1 + }), + ['TS.CREATE', 'key', 'RETENTION', '1'] + ); + }); - it('with ENCODING', () => { - assert.deepEqual( - transformArguments('key', { - ENCODING: TimeSeriesEncoding.UNCOMPRESSED - }), - ['TS.CREATE', 'key', 'ENCODING', 'UNCOMPRESSED'] - ); - }); + it('with ENCODING', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + ENCODING: TimeSeriesEncoding.UNCOMPRESSED + }), + ['TS.CREATE', 'key', 'ENCODING', 'UNCOMPRESSED'] + ); + }); - it('with CHUNK_SIZE', () => { - assert.deepEqual( - transformArguments('key', { - CHUNK_SIZE: 1 - }), - ['TS.CREATE', 'key', 'CHUNK_SIZE', '1'] - ); - }); + it('with CHUNK_SIZE', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + CHUNK_SIZE: 1 + }), + ['TS.CREATE', 'key', 'CHUNK_SIZE', '1'] + ); + }); - it('with DUPLICATE_POLICY', () => { - assert.deepEqual( - transformArguments('key', { - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK - }), - ['TS.CREATE', 'key', 'DUPLICATE_POLICY', 'BLOCK'] - ); - }); + it('with DUPLICATE_POLICY', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK + }), + ['TS.CREATE', 'key', 'DUPLICATE_POLICY', 'BLOCK'] + ); + }); - it('with LABELS', () => { - assert.deepEqual( - transformArguments('key', { - LABELS: { label: 'value' } - }), - ['TS.CREATE', 'key', 'LABELS', 'label', 'value'] - ); - }); + it('with LABELS', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + LABELS: { label: 'value' } + }), + ['TS.CREATE', 'key', 'LABELS', 'label', 'value'] + ); + }); - it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { - assert.deepEqual( - transformArguments('key', { - RETENTION: 1, - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, - CHUNK_SIZE: 1, - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } - }), - ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] - ); - }); + it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + RETENTION: 1, + ENCODING: TimeSeriesEncoding.UNCOMPRESSED, + CHUNK_SIZE: 1, + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, + LABELS: { label: 'value' } + }), + ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ); }); + }); - testUtils.testWithClient('client.ts.create', async client => { - assert.equal( - await client.ts.create('key'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.ts.create', async client => { + assert.equal( + await client.ts.create('key'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/CREATE.ts b/packages/time-series/lib/commands/CREATE.ts index a360950feff..da28112d284 100644 --- a/packages/time-series/lib/commands/CREATE.ts +++ b/packages/time-series/lib/commands/CREATE.ts @@ -1,25 +1,27 @@ import { - pushRetentionArgument, - TimeSeriesEncoding, - pushEncodingArgument, - pushChunkSizeArgument, - TimeSeriesDuplicatePolicies, - Labels, - pushLabelsArgument, - pushDuplicatePolicy + pushRetentionArgument, + TimeSeriesEncoding, + pushEncodingArgument, + pushChunkSizeArgument, + TimeSeriesDuplicatePolicies, + Labels, + pushLabelsArgument, + pushDuplicatePolicy } from '.'; - -export const FIRST_KEY_INDEX = 1; - -interface CreateOptions { - RETENTION?: number; - ENCODING?: TimeSeriesEncoding; - CHUNK_SIZE?: number; - DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; - LABELS?: Labels; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export interface TsCreateOptions { + RETENTION?: number; + ENCODING?: TimeSeriesEncoding; + CHUNK_SIZE?: number; + DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; + LABELS?: Labels; } -export function transformArguments(key: string, options?: CreateOptions): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, options?: TsCreateOptions) { const args = ['TS.CREATE', key]; pushRetentionArgument(args, options?.RETENTION); @@ -33,6 +35,6 @@ export function transformArguments(key: string, options?: CreateOptions): Array< pushLabelsArgument(args, options?.LABELS); return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; From ffa5c50fc0361d25ed65063ecddac4f41431a4a5 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:41:15 -0400 Subject: [PATCH 157/325] fix MADD --- .../time-series/lib/commands/MADD.spec.ts | 62 +++++++++---------- packages/time-series/lib/commands/MADD.ts | 32 +++++----- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/packages/time-series/lib/commands/MADD.spec.ts b/packages/time-series/lib/commands/MADD.spec.ts index eed014f2b14..d5446763310 100644 --- a/packages/time-series/lib/commands/MADD.spec.ts +++ b/packages/time-series/lib/commands/MADD.spec.ts @@ -1,39 +1,39 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MADD'; +import MADD from './MADD'; describe('MADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments([{ - key: '1', - timestamp: 0, - value: 0 - }, { - key: '2', - timestamp: 1, - value: 1 - }]), - ['TS.MADD', '1', '0', '0', '2', '1', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MADD.transformArguments([{ + key: '1', + timestamp: 0, + value: 0 + }, { + key: '2', + timestamp: 1, + value: 1 + }]), + ['TS.MADD', '1', '0', '0', '2', '1', '1'] + ); + }); - // Should we check empty array? + // Should we check empty array? - testUtils.testWithClient('client.ts.mAdd', async client => { - await client.ts.create('key'); + testUtils.testWithClient('client.ts.mAdd', async client => { + await client.ts.create('key'); - assert.deepEqual( - await client.ts.mAdd([{ - key: 'key', - timestamp: 0, - value: 0 - }, { - key: 'key', - timestamp: 1, - value: 1 - }]), - [0, 1] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + await client.ts.mAdd([{ + key: 'key', + timestamp: 0, + value: 0 + }, { + key: 'key', + timestamp: 1, + value: 1 + }]), + [0, 1] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MADD.ts b/packages/time-series/lib/commands/MADD.ts index 426eae7e3f3..fc4d22d13ae 100644 --- a/packages/time-series/lib/commands/MADD.ts +++ b/packages/time-series/lib/commands/MADD.ts @@ -1,25 +1,27 @@ import { Timestamp, transformTimestampArgument } from '.'; +import { ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -interface MAddSample { - key: string; - timestamp: Timestamp; - value: number; +export interface TsMAddSample { + key: string; + timestamp: Timestamp; + value: number; } -export function transformArguments(toAdd: Array): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(toAdd: Array) { const args = ['TS.MADD']; for (const { key, timestamp, value } of toAdd) { - args.push( - key, - transformTimestampArgument(timestamp), - value.toString() - ); + args.push( + key, + transformTimestampArgument(timestamp), + value.toString() + ); } return args; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; From a9ec9e2b9b0dfcc6e7c515b22adf246278606d79 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:41:38 -0400 Subject: [PATCH 158/325] fix DELETERULE --- .../lib/commands/DELETERULE.spec.ts | 36 +++++++++---------- .../time-series/lib/commands/DELETERULE.ts | 19 +++++----- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/packages/time-series/lib/commands/DELETERULE.spec.ts b/packages/time-series/lib/commands/DELETERULE.spec.ts index 9364bea711c..c131dbcef17 100644 --- a/packages/time-series/lib/commands/DELETERULE.spec.ts +++ b/packages/time-series/lib/commands/DELETERULE.spec.ts @@ -1,26 +1,26 @@ import { strict as assert } from 'assert'; import { TimeSeriesAggregationType } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DELETERULE'; +import DELETERULE from './DELETERULE'; describe('DELETERULE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('source', 'destination'), - ['TS.DELETERULE', 'source', 'destination'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DELETERULE.transformArguments('source', 'destination'), + ['TS.DELETERULE', 'source', 'destination'] + ); + }); - testUtils.testWithClient('client.ts.deleteRule', async client => { - await Promise.all([ - client.ts.create('source'), - client.ts.create('destination'), - client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1) - ]); + testUtils.testWithClient('client.ts.deleteRule', async client => { + await Promise.all([ + client.ts.create('source'), + client.ts.create('destination'), + client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1) + ]); - assert.equal( - await client.ts.deleteRule('source', 'destination'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ts.deleteRule('source', 'destination'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/DELETERULE.ts b/packages/time-series/lib/commands/DELETERULE.ts index 7d2cfaeed94..5cf88897f7d 100644 --- a/packages/time-series/lib/commands/DELETERULE.ts +++ b/packages/time-series/lib/commands/DELETERULE.ts @@ -1,11 +1,14 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(sourceKey: string, destinationKey: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(sourceKey: RedisArgument, destinationKey: RedisArgument) { return [ - 'TS.DELETERULE', - sourceKey, - destinationKey + 'TS.DELETERULE', + sourceKey, + destinationKey ]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; From 60d04338106787b08111fff8d1c6185617ab6270 Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 14:41:55 -0400 Subject: [PATCH 159/325] fix CREATERULE --- .../lib/commands/CREATERULE.spec.ts | 48 +++++++++---------- .../time-series/lib/commands/CREATERULE.ts | 34 ++++++------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/packages/time-series/lib/commands/CREATERULE.spec.ts b/packages/time-series/lib/commands/CREATERULE.spec.ts index 65457898181..bd336b78df5 100644 --- a/packages/time-series/lib/commands/CREATERULE.spec.ts +++ b/packages/time-series/lib/commands/CREATERULE.spec.ts @@ -1,34 +1,34 @@ import { strict as assert } from 'assert'; import { TimeSeriesAggregationType } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CREATERULE'; +import CREATERULE from './CREATERULE'; describe('CREATERULE', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), - ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), + ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1'] + ); + }); - it('with alignTimestamp', () => { - assert.deepEqual( - transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1, 1), - ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1'] - ); - }); + it('with alignTimestamp', () => { + assert.deepEqual( + CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1, 1), + ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1'] + ); }); + }); - testUtils.testWithClient('client.ts.createRule', async client => { - await Promise.all([ - client.ts.create('source'), - client.ts.create('destination') - ]); + testUtils.testWithClient('client.ts.createRule', async client => { + await Promise.all([ + client.ts.create('source'), + client.ts.create('destination') + ]); - assert.equal( - await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/CREATERULE.ts b/packages/time-series/lib/commands/CREATERULE.ts index 87b8579a6ee..8c4536f0393 100644 --- a/packages/time-series/lib/commands/CREATERULE.ts +++ b/packages/time-series/lib/commands/CREATERULE.ts @@ -1,28 +1,30 @@ import { TimeSeriesAggregationType } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - sourceKey: string, - destinationKey: string, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + sourceKey: RedisArgument, + destinationKey: RedisArgument, aggregationType: TimeSeriesAggregationType, bucketDuration: number, alignTimestamp?: number -): Array { + ) { const args = [ - 'TS.CREATERULE', - sourceKey, - destinationKey, - 'AGGREGATION', - aggregationType, - bucketDuration.toString() + 'TS.CREATERULE', + sourceKey, + destinationKey, + 'AGGREGATION', + aggregationType, + bucketDuration.toString() ]; if (alignTimestamp) { - args.push(alignTimestamp.toString()); + args.push(alignTimestamp.toString()); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; From ddc44d3c497dadb52af6e0c1b6e773a04832007b Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 15:17:45 -0400 Subject: [PATCH 160/325] fix GRAPH --- .../graph/lib/commands/CONFIG_GET.spec.ts | 32 +++++----- packages/graph/lib/commands/CONFIG_GET.ts | 23 +++---- .../graph/lib/commands/CONFIG_SET.spec.ts | 26 ++++---- packages/graph/lib/commands/CONFIG_SET.ts | 21 ++++--- packages/graph/lib/commands/DELETE.spec.ts | 28 ++++----- packages/graph/lib/commands/DELETE.ts | 13 ++-- packages/graph/lib/commands/EXPLAIN.spec.ts | 30 +++++----- packages/graph/lib/commands/EXPLAIN.ts | 15 ++--- packages/graph/lib/commands/LIST.spec.ts | 26 ++++---- packages/graph/lib/commands/LIST.ts | 13 ++-- packages/graph/lib/commands/PROFILE.spec.ts | 24 ++++---- packages/graph/lib/commands/PROFILE.ts | 15 ++--- packages/graph/lib/commands/QUERY.spec.ts | 22 +++---- packages/graph/lib/commands/QUERY.ts | 60 +++++++++---------- packages/graph/lib/commands/SLOWLOG.spec.ts | 22 +++---- 15 files changed, 193 insertions(+), 177 deletions(-) diff --git a/packages/graph/lib/commands/CONFIG_GET.spec.ts b/packages/graph/lib/commands/CONFIG_GET.spec.ts index 6e1fa74e219..c002bbdf0e0 100644 --- a/packages/graph/lib/commands/CONFIG_GET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_GET.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CONFIG_GET'; +import CONFIG_GET from './CONFIG_GET'; describe('CONFIG GET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('TIMEOUT'), - ['GRAPH.CONFIG', 'GET', 'TIMEOUT'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CONFIG_GET.transformArguments('TIMEOUT'), + ['GRAPH.CONFIG', 'GET', 'TIMEOUT'] + ); + }); - testUtils.testWithClient('client.graph.configGet', async client => { - assert.deepEqual( - await client.graph.configGet('TIMEOUT'), - [ - 'TIMEOUT', - 0 - ] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.configGet', async client => { + assert.deepEqual( + await client.graph.configGet('TIMEOUT'), + [ + 'TIMEOUT', + 0 + ] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/CONFIG_GET.ts b/packages/graph/lib/commands/CONFIG_GET.ts index ce80a1148ed..c7ed037e1a1 100644 --- a/packages/graph/lib/commands/CONFIG_GET.ts +++ b/packages/graph/lib/commands/CONFIG_GET.ts @@ -1,12 +1,15 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, TuplesReply, ArrayReply, BlobStringReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(configKey: string): Array { - return ['GRAPH.CONFIG', 'GET', configKey]; -} - -type ConfigItem = [ - configKey: string, - value: number -]; +type ConfigItemReply = TuplesReply<[ + configKey: BlobStringReply, + value: NumberReply +]>; -export declare function transformReply(): ConfigItem | Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(configKey: RedisArgument) { + return ['GRAPH.CONFIG', 'GET', configKey]; + }, + transformReply: undefined as unknown as () => ConfigItemReply | ArrayReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/CONFIG_SET.spec.ts b/packages/graph/lib/commands/CONFIG_SET.spec.ts index 51dce0a8cd9..02eed85cd95 100644 --- a/packages/graph/lib/commands/CONFIG_SET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_SET.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CONFIG_SET'; +import CONFIG_SET from './CONFIG_SET'; describe('CONFIG SET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('TIMEOUT', 0), - ['GRAPH.CONFIG', 'SET', 'TIMEOUT', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CONFIG_SET.transformArguments('TIMEOUT', 0), + ['GRAPH.CONFIG', 'SET', 'TIMEOUT', '0'] + ); + }); - testUtils.testWithClient('client.graph.configSet', async client => { - assert.equal( - await client.graph.configSet('TIMEOUT', 0), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.configSet', async client => { + assert.equal( + await client.graph.configSet('TIMEOUT', 0), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/CONFIG_SET.ts b/packages/graph/lib/commands/CONFIG_SET.ts index ac81449ad15..715f754ce38 100644 --- a/packages/graph/lib/commands/CONFIG_SET.ts +++ b/packages/graph/lib/commands/CONFIG_SET.ts @@ -1,10 +1,15 @@ -export function transformArguments(configKey: string, value: number): Array { +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(configKey: RedisArgument, value: number) { return [ - 'GRAPH.CONFIG', - 'SET', - configKey, - value.toString() + 'GRAPH.CONFIG', + 'SET', + configKey, + value.toString() ]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/DELETE.spec.ts b/packages/graph/lib/commands/DELETE.spec.ts index e51ac2bfab8..5b9fd2ceb61 100644 --- a/packages/graph/lib/commands/DELETE.spec.ts +++ b/packages/graph/lib/commands/DELETE.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DELETE'; +import DELETE from './DELETE'; describe('', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GRAPH.DELETE', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DELETE.transformArguments('key'), + ['GRAPH.DELETE', 'key'] + ); + }); - testUtils.testWithClient('client.graph.delete', async client => { - await client.graph.query('key', 'RETURN 1'); + testUtils.testWithClient('client.graph.delete', async client => { + await client.graph.query('key', 'RETURN 1'); - assert.equal( - typeof await client.graph.delete('key'), - 'string' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + typeof await client.graph.delete('key'), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/DELETE.ts b/packages/graph/lib/commands/DELETE.ts index 240708143c6..16c2566af01 100644 --- a/packages/graph/lib/commands/DELETE.ts +++ b/packages/graph/lib/commands/DELETE.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument) { return ['GRAPH.DELETE', key]; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/EXPLAIN.spec.ts b/packages/graph/lib/commands/EXPLAIN.spec.ts index 86d89b212cb..9e532307a92 100644 --- a/packages/graph/lib/commands/EXPLAIN.spec.ts +++ b/packages/graph/lib/commands/EXPLAIN.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './EXPLAIN'; +import EXPLAIN from './EXPLAIN'; describe('EXPLAIN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'RETURN 0'), - ['GRAPH.EXPLAIN', 'key', 'RETURN 0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EXPLAIN.transformArguments('key', 'RETURN 0'), + ['GRAPH.EXPLAIN', 'key', 'RETURN 0'] + ); + }); - testUtils.testWithClient('client.graph.explain', async client => { - const [, reply] = await Promise.all([ - client.graph.query('key', 'RETURN 0'), // make sure to create a graph first - client.graph.explain('key', 'RETURN 0') - ]); - assert.ok(Array.isArray(reply)); - assert.ok(!reply.find(x => typeof x !== 'string')); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.explain', async client => { + const [, reply] = await Promise.all([ + client.graph.query('key', 'RETURN 0'), // make sure to create a graph first + client.graph.explain('key', 'RETURN 0') + ]); + assert.ok(Array.isArray(reply)); + assert.ok(!reply.find(x => typeof x !== 'string')); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/EXPLAIN.ts b/packages/graph/lib/commands/EXPLAIN.ts index 419ff62b112..99a73bf04bf 100644 --- a/packages/graph/lib/commands/EXPLAIN.ts +++ b/packages/graph/lib/commands/EXPLAIN.ts @@ -1,9 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, query: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, query: RedisArgument) { return ['GRAPH.EXPLAIN', key, query]; -} - -export declare function transfromReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/LIST.spec.ts b/packages/graph/lib/commands/LIST.spec.ts index d4fab0358b9..3621adf1244 100644 --- a/packages/graph/lib/commands/LIST.spec.ts +++ b/packages/graph/lib/commands/LIST.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './LIST'; +import LIST from './LIST'; describe('LIST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['GRAPH.LIST'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LIST.transformArguments(), + ['GRAPH.LIST'] + ); + }); - testUtils.testWithClient('client.graph.list', async client => { - assert.deepEqual( - await client.graph.list(), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.list', async client => { + assert.deepEqual( + await client.graph.list(), + [] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/LIST.ts b/packages/graph/lib/commands/LIST.ts index 1939d43d889..01a868854be 100644 --- a/packages/graph/lib/commands/LIST.ts +++ b/packages/graph/lib/commands/LIST.ts @@ -1,7 +1,10 @@ -export const IS_READ_ONLY = true; +import { ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['GRAPH.LIST']; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/PROFILE.spec.ts b/packages/graph/lib/commands/PROFILE.spec.ts index 80857eb0ab9..8d967a1344e 100644 --- a/packages/graph/lib/commands/PROFILE.spec.ts +++ b/packages/graph/lib/commands/PROFILE.spec.ts @@ -1,18 +1,18 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PROFILE'; +import PROFILE from './PROFILE'; describe('PROFILE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'RETURN 0'), - ['GRAPH.PROFILE', 'key', 'RETURN 0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + PROFILE.transformArguments('key', 'RETURN 0'), + ['GRAPH.PROFILE', 'key', 'RETURN 0'] + ); + }); - testUtils.testWithClient('client.graph.profile', async client => { - const reply = await client.graph.profile('key', 'RETURN 0'); - assert.ok(Array.isArray(reply)); - assert.ok(!reply.find(x => typeof x !== 'string')); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.profile', async client => { + const reply = await client.graph.profile('key', 'RETURN 0'); + assert.ok(Array.isArray(reply)); + assert.ok(!reply.find(x => typeof x !== 'string')); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/PROFILE.ts b/packages/graph/lib/commands/PROFILE.ts index 473c526e679..2aa1e83dfb0 100644 --- a/packages/graph/lib/commands/PROFILE.ts +++ b/packages/graph/lib/commands/PROFILE.ts @@ -1,9 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, query: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, query: RedisArgument) { return ['GRAPH.PROFILE', key, query]; -} - -export declare function transfromReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/QUERY.spec.ts b/packages/graph/lib/commands/QUERY.spec.ts index c8a9a20372b..accbc5cc4cf 100644 --- a/packages/graph/lib/commands/QUERY.spec.ts +++ b/packages/graph/lib/commands/QUERY.spec.ts @@ -1,17 +1,17 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './QUERY'; +import QUERY from './QUERY'; describe('QUERY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'query'), - ['GRAPH.QUERY', 'key', 'query'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'query'), + ['GRAPH.QUERY', 'key', 'query'] + ); + }); - testUtils.testWithClient('client.graph.query', async client => { - const { data } = await client.graph.query('key', 'RETURN 0'); - assert.deepEqual(data, [[0]]); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.query', async client => { + const { data } = await client.graph.query('key', 'RETURN 0'); + assert.deepEqual(data, [[0]]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index 741cc6a3601..1d6a4229fa7 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -4,18 +4,18 @@ import { pushQueryArguments, QueryOptionsBackwardCompatible } from '.'; export const FIRST_KEY_INDEX = 1; export function transformArguments( - graph: RedisCommandArgument, - query: RedisCommandArgument, - options?: QueryOptionsBackwardCompatible, - compact?: boolean + graph: RedisCommandArgument, + query: RedisCommandArgument, + options?: QueryOptionsBackwardCompatible, + compact?: boolean ): RedisCommandArguments { - return pushQueryArguments( - ['GRAPH.QUERY'], - graph, - query, - options, - compact - ); + return pushQueryArguments( + ['GRAPH.QUERY'], + graph, + query, + options, + compact + ); } type Headers = Array; @@ -25,31 +25,31 @@ type Data = Array; type Metadata = Array; type QueryRawReply = [ - headers: Headers, - data: Data, - metadata: Metadata + headers: Headers, + data: Data, + metadata: Metadata ] | [ - metadata: Metadata + metadata: Metadata ]; export type QueryReply = { - headers: undefined; - data: undefined; - metadata: Metadata; + headers: undefined; + data: undefined; + metadata: Metadata; } | { - headers: Headers; - data: Data; - metadata: Metadata; + headers: Headers; + data: Data; + metadata: Metadata; }; export function transformReply(reply: QueryRawReply): QueryReply { - return reply.length === 1 ? { - headers: undefined, - data: undefined, - metadata: reply[0] - } : { - headers: reply[0], - data: reply[1], - metadata: reply[2] - }; + return reply.length === 1 ? { + headers: undefined, + data: undefined, + metadata: reply[0] + } : { + headers: reply[0], + data: reply[1], + metadata: reply[2] + }; } diff --git a/packages/graph/lib/commands/SLOWLOG.spec.ts b/packages/graph/lib/commands/SLOWLOG.spec.ts index e3083b994d6..00ec90e9450 100644 --- a/packages/graph/lib/commands/SLOWLOG.spec.ts +++ b/packages/graph/lib/commands/SLOWLOG.spec.ts @@ -3,16 +3,16 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SLOWLOG'; describe('SLOWLOG', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['GRAPH.SLOWLOG', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['GRAPH.SLOWLOG', 'key'] + ); + }); - testUtils.testWithClient('client.graph.slowLog', async client => { - await client.graph.query('key', 'RETURN 1'); - const reply = await client.graph.slowLog('key'); - assert.equal(reply.length, 1); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.slowLog', async client => { + await client.graph.query('key', 'RETURN 1'); + const reply = await client.graph.slowLog('key'); + assert.equal(reply.length, 1); + }, GLOBAL.SERVERS.OPEN); }); From 2dd1f2ca385dd8a36b88b3bd1cd9f86521f1df40 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 5 Jul 2023 15:22:33 -0400 Subject: [PATCH 161/325] bloom module --- .github/workflows/tests.yml | 2 +- docs/v4-to-v5.md | 1 + packages/bloom/lib/commands/bloom/ADD.spec.ts | 28 ++-- packages/bloom/lib/commands/bloom/ADD.ts | 14 +- .../bloom/lib/commands/bloom/CARD.spec.ts | 28 ++-- packages/bloom/lib/commands/bloom/CARD.ts | 15 +- .../bloom/lib/commands/bloom/EXISTS.spec.ts | 28 ++-- packages/bloom/lib/commands/bloom/EXISTS.ts | 16 ++- .../bloom/lib/commands/bloom/INFO.spec.ts | 42 +++--- packages/bloom/lib/commands/bloom/INFO.ts | 95 +++++++----- .../bloom/lib/commands/bloom/INSERT.spec.ts | 114 +++++++-------- packages/bloom/lib/commands/bloom/INSERT.ts | 56 ++++---- .../lib/commands/bloom/LOADCHUNK.spec.ts | 51 ++++--- .../bloom/lib/commands/bloom/LOADCHUNK.ts | 21 ++- .../bloom/lib/commands/bloom/MADD.spec.ts | 28 ++-- packages/bloom/lib/commands/bloom/MADD.ts | 17 ++- .../bloom/lib/commands/bloom/MEXISTS.spec.ts | 28 ++-- packages/bloom/lib/commands/bloom/MEXISTS.ts | 19 +-- .../bloom/lib/commands/bloom/RESERVE.spec.ts | 80 +++++------ packages/bloom/lib/commands/bloom/RESERVE.ts | 26 ++-- .../bloom/lib/commands/bloom/SCANDUMP.spec.ts | 34 ++--- packages/bloom/lib/commands/bloom/SCANDUMP.ts | 31 ++-- packages/bloom/lib/commands/bloom/index.ts | 74 ++++++---- .../commands/count-min-sketch/INCRBY.spec.ts | 69 ++++----- .../lib/commands/count-min-sketch/INCRBY.ts | 37 ++--- .../commands/count-min-sketch/INFO.spec.ts | 40 +++--- .../lib/commands/count-min-sketch/INFO.ts | 49 +++---- .../count-min-sketch/INITBYDIM.spec.ts | 28 ++-- .../commands/count-min-sketch/INITBYDIM.ts | 13 +- .../count-min-sketch/INITBYPROB.spec.ts | 28 ++-- .../commands/count-min-sketch/INITBYPROB.ts | 13 +- .../commands/count-min-sketch/MERGE.spec.ts | 54 ++++--- .../lib/commands/count-min-sketch/MERGE.ts | 52 +++---- .../commands/count-min-sketch/QUERY.spec.ts | 31 ++-- .../lib/commands/count-min-sketch/QUERY.ts | 22 ++- .../lib/commands/count-min-sketch/index.ts | 46 +++--- .../bloom/lib/commands/cuckoo/ADD.spec.ts | 28 ++-- packages/bloom/lib/commands/cuckoo/ADD.ts | 14 +- .../bloom/lib/commands/cuckoo/ADDNX.spec.ts | 30 ++-- packages/bloom/lib/commands/cuckoo/ADDNX.ts | 14 +- .../bloom/lib/commands/cuckoo/COUNT.spec.ts | 28 ++-- packages/bloom/lib/commands/cuckoo/COUNT.ts | 13 +- .../bloom/lib/commands/cuckoo/DEL.spec.ts | 30 ++-- packages/bloom/lib/commands/cuckoo/DEL.ts | 14 +- .../bloom/lib/commands/cuckoo/EXISTS.spec.ts | 28 ++-- packages/bloom/lib/commands/cuckoo/EXISTS.ts | 16 ++- .../bloom/lib/commands/cuckoo/INFO.spec.ts | 48 +++---- packages/bloom/lib/commands/cuckoo/INFO.ts | 90 ++++++------ .../bloom/lib/commands/cuckoo/INSERT.spec.ts | 34 ++--- packages/bloom/lib/commands/cuckoo/INSERT.ts | 44 ++++-- .../lib/commands/cuckoo/INSERTNX.spec.ts | 34 ++--- .../bloom/lib/commands/cuckoo/INSERTNX.ts | 25 ++-- .../lib/commands/cuckoo/LOADCHUNK.spec.ts | 55 +++---- .../bloom/lib/commands/cuckoo/LOADCHUNK.ts | 19 ++- .../bloom/lib/commands/cuckoo/RESERVE.spec.ts | 78 +++++----- packages/bloom/lib/commands/cuckoo/RESERVE.ts | 39 ++--- .../lib/commands/cuckoo/SCANDUMP.spec.ts | 37 ++--- .../bloom/lib/commands/cuckoo/SCANDUMP.ts | 29 ++-- .../bloom/lib/commands/cuckoo/index.spec.ts | 48 ------- packages/bloom/lib/commands/cuckoo/index.ts | 102 ++++++------- packages/bloom/lib/commands/index.ts | 13 +- .../bloom/lib/commands/t-digest/ADD.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/ADD.ts | 23 ++- .../lib/commands/t-digest/BYRANK.spec.ts | 28 ++-- .../bloom/lib/commands/t-digest/BYRANK.ts | 33 +++-- .../lib/commands/t-digest/BYREVRANK.spec.ts | 28 ++-- .../bloom/lib/commands/t-digest/BYREVRANK.ts | 28 ++-- .../bloom/lib/commands/t-digest/CDF.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/CDF.ts | 24 ++-- .../lib/commands/t-digest/CREATE.spec.ts | 44 +++--- .../bloom/lib/commands/t-digest/CREATE.ts | 30 ++-- .../bloom/lib/commands/t-digest/INFO.spec.ts | 44 +++--- packages/bloom/lib/commands/t-digest/INFO.ts | 90 ++++++------ .../bloom/lib/commands/t-digest/MAX.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/MAX.ts | 25 ++-- .../bloom/lib/commands/t-digest/MERGE.spec.ts | 78 +++++----- packages/bloom/lib/commands/t-digest/MERGE.ts | 42 +++--- .../bloom/lib/commands/t-digest/MIN.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/MIN.ts | 25 ++-- .../lib/commands/t-digest/QUANTILE.spec.ts | 34 ++--- .../bloom/lib/commands/t-digest/QUANTILE.ts | 28 ++-- .../bloom/lib/commands/t-digest/RANK.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/RANK.ts | 31 ++-- .../bloom/lib/commands/t-digest/RESET.spec.ts | 28 ++-- packages/bloom/lib/commands/t-digest/RESET.ts | 15 +- .../lib/commands/t-digest/REVRANK.spec.ts | 28 ++-- .../bloom/lib/commands/t-digest/REVRANK.ts | 28 ++-- .../commands/t-digest/TRIMMED_MEAN.spec.ts | 30 ++-- .../lib/commands/t-digest/TRIMMED_MEAN.ts | 30 ++-- .../bloom/lib/commands/t-digest/index.spec.ts | 55 ------- packages/bloom/lib/commands/t-digest/index.ts | 135 ++++++++---------- packages/bloom/lib/commands/top-k/ADD.spec.ts | 31 ++-- packages/bloom/lib/commands/top-k/ADD.ts | 20 ++- .../bloom/lib/commands/top-k/COUNT.spec.ts | 30 ++-- packages/bloom/lib/commands/top-k/COUNT.ts | 22 ++- .../bloom/lib/commands/top-k/INCRBY.spec.ts | 68 ++++----- packages/bloom/lib/commands/top-k/INCRBY.ts | 41 +++--- .../bloom/lib/commands/top-k/INFO.spec.ts | 35 ++--- packages/bloom/lib/commands/top-k/INFO.ts | 55 +++---- .../bloom/lib/commands/top-k/LIST.spec.ts | 30 ++-- packages/bloom/lib/commands/top-k/LIST.ts | 15 +- .../lib/commands/top-k/LIST_WITHCOUNT.spec.ts | 45 +++--- .../lib/commands/top-k/LIST_WITHCOUNT.ts | 38 +++-- .../bloom/lib/commands/top-k/QUERY.spec.ts | 30 ++-- packages/bloom/lib/commands/top-k/QUERY.ts | 22 ++- .../bloom/lib/commands/top-k/RESERVE.spec.ts | 50 +++---- packages/bloom/lib/commands/top-k/RESERVE.ts | 37 +++-- packages/bloom/lib/commands/top-k/index.ts | 57 ++++---- packages/bloom/lib/test-utils.ts | 20 +-- .../lib/commands/XADD_NOMKSTREAM.spec.ts | 2 + .../lib/commands/generic-transformers.ts | 20 ++- packages/client/tsconfig.json | 3 - tsconfig.base.json | 3 +- tsconfig.json | 4 +- 114 files changed, 1982 insertions(+), 2060 deletions(-) delete mode 100644 packages/bloom/lib/commands/cuckoo/index.spec.ts delete mode 100644 packages/bloom/lib/commands/t-digest/index.spec.ts diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 381b79d14fb..97658828676 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,7 +34,7 @@ jobs: - name: Build run: npm run build -- ./packages/client ./packages/test-utils/ - name: Run Tests - run: npm run test -w ./packages/client -- --forbid-only --redis-version=${{ matrix.redis-version }} + run: npm run test -w ./packages/client -- --forbid-only --redis-version=${{ matrix.redis-version }} && npm run test -w ./packages/bloom -- --forbid-only - name: Upload to Codecov run: | curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 91d88c066e7..cfe91df18a4 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -174,6 +174,7 @@ Some command arguments/replies have changed to align more closely to data types - `XINFO GROUPS`: `lastDeliveredId` -> `last-delivered-id` [^map-keys] - `XINFO STREAM`: `radixTreeKeys` -> `radix-tree-keys`, `radixTreeNodes` -> `radix-tree-nodes`, `lastGeneratedId` -> `last-generated-id`, `maxDeletedEntryId` -> `max-deleted-entry-id`, `entriesAdded` -> `entries-added`, `recordedFirstEntryId` -> `recorded-first-entry-id`, `firstEntry` -> `first-entry`, `lastEntry` -> `last-entry` - `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record }>; }>` -> `Record }>>` +`TOPK.QUERY`: `Array` -> `Array` [^enum-to-constants]: TODO diff --git a/packages/bloom/lib/commands/bloom/ADD.spec.ts b/packages/bloom/lib/commands/bloom/ADD.spec.ts index e7ec3409136..5a14e0c7799 100644 --- a/packages/bloom/lib/commands/bloom/ADD.spec.ts +++ b/packages/bloom/lib/commands/bloom/ADD.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './ADD'; +import ADD from './ADD'; -describe('BF ADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['BF.ADD', 'key', 'item'] - ); - }); +describe('BF.ADD', () => { + it('transformArguments', () => { + assert.deepEqual( + ADD.transformArguments('key', 'item'), + ['BF.ADD', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.bf.add', async client => { - assert.equal( - await client.bf.add('key', 'item'), - true - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.add', async client => { + assert.equal( + await client.bf.add('key', 'item'), + true + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/ADD.ts b/packages/bloom/lib/commands/bloom/ADD.ts index d8938f4c2b0..a9655754897 100644 --- a/packages/bloom/lib/commands/bloom/ADD.ts +++ b/packages/bloom/lib/commands/bloom/ADD.ts @@ -1,7 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['BF.ADD', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/CARD.spec.ts b/packages/bloom/lib/commands/bloom/CARD.spec.ts index 4d5620ea196..ed54a436148 100644 --- a/packages/bloom/lib/commands/bloom/CARD.spec.ts +++ b/packages/bloom/lib/commands/bloom/CARD.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './CARD'; +import CARD from './CARD'; -describe('BF CARD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('bloom'), - ['BF.CARD', 'bloom'] - ); - }); +describe('BF.CARD', () => { + it('transformArguments', () => { + assert.deepEqual( + CARD.transformArguments('bloom'), + ['BF.CARD', 'bloom'] + ); + }); - testUtils.testWithClient('client.bf.card', async client => { - assert.equal( - await client.bf.card('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.card', async client => { + assert.equal( + await client.bf.card('key'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/CARD.ts b/packages/bloom/lib/commands/bloom/CARD.ts index 530284c3f60..ddaa76cc1f8 100644 --- a/packages/bloom/lib/commands/bloom/CARD.ts +++ b/packages/bloom/lib/commands/bloom/CARD.ts @@ -1,9 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['BF.CARD', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/EXISTS.spec.ts b/packages/bloom/lib/commands/bloom/EXISTS.spec.ts index 1088e739e61..276607b5d1e 100644 --- a/packages/bloom/lib/commands/bloom/EXISTS.spec.ts +++ b/packages/bloom/lib/commands/bloom/EXISTS.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './EXISTS'; +import EXISTS from './EXISTS'; -describe('BF EXISTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['BF.EXISTS', 'key', 'item'] - ); - }); +describe('BF.EXISTS', () => { + it('transformArguments', () => { + assert.deepEqual( + EXISTS.transformArguments('key', 'item'), + ['BF.EXISTS', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.bf.exists', async client => { - assert.equal( - await client.bf.exists('key', 'item'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.exists', async client => { + assert.equal( + await client.bf.exists('key', 'item'), + false + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/EXISTS.ts b/packages/bloom/lib/commands/bloom/EXISTS.ts index d044207e244..9d28d671d61 100644 --- a/packages/bloom/lib/commands/bloom/EXISTS.ts +++ b/packages/bloom/lib/commands/bloom/EXISTS.ts @@ -1,9 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['BF.EXISTS', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/INFO.spec.ts b/packages/bloom/lib/commands/bloom/INFO.spec.ts index 7a5e5724c22..7a9f30faa71 100644 --- a/packages/bloom/lib/commands/bloom/INFO.spec.ts +++ b/packages/bloom/lib/commands/bloom/INFO.spec.ts @@ -1,24 +1,24 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INFO'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../../test-utils'; +// import { transformArguments } from './INFO'; -describe('BF INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('bloom'), - ['BF.INFO', 'bloom'] - ); - }); +// describe('BF INFO', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('bloom'), +// ['BF.INFO', 'bloom'] +// ); +// }); - testUtils.testWithClient('client.bf.info', async client => { - await client.bf.reserve('key', 0.01, 100); +// testUtils.testWithClient('client.bf.info', async client => { +// await client.bf.reserve('key', 0.01, 100); - const info = await client.bf.info('key'); - assert.equal(typeof info, 'object'); - assert.equal(info.capacity, 100); - assert.equal(typeof info.size, 'number'); - assert.equal(typeof info.numberOfFilters, 'number'); - assert.equal(typeof info.numberOfInsertedItems, 'number'); - assert.equal(typeof info.expansionRate, 'number'); - }, GLOBAL.SERVERS.OPEN); -}); +// const info = await client.bf.info('key'); +// assert.equal(typeof info, 'object'); +// assert.equal(info.capacity, 100); +// assert.equal(typeof info.size, 'number'); +// assert.equal(typeof info.numberOfFilters, 'number'); +// assert.equal(typeof info.numberOfInsertedItems, 'number'); +// assert.equal(typeof info.expansionRate, 'number'); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/bloom/lib/commands/bloom/INFO.ts b/packages/bloom/lib/commands/bloom/INFO.ts index 52e97646404..7954053f0f5 100644 --- a/packages/bloom/lib/commands/bloom/INFO.ts +++ b/packages/bloom/lib/commands/bloom/INFO.ts @@ -1,38 +1,57 @@ -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { - return ['BF.INFO', key]; -} - -export type InfoRawReply = [ - _: string, - capacity: number, - _: string, - size: number, - _: string, - numberOfFilters: number, - _: string, - numberOfInsertedItems: number, - _: string, - expansionRate: number, -]; - -export interface InfoReply { - capacity: number; - size: number; - numberOfFilters: number; - numberOfInsertedItems: number; - expansionRate: number; -} - -export function transformReply(reply: InfoRawReply): InfoReply { - return { - capacity: reply[1], - size: reply[3], - numberOfFilters: reply[5], - numberOfInsertedItems: reply[7], - expansionRate: reply[9] - }; -} +// // export type InfoRawReply = [ +// // _: string, +// // capacity: number, +// // _: string, +// // size: number, +// // _: string, +// // numberOfFilters: number, +// // _: string, +// // numberOfInsertedItems: number, +// // _: string, +// // expansionRate: number, +// // ]; + +// // export interface InfoReply { +// // capacity: number; +// // size: number; +// // numberOfFilters: number; +// // numberOfInsertedItems: number; +// // expansionRate: number; +// // } + +// // export function transformReply(reply: InfoRawReply): InfoReply { +// // return { +// // capacity: reply[1], +// // size: reply[3], +// // numberOfFilters: reply[5], +// // numberOfInsertedItems: reply[7], +// // expansionRate: reply[9] +// // }; +// // } + +// import { RedisArgument, Command, TuplesToMapReply, BlobStringReply, NumberReply } from '@redis/client/dist/lib/RESP/types'; +// import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; + +// export type BfInfoReply = TuplesToMapReply<[ +// [BlobStringReply<'Capacity'>, NumberReply], +// [BlobStringReply<'Size'>, NumberReply], +// [BlobStringReply<'Number of filters'>, NumberReply], + + +// ]>; + +// export default { +// FIRST_KEY_INDEX: 1, +// IS_READ_ONLY: true, +// transformArguments(key: RedisArgument) { +// return ['BF.INFO', key]; +// }, +// transformReply: { +// 2: () => { + +// }, +// 3: () => { + +// } +// } +// } as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/INSERT.spec.ts b/packages/bloom/lib/commands/bloom/INSERT.spec.ts index aff9e6e282b..cb18dcd7a11 100644 --- a/packages/bloom/lib/commands/bloom/INSERT.spec.ts +++ b/packages/bloom/lib/commands/bloom/INSERT.spec.ts @@ -1,69 +1,69 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INSERT'; +import INSERT from './INSERT'; -describe('BF INSERT', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['BF.INSERT', 'key', 'ITEMS', 'item'] - ); - }); +describe('BF.INSERT', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item'), + ['BF.INSERT', 'key', 'ITEMS', 'item'] + ); + }); - it('with CAPACITY', () => { - assert.deepEqual( - transformArguments('key', 'item', { CAPACITY: 100 }), - ['BF.INSERT', 'key', 'CAPACITY', '100', 'ITEMS', 'item'] - ); - }); + it('with CAPACITY', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { CAPACITY: 100 }), + ['BF.INSERT', 'key', 'CAPACITY', '100', 'ITEMS', 'item'] + ); + }); - it('with ERROR', () => { - assert.deepEqual( - transformArguments('key', 'item', { ERROR: 0.01 }), - ['BF.INSERT', 'key', 'ERROR', '0.01', 'ITEMS', 'item'] - ); - }); + it('with ERROR', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { ERROR: 0.01 }), + ['BF.INSERT', 'key', 'ERROR', '0.01', 'ITEMS', 'item'] + ); + }); - it('with EXPANSION', () => { - assert.deepEqual( - transformArguments('key', 'item', { EXPANSION: 1 }), - ['BF.INSERT', 'key', 'EXPANSION', '1', 'ITEMS', 'item'] - ); - }); + it('with EXPANSION', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { EXPANSION: 1 }), + ['BF.INSERT', 'key', 'EXPANSION', '1', 'ITEMS', 'item'] + ); + }); - it('with NOCREATE', () => { - assert.deepEqual( - transformArguments('key', 'item', { NOCREATE: true }), - ['BF.INSERT', 'key', 'NOCREATE', 'ITEMS', 'item'] - ); - }); + it('with NOCREATE', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { NOCREATE: true }), + ['BF.INSERT', 'key', 'NOCREATE', 'ITEMS', 'item'] + ); + }); - it('with NONSCALING', () => { - assert.deepEqual( - transformArguments('key', 'item', { NONSCALING: true }), - ['BF.INSERT', 'key', 'NONSCALING', 'ITEMS', 'item'] - ); - }); + it('with NONSCALING', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { NONSCALING: true }), + ['BF.INSERT', 'key', 'NONSCALING', 'ITEMS', 'item'] + ); + }); - it('with CAPACITY, ERROR, EXPANSION, NOCREATE and NONSCALING', () => { - assert.deepEqual( - transformArguments('key', 'item', { - CAPACITY: 100, - ERROR: 0.01, - EXPANSION: 1, - NOCREATE: true, - NONSCALING: true - }), - ['BF.INSERT', 'key', 'CAPACITY', '100', 'ERROR', '0.01', 'EXPANSION', '1', 'NOCREATE', 'NONSCALING', 'ITEMS', 'item'] - ); - }); + it('with CAPACITY, ERROR, EXPANSION, NOCREATE and NONSCALING', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { + CAPACITY: 100, + ERROR: 0.01, + EXPANSION: 1, + NOCREATE: true, + NONSCALING: true + }), + ['BF.INSERT', 'key', 'CAPACITY', '100', 'ERROR', '0.01', 'EXPANSION', '1', 'NOCREATE', 'NONSCALING', 'ITEMS', 'item'] + ); }); + }); - testUtils.testWithClient('client.bf.insert', async client => { - assert.deepEqual( - await client.bf.insert('key', 'item'), - [true] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.insert', async client => { + assert.deepEqual( + await client.bf.insert('key', 'item'), + [true] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/INSERT.ts b/packages/bloom/lib/commands/bloom/INSERT.ts index 4c3cec0f79b..dfeaf5f20de 100644 --- a/packages/bloom/lib/commands/bloom/INSERT.ts +++ b/packages/bloom/lib/commands/bloom/INSERT.ts @@ -1,45 +1,47 @@ -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -export const FIRST_KEY_INDEX = 1; - -interface InsertOptions { - CAPACITY?: number; - ERROR?: number; - EXPANSION?: number; - NOCREATE?: true; - NONSCALING?: true; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; + +export interface BfInsertOptions { + CAPACITY?: number; + ERROR?: number; + EXPANSION?: number; + NOCREATE?: boolean; + NONSCALING?: boolean; } -export function transformArguments( - key: string, - items: RedisCommandArgument | Array, - options?: InsertOptions -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + items: RedisVariadicArgument, + options?: BfInsertOptions + ) { const args = ['BF.INSERT', key]; - if (options?.CAPACITY) { - args.push('CAPACITY', options.CAPACITY.toString()); + if (options?.CAPACITY !== undefined) { + args.push('CAPACITY', options.CAPACITY.toString()); } - if (options?.ERROR) { - args.push('ERROR', options.ERROR.toString()); + if (options?.ERROR !== undefined) { + args.push('ERROR', options.ERROR.toString()); } - if (options?.EXPANSION) { - args.push('EXPANSION', options.EXPANSION.toString()); + if (options?.EXPANSION !== undefined) { + args.push('EXPANSION', options.EXPANSION.toString()); } if (options?.NOCREATE) { - args.push('NOCREATE'); + args.push('NOCREATE'); } if (options?.NONSCALING) { - args.push('NONSCALING'); + args.push('NONSCALING'); } args.push('ITEMS'); return pushVariadicArguments(args, items); -} - -export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts b/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts index 19634cb4a78..29a22cbd713 100644 --- a/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts +++ b/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts @@ -1,28 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './LOADCHUNK'; +import LOADCHUNK from './LOADCHUNK'; +import { RESP_TYPES } from '@redis/client'; -describe('BF LOADCHUNK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, ''), - ['BF.LOADCHUNK', 'key', '0', ''] - ); - }); +describe('BF.LOADCHUNK', () => { + it('transformArguments', () => { + assert.deepEqual( + LOADCHUNK.transformArguments('key', 0, ''), + ['BF.LOADCHUNK', 'key', '0', ''] + ); + }); - testUtils.testWithClient('client.bf.loadChunk', async client => { - const [, { iterator, chunk }] = await Promise.all([ - client.bf.reserve('source', 0.01, 100), - client.bf.scanDump( - client.commandOptions({ returnBuffers: true }), - 'source', - 0 - ) - ]); + testUtils.testWithClient('client.bf.loadChunk', async client => { + const [, { iterator, chunk }] = await Promise.all([ + client.bf.reserve('source', 0.01, 100), + client.bf.scanDump('source', 0) + ]); - assert.equal( - await client.bf.loadChunk('destination', iterator, chunk), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.bf.loadChunk('destination', iterator, chunk), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + ...GLOBAL.SERVERS.OPEN.clientOptions, + commandOptions: { + typeMapping: { + [RESP_TYPES.BLOB_STRING]: Buffer + } + } + } + }); }); diff --git a/packages/bloom/lib/commands/bloom/LOADCHUNK.ts b/packages/bloom/lib/commands/bloom/LOADCHUNK.ts index 491f572a49e..feade2fac4c 100644 --- a/packages/bloom/lib/commands/bloom/LOADCHUNK.ts +++ b/packages/bloom/lib/commands/bloom/LOADCHUNK.ts @@ -1,13 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: string, - iteretor: number, - chunk: RedisCommandArgument -): RedisCommandArguments { - return ['BF.LOADCHUNK', key, iteretor.toString(), chunk]; -} - -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, iterator: number, chunk: RedisArgument) { + return ['BF.LOADCHUNK', key, iterator.toString(), chunk]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/MADD.spec.ts b/packages/bloom/lib/commands/bloom/MADD.spec.ts index 784f99926ff..f4abf6e2480 100644 --- a/packages/bloom/lib/commands/bloom/MADD.spec.ts +++ b/packages/bloom/lib/commands/bloom/MADD.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './MADD'; +import MADD from './MADD'; -describe('BF MADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['BF.MADD', 'key', '1', '2'] - ); - }); +describe('BF.MADD', () => { + it('transformArguments', () => { + assert.deepEqual( + MADD.transformArguments('key', ['1', '2']), + ['BF.MADD', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.ts.mAdd', async client => { - assert.deepEqual( - await client.bf.mAdd('key', ['1', '2']), - [true, true] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.ts.mAdd', async client => { + assert.deepEqual( + await client.bf.mAdd('key', ['1', '2']), + [true, true] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/MADD.ts b/packages/bloom/lib/commands/bloom/MADD.ts index 056c4a1c1c2..afb122476fd 100644 --- a/packages/bloom/lib/commands/bloom/MADD.ts +++ b/packages/bloom/lib/commands/bloom/MADD.ts @@ -1,7 +1,12 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(key: string, items: Array): Array { - return ['BF.MADD', key, ...items]; -} - -export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { + return pushVariadicArguments(['BF.MADD', key], items); + }, + transformReply: transformBooleanArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts b/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts index 027e51d2c43..0023a41e9b2 100644 --- a/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts +++ b/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './MEXISTS'; +import MEXISTS from './MEXISTS'; -describe('BF MEXISTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['BF.MEXISTS', 'key', '1', '2'] - ); - }); +describe('BF.MEXISTS', () => { + it('transformArguments', () => { + assert.deepEqual( + MEXISTS.transformArguments('key', ['1', '2']), + ['BF.MEXISTS', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.bf.mExists', async client => { - assert.deepEqual( - await client.bf.mExists('key', ['1', '2']), - [false, false] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.mExists', async client => { + assert.deepEqual( + await client.bf.mExists('key', ['1', '2']), + [false, false] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/MEXISTS.ts b/packages/bloom/lib/commands/bloom/MEXISTS.ts index fb79410155d..a23b713b50c 100644 --- a/packages/bloom/lib/commands/bloom/MEXISTS.ts +++ b/packages/bloom/lib/commands/bloom/MEXISTS.ts @@ -1,9 +1,12 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, items: Array): Array { - return ['BF.MEXISTS', key, ...items]; -} - -export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { + return pushVariadicArguments(['BF.MEXISTS', key], items); + }, + transformReply: transformBooleanArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/RESERVE.spec.ts b/packages/bloom/lib/commands/bloom/RESERVE.spec.ts index bc872f9c3f7..dfb6c820ff4 100644 --- a/packages/bloom/lib/commands/bloom/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/bloom/RESERVE.spec.ts @@ -1,49 +1,49 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './RESERVE'; +import RESERVE from './RESERVE'; -describe('BF RESERVE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 0.01, 100), - ['BF.RESERVE', 'key', '0.01', '100'] - ); - }); +describe('BF.RESERVE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 0.01, 100), + ['BF.RESERVE', 'key', '0.01', '100'] + ); + }); - it('with EXPANSION', () => { - assert.deepEqual( - transformArguments('key', 0.01, 100, { - EXPANSION: 1 - }), - ['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1'] - ); - }); + it('with EXPANSION', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 0.01, 100, { + EXPANSION: 1 + }), + ['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1'] + ); + }); - it('with NONSCALING', () => { - assert.deepEqual( - transformArguments('key', 0.01, 100, { - NONSCALING: true - }), - ['BF.RESERVE', 'key', '0.01', '100', 'NONSCALING'] - ); - }); + it('with NONSCALING', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 0.01, 100, { + NONSCALING: true + }), + ['BF.RESERVE', 'key', '0.01', '100', 'NONSCALING'] + ); + }); - it('with EXPANSION and NONSCALING', () => { - assert.deepEqual( - transformArguments('key', 0.01, 100, { - EXPANSION: 1, - NONSCALING: true - }), - ['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1', 'NONSCALING'] - ); - }); + it('with EXPANSION and NONSCALING', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 0.01, 100, { + EXPANSION: 1, + NONSCALING: true + }), + ['BF.RESERVE', 'key', '0.01', '100', 'EXPANSION', '1', 'NONSCALING'] + ); }); + }); - testUtils.testWithClient('client.bf.reserve', async client => { - assert.equal( - await client.bf.reserve('bloom', 0.01, 100), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.reserve', async client => { + assert.equal( + await client.bf.reserve('bloom', 0.01, 100), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/RESERVE.ts b/packages/bloom/lib/commands/bloom/RESERVE.ts index 18d7002f158..c4602535236 100644 --- a/packages/bloom/lib/commands/bloom/RESERVE.ts +++ b/packages/bloom/lib/commands/bloom/RESERVE.ts @@ -1,16 +1,20 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -interface ReserveOptions { - EXPANSION?: number; - NONSCALING?: true; +export interface BfReserveOptions { + EXPANSION?: number; + NONSCALING?: boolean; } -export function transformArguments( - key: string, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, errorRate: number, capacity: number, - options?: ReserveOptions -): Array { + options?: BfReserveOptions + ) { const args = ['BF.RESERVE', key, errorRate.toString(), capacity.toString()]; if (options?.EXPANSION) { @@ -22,6 +26,6 @@ export function transformArguments( } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts b/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts index 50119590482..4e5f5c3cccc 100644 --- a/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts +++ b/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './SCANDUMP'; +import SCANDUMP from './SCANDUMP'; -describe('BF SCANDUMP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0), - ['BF.SCANDUMP', 'key', '0'] - ); - }); +describe('BF.SCANDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + SCANDUMP.transformArguments('key', 0), + ['BF.SCANDUMP', 'key', '0'] + ); + }); - testUtils.testWithClient('client.bf.scanDump', async client => { - const [, dump] = await Promise.all([ - client.bf.reserve('key', 0.01, 100), - client.bf.scanDump('key', 0) - ]); - assert.equal(typeof dump, 'object'); - assert.equal(typeof dump.iterator, 'number'); - assert.equal(typeof dump.chunk, 'string'); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.bf.scanDump', async client => { + const [, dump] = await Promise.all([ + client.bf.reserve('key', 0.01, 100), + client.bf.scanDump('key', 0) + ]); + assert.equal(typeof dump, 'object'); + assert.equal(typeof dump.iterator, 'number'); + assert.equal(typeof dump.chunk, 'string'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/bloom/SCANDUMP.ts b/packages/bloom/lib/commands/bloom/SCANDUMP.ts index 04b3edc2a1f..be5367b872f 100644 --- a/packages/bloom/lib/commands/bloom/SCANDUMP.ts +++ b/packages/bloom/lib/commands/bloom/SCANDUMP.ts @@ -1,24 +1,15 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, iterator: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, iterator: number) { return ['BF.SCANDUMP', key, iterator.toString()]; -} - -type ScanDumpRawReply = [ - iterator: number, - chunk: string -]; - -interface ScanDumpReply { - iterator: number; - chunk: string; -} - -export function transformReply([iterator, chunk]: ScanDumpRawReply): ScanDumpReply { + }, + transformReply(reply: TuplesReply<[NumberReply, BlobStringReply]>) { return { - iterator, - chunk + iterator: reply[0], + chunk: reply[1] }; -} + } +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/index.ts b/packages/bloom/lib/commands/bloom/index.ts index f18b8f71095..1e87c8bd455 100644 --- a/packages/bloom/lib/commands/bloom/index.ts +++ b/packages/bloom/lib/commands/bloom/index.ts @@ -1,33 +1,45 @@ -import * as ADD from './ADD'; -import * as CARD from './CARD'; -import * as EXISTS from './EXISTS'; -import * as INFO from './INFO'; -import * as INSERT from './INSERT'; -import * as LOADCHUNK from './LOADCHUNK'; -import * as MADD from './MADD'; -import * as MEXISTS from './MEXISTS'; -import * as RESERVE from './RESERVE'; -import * as SCANDUMP from './SCANDUMP'; +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; +import ADD from './ADD'; +import CARD from './CARD'; +import EXISTS from './EXISTS'; +// import INFO from './INFO'; +import INSERT from './INSERT'; +import LOADCHUNK from './LOADCHUNK'; +import MADD from './MADD'; +import MEXISTS from './MEXISTS'; +import RESERVE from './RESERVE'; +import SCANDUMP from './SCANDUMP'; + +type ADD = typeof import('./ADD').default; +type CARD = typeof import('./CARD').default; +type EXISTS = typeof import('./EXISTS').default; +// type INFO = typeof import('./INFO').default; +type INSERT = typeof import('./INSERT').default; +type LOADCHUNK = typeof import('./LOADCHUNK').default; +type MADD = typeof import('./MADD').default; +type MEXISTS = typeof import('./MEXISTS').default; +type RESERVE = typeof import('./RESERVE').default; +type SCANDUMP = typeof import('./SCANDUMP').default; export default { - ADD, - add: ADD, - CARD, - card: CARD, - EXISTS, - exists: EXISTS, - INFO, - info: INFO, - INSERT, - insert: INSERT, - LOADCHUNK, - loadChunk: LOADCHUNK, - MADD, - mAdd: MADD, - MEXISTS, - mExists: MEXISTS, - RESERVE, - reserve: RESERVE, - SCANDUMP, - scanDump: SCANDUMP -}; + ADD: ADD as ADD, + add: ADD as ADD, + CARD: CARD as CARD, + card: CARD as CARD, + EXISTS: EXISTS as EXISTS, + exists: EXISTS as EXISTS, + // INFO: INFO as INFO, + // info: INFO as INFO, + INSERT: INSERT as INSERT, + insert: INSERT as INSERT, + LOADCHUNK: LOADCHUNK as LOADCHUNK, + loadChunk: LOADCHUNK as LOADCHUNK, + MADD: MADD as MADD, + mAdd: MADD as MADD, + MEXISTS: MEXISTS as MEXISTS, + mExists: MEXISTS as MEXISTS, + RESERVE: RESERVE as RESERVE, + reserve: RESERVE as RESERVE, + SCANDUMP: SCANDUMP as SCANDUMP, + scanDump: SCANDUMP as SCANDUMP +} satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts index 95bb28e88b5..3b77d3b93d8 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts @@ -1,41 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INCRBY'; +import INCRBY from './INCRBY'; -describe('CMS INCRBY', () => { - describe('transformArguments', () => { - it('single item', () => { - assert.deepEqual( - transformArguments('key', { - item: 'item', - incrementBy: 1 - }), - ['CMS.INCRBY', 'key', 'item', '1'] - ); - }); +describe('CMS.INCRBY', () => { + describe('transformArguments', () => { + it('single item', () => { + assert.deepEqual( + INCRBY.transformArguments('key', { + item: 'item', + incrementBy: 1 + }), + ['CMS.INCRBY', 'key', 'item', '1'] + ); + }); - it('multiple items', () => { - assert.deepEqual( - transformArguments('key', [{ - item: 'a', - incrementBy: 1 - }, { - item: 'b', - incrementBy: 2 - }]), - ['CMS.INCRBY', 'key', 'a', '1', 'b', '2'] - ); - }); + it('multiple items', () => { + assert.deepEqual( + INCRBY.transformArguments('key', [{ + item: 'a', + incrementBy: 1 + }, { + item: 'b', + incrementBy: 2 + }]), + ['CMS.INCRBY', 'key', 'a', '1', 'b', '2'] + ); }); + }); + + testUtils.testWithClient('client.cms.incrBy', async client => { + const [, reply] = await Promise.all([ + client.cms.initByDim('key', 1000, 5), + client.cms.incrBy('key', { + item: 'item', + incrementBy: 1 + }) + ]); - testUtils.testWithClient('client.cms.incrBy', async client => { - await client.cms.initByDim('key', 1000, 5); - assert.deepEqual( - await client.cms.incrBy('key', { - item: 'item', - incrementBy: 1 - }), - [1] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [1]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/INCRBY.ts b/packages/bloom/lib/commands/count-min-sketch/INCRBY.ts index e27fb397cdf..1dfbabbaa49 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INCRBY.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INCRBY.ts @@ -1,29 +1,32 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -interface IncrByItem { - item: string; - incrementBy: number; +export interface BfIncrByItem { + item: RedisArgument; + incrementBy: number; } -export function transformArguments( - key: string, - items: IncrByItem | Array -): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + items: BfIncrByItem | Array + ) { const args = ['CMS.INCRBY', key]; if (Array.isArray(items)) { - for (const item of items) { - pushIncrByItem(args, item); - } + for (const item of items) { + pushIncrByItem(args, item); + } } else { - pushIncrByItem(args, items); + pushIncrByItem(args, items); } return args; -} + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; -function pushIncrByItem(args: Array, { item, incrementBy }: IncrByItem): void { - args.push(item, incrementBy.toString()); +function pushIncrByItem(args: Array, { item, incrementBy }: BfIncrByItem): void { + args.push(item, incrementBy.toString()); } - -export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts index 0db8a48447e..ff227cb5be0 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts @@ -1,25 +1,27 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INFO'; +import INFO from './INFO'; -describe('CMS INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['CMS.INFO', 'key'] - ); - }); +describe('CMS.INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + INFO.transformArguments('key'), + ['CMS.INFO', 'key'] + ); + }); - testUtils.testWithClient('client.cms.info', async client => { - await client.cms.initByDim('key', 1000, 5); + testUtils.testWithClient('client.cms.info', async client => { + const width = 1000, + depth = 5, + [, reply] = await Promise.all([ + client.cms.initByDim('key', width, depth), + client.cms.info('key') + ]); - assert.deepEqual( - await client.cms.info('key'), - { - width: 1000, - depth: 5, - count: 0 - } - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, { + width, + depth, + count: 0 + }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/INFO.ts b/packages/bloom/lib/commands/count-min-sketch/INFO.ts index 6dbfffcb0e0..e298efd16ad 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INFO.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INFO.ts @@ -1,30 +1,23 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { +export type BfInfoReply = TuplesToMapReply<[ + [BlobStringReply<'width'>, NumberReply], + [BlobStringReply<'depth'>, NumberReply], + [BlobStringReply<'count'>, NumberReply] +]>; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['CMS.INFO', key]; -} - -export type InfoRawReply = [ - _: string, - width: number, - _: string, - depth: number, - _: string, - count: number -]; - -export interface InfoReply { - width: number; - depth: number; - count: number; -} - -export function transformReply(reply: InfoRawReply): InfoReply { - return { - width: reply[1], - depth: reply[3], - count: reply[5] - }; -} + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + width: reply[1], + depth: reply[3], + count: reply[5] + }), + 3: undefined as unknown as () => BfInfoReply + } +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts index 2a9014b765a..0c9a712183b 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INITBYDIM'; +import INITBYDIM from './INITBYDIM'; -describe('CMS INITBYDIM', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 1000, 5), - ['CMS.INITBYDIM', 'key', '1000', '5'] - ); - }); +describe('CMS.INITBYDIM', () => { + it('transformArguments', () => { + assert.deepEqual( + INITBYDIM.transformArguments('key', 1000, 5), + ['CMS.INITBYDIM', 'key', '1000', '5'] + ); + }); - testUtils.testWithClient('client.cms.initByDim', async client => { - assert.equal( - await client.cms.initByDim('key', 1000, 5), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cms.initByDim', async client => { + assert.equal( + await client.cms.initByDim('key', 1000, 5), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.ts index 4ec6cedd9ea..60790d421e4 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, width: number, depth: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, width: number, depth: number) { return ['CMS.INITBYDIM', key, width.toString(), depth.toString()]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts index 004d3df14ef..592be4db6bf 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INITBYPROB'; +import INITBYPROB from './INITBYPROB'; -describe('CMS INITBYPROB', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0.001, 0.01), - ['CMS.INITBYPROB', 'key', '0.001', '0.01'] - ); - }); +describe('CMS.INITBYPROB', () => { + it('transformArguments', () => { + assert.deepEqual( + INITBYPROB.transformArguments('key', 0.001, 0.01), + ['CMS.INITBYPROB', 'key', '0.001', '0.01'] + ); + }); - testUtils.testWithClient('client.cms.initByProb', async client => { - assert.equal( - await client.cms.initByProb('key', 0.001, 0.01), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cms.initByProb', async client => { + assert.equal( + await client.cms.initByProb('key', 0.001, 0.01), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.ts index 7f0256515fb..7b21755f17d 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, error: number, probability: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, error: number, probability: number) { return ['CMS.INITBYPROB', key, error.toString(), probability.toString()]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts b/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts index cf234e5734f..f996f88648c 100644 --- a/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts @@ -1,36 +1,34 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './MERGE'; +import MERGE from './MERGE'; -describe('CMS MERGE', () => { - describe('transformArguments', () => { - it('without WEIGHTS', () => { - assert.deepEqual( - transformArguments('dest', ['src']), - ['CMS.MERGE', 'dest', '1', 'src'] - ); - }); +describe('CMS.MERGE', () => { + describe('transformArguments', () => { + it('without WEIGHTS', () => { + assert.deepEqual( + MERGE.transformArguments('destination', ['source']), + ['CMS.MERGE', 'destination', '1', 'source'] + ); + }); - it('with WEIGHTS', () => { - assert.deepEqual( - transformArguments('dest', [{ - name: 'src', - weight: 1 - }]), - ['CMS.MERGE', 'dest', '1', 'src', 'WEIGHTS', '1'] - ); - }); + it('with WEIGHTS', () => { + assert.deepEqual( + MERGE.transformArguments('destination', [{ + name: 'source', + weight: 1 + }]), + ['CMS.MERGE', 'destination', '1', 'source', 'WEIGHTS', '1'] + ); }); + }); - testUtils.testWithClient('client.cms.merge', async client => { - await Promise.all([ - client.cms.initByDim('src', 1000, 5), - client.cms.initByDim('dest', 1000, 5), - ]); + testUtils.testWithClient('client.cms.merge', async client => { + const [, , reply] = await Promise.all([ + client.cms.initByDim('source', 1000, 5), + client.cms.initByDim('destination', 1000, 5), + client.cms.merge('destination', ['source']) + ]); - assert.equal( - await client.cms.merge('dest', ['src']), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/MERGE.ts b/packages/bloom/lib/commands/count-min-sketch/MERGE.ts index 6cca4e797cd..2e63065d1cc 100644 --- a/packages/bloom/lib/commands/count-min-sketch/MERGE.ts +++ b/packages/bloom/lib/commands/count-min-sketch/MERGE.ts @@ -1,37 +1,37 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -interface Sketch { - name: string; - weight: number; +interface BfMergeSketch { + name: RedisArgument; + weight: number; } -type Sketches = Array | Array; +export type BfMergeSketches = Array | Array; -export function transformArguments(dest: string, src: Sketches): Array { - const args = [ - 'CMS.MERGE', - dest, - src.length.toString() - ]; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + source: BfMergeSketches + ) { + let args = ['CMS.MERGE', destination, source.length.toString()]; - if (isStringSketches(src)) { - args.push(...src); + if (isPlainSketches(source)) { + args = args.concat(source); } else { - for (const sketch of src) { - args.push(sketch.name); - } - - args.push('WEIGHTS'); - for (const sketch of src) { - args.push(sketch.weight.toString()); - } + const { length } = args; + args[length + source.length] = 'WEIGHTS'; + for (let i = 0; i < source.length; i++) { + args[length + i] = source[i].name; + args[length + source.length + i + 1] = source[i].weight.toString(); + } } return args; -} + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -function isStringSketches(src: Sketches): src is Array { - return typeof src[0] === 'string'; +function isPlainSketches(src: BfMergeSketches): src is Array { + return typeof src[0] === 'string' || src[0] instanceof Buffer; } - -export declare function transformReply(): 'OK'; diff --git a/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts b/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts index d391ab838be..f321c28a0e9 100644 --- a/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts @@ -1,22 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './QUERY'; +import QUERY from './QUERY'; -describe('CMS QUERY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CMS.QUERY', 'key', 'item'] - ); - }); +describe('CMS.QUERY', () => { + it('transformArguments', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'item'), + ['CMS.QUERY', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cms.query', async client => { - await client.cms.initByDim('key', 1000, 5); + testUtils.testWithClient('client.cms.query', async client => { + const [, reply] = await Promise.all([ + client.cms.initByDim('key', 1000, 5), + client.cms.query('key', 'item') + ]); - assert.deepEqual( - await client.cms.query('key', 'item'), - [0] - ); - - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [0]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/count-min-sketch/QUERY.ts b/packages/bloom/lib/commands/count-min-sketch/QUERY.ts index a34a9e9b9a0..5d2905300b1 100644 --- a/packages/bloom/lib/commands/count-min-sketch/QUERY.ts +++ b/packages/bloom/lib/commands/count-min-sketch/QUERY.ts @@ -1,15 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { ArrayReply, NumberReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - items: string | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { return pushVariadicArguments(['CMS.QUERY', key], items); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/count-min-sketch/index.ts b/packages/bloom/lib/commands/count-min-sketch/index.ts index 1d61734a8d0..3a2dfa40ac5 100644 --- a/packages/bloom/lib/commands/count-min-sketch/index.ts +++ b/packages/bloom/lib/commands/count-min-sketch/index.ts @@ -1,21 +1,29 @@ -import * as INCRBY from './INCRBY'; -import * as INFO from './INFO'; -import * as INITBYDIM from './INITBYDIM'; -import * as INITBYPROB from './INITBYPROB'; -import * as MERGE from './MERGE'; -import * as QUERY from './QUERY'; +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; +import INCRBY from './INCRBY'; +import INFO from './INFO'; +import INITBYDIM from './INITBYDIM'; +import INITBYPROB from './INITBYPROB'; +import MERGE from './MERGE'; +import QUERY from './QUERY'; + +type INCRBY = typeof import('./INCRBY').default; +type INFO = typeof import('./INFO').default; +type INITBYDIM = typeof import('./INITBYDIM').default; +type INITBYPROB = typeof import('./INITBYPROB').default; +type MERGE = typeof import('./MERGE').default; +type QUERY = typeof import('./QUERY').default; export default { - INCRBY, - incrBy: INCRBY, - INFO, - info: INFO, - INITBYDIM, - initByDim: INITBYDIM, - INITBYPROB, - initByProb: INITBYPROB, - MERGE, - merge: MERGE, - QUERY, - query: QUERY -}; + INCRBY: INCRBY as INCRBY, + incrBy: INCRBY as INCRBY, + INFO: INFO as INFO, + info: INFO as INFO, + INITBYDIM: INITBYDIM as INITBYDIM, + initByDim: INITBYDIM as INITBYDIM, + INITBYPROB: INITBYPROB as INITBYPROB, + initByProb: INITBYPROB as INITBYPROB, + MERGE: MERGE as MERGE, + merge: MERGE as MERGE, + QUERY: QUERY as QUERY, + query: QUERY as QUERY, +} satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/cuckoo/ADD.spec.ts b/packages/bloom/lib/commands/cuckoo/ADD.spec.ts index f2c029fad3d..d05c1c0e7f3 100644 --- a/packages/bloom/lib/commands/cuckoo/ADD.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/ADD.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments, transformReply } from './ADD'; +import ADD from './ADD'; -describe('CF ADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CF.ADD', 'key', 'item'] - ); - }); +describe('CF.ADD', () => { + it('transformArguments', () => { + assert.deepEqual( + ADD.transformArguments('key', 'item'), + ['CF.ADD', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cf.add', async client => { - assert.equal( - await client.cf.add('key', 'item'), - true - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.add', async client => { + assert.equal( + await client.cf.add('key', 'item'), + true + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/ADD.ts b/packages/bloom/lib/commands/cuckoo/ADD.ts index 8d16c0f2ed0..52e98a801d4 100644 --- a/packages/bloom/lib/commands/cuckoo/ADD.ts +++ b/packages/bloom/lib/commands/cuckoo/ADD.ts @@ -1,7 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['CF.ADD', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts b/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts index ddd9f922b13..1a291e7b308 100644 --- a/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts @@ -1,21 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './ADDNX'; +import ADDNX from './ADDNX'; -describe('CF ADDNX', () => { - describe('transformArguments', () => { - it('basic add', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CF.ADDNX', 'key', 'item'] - ); - }); - }); +describe('CF.ADDNX', () => { + it('transformArguments', () => { + assert.deepEqual( + ADDNX.transformArguments('key', 'item'), + ['CF.ADDNX', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cf.add', async client => { - assert.equal( - await client.cf.addNX('key', 'item'), - true - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.add', async client => { + assert.equal( + await client.cf.addNX('key', 'item'), + true + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/ADDNX.ts b/packages/bloom/lib/commands/cuckoo/ADDNX.ts index 789003a3a57..c739077ee46 100644 --- a/packages/bloom/lib/commands/cuckoo/ADDNX.ts +++ b/packages/bloom/lib/commands/cuckoo/ADDNX.ts @@ -1,7 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['CF.ADDNX', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts b/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts index 29f5b415935..e3b53cd35a5 100644 --- a/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './COUNT'; +import COUNT from './COUNT'; -describe('CF COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CF.COUNT', 'key', 'item'] - ); - }); +describe('CF.COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + COUNT.transformArguments('key', 'item'), + ['CF.COUNT', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cf.count', async client => { - assert.equal( - await client.cf.count('key', 'item'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.count', async client => { + assert.equal( + await client.cf.count('key', 'item'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/COUNT.ts b/packages/bloom/lib/commands/cuckoo/COUNT.ts index c9f3e28b38a..2284edff174 100644 --- a/packages/bloom/lib/commands/cuckoo/COUNT.ts +++ b/packages/bloom/lib/commands/cuckoo/COUNT.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['CF.COUNT', key, item]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/DEL.spec.ts b/packages/bloom/lib/commands/cuckoo/DEL.spec.ts index 03da65881c1..eddfe7298d3 100644 --- a/packages/bloom/lib/commands/cuckoo/DEL.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/DEL.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './DEL'; +import DEL from './DEL'; -describe('CF DEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CF.DEL', 'key', 'item'] - ); - }); +describe('CF.DEL', () => { + it('transformArguments', () => { + assert.deepEqual( + DEL.transformArguments('key', 'item'), + ['CF.DEL', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cf.del', async client => { - await client.cf.reserve('key', 4); + testUtils.testWithClient('client.cf.del', async client => { + const [, reply] = await Promise.all([ + client.cf.reserve('key', 4), + client.cf.del('key', 'item') + ]); - assert.equal( - await client.cf.del('key', 'item'), - false - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, false); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/DEL.ts b/packages/bloom/lib/commands/cuckoo/DEL.ts index 1c395a515a8..55cefb4a054 100644 --- a/packages/bloom/lib/commands/cuckoo/DEL.ts +++ b/packages/bloom/lib/commands/cuckoo/DEL.ts @@ -1,7 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['CF.DEL', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts b/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts index e281bde6d8a..08e3c522f4d 100644 --- a/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './EXISTS'; +import EXISTS from './EXISTS'; -describe('CF EXISTS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['CF.EXISTS', 'key', 'item'] - ); - }); +describe('CF.EXISTS', () => { + it('transformArguments', () => { + assert.deepEqual( + EXISTS.transformArguments('key', 'item'), + ['CF.EXISTS', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cf.exists', async client => { - assert.equal( - await client.cf.exists('key', 'item'), - false - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.exists', async client => { + assert.equal( + await client.cf.exists('key', 'item'), + false + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/EXISTS.ts b/packages/bloom/lib/commands/cuckoo/EXISTS.ts index b50a1e25a87..1cb6b4df8fa 100644 --- a/packages/bloom/lib/commands/cuckoo/EXISTS.ts +++ b/packages/bloom/lib/commands/cuckoo/EXISTS.ts @@ -1,9 +1,11 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, item: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, item: RedisArgument) { return ['CF.EXISTS', key, item]; -} - -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; + }, + transformReply: transformBooleanReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts index c2ac5de6fe0..1663ed0c7c8 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts @@ -1,27 +1,27 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INFO'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../../test-utils'; +// import { transformArguments } from './INFO'; -describe('CF INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('cuckoo'), - ['CF.INFO', 'cuckoo'] - ); - }); +// describe('CF INFO', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('cuckoo'), +// ['CF.INFO', 'cuckoo'] +// ); +// }); - testUtils.testWithClient('client.cf.info', async client => { - await client.cf.reserve('key', 4); +// testUtils.testWithClient('client.cf.info', async client => { +// await client.cf.reserve('key', 4); - const info = await client.cf.info('key'); - assert.equal(typeof info, 'object'); - assert.equal(typeof info.size, 'number'); - assert.equal(typeof info.numberOfBuckets, 'number'); - assert.equal(typeof info.numberOfFilters, 'number'); - assert.equal(typeof info.numberOfInsertedItems, 'number'); - assert.equal(typeof info.numberOfDeletedItems, 'number'); - assert.equal(typeof info.bucketSize, 'number'); - assert.equal(typeof info.expansionRate, 'number'); - assert.equal(typeof info.maxIteration, 'number'); - }, GLOBAL.SERVERS.OPEN); -}); +// const info = await client.cf.info('key'); +// assert.equal(typeof info, 'object'); +// assert.equal(typeof info.size, 'number'); +// assert.equal(typeof info.numberOfBuckets, 'number'); +// assert.equal(typeof info.numberOfFilters, 'number'); +// assert.equal(typeof info.numberOfInsertedItems, 'number'); +// assert.equal(typeof info.numberOfDeletedItems, 'number'); +// assert.equal(typeof info.bucketSize, 'number'); +// assert.equal(typeof info.expansionRate, 'number'); +// assert.equal(typeof info.maxIteration, 'number'); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/bloom/lib/commands/cuckoo/INFO.ts b/packages/bloom/lib/commands/cuckoo/INFO.ts index 04d6954e37a..be77430ae95 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.ts @@ -1,50 +1,50 @@ -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(key: string): Array { - return ['CF.INFO', key]; -} +// export function transformArguments(key: string): Array { +// return ['CF.INFO', key]; +// } -export type InfoRawReply = [ - _: string, - size: number, - _: string, - numberOfBuckets: number, - _: string, - numberOfFilters: number, - _: string, - numberOfInsertedItems: number, - _: string, - numberOfDeletedItems: number, - _: string, - bucketSize: number, - _: string, - expansionRate: number, - _: string, - maxIteration: number -]; +// export type InfoRawReply = [ +// _: string, +// size: number, +// _: string, +// numberOfBuckets: number, +// _: string, +// numberOfFilters: number, +// _: string, +// numberOfInsertedItems: number, +// _: string, +// numberOfDeletedItems: number, +// _: string, +// bucketSize: number, +// _: string, +// expansionRate: number, +// _: string, +// maxIteration: number +// ]; -export interface InfoReply { - size: number; - numberOfBuckets: number; - numberOfFilters: number; - numberOfInsertedItems: number; - numberOfDeletedItems: number; - bucketSize: number; - expansionRate: number; - maxIteration: number; -} +// export interface InfoReply { +// size: number; +// numberOfBuckets: number; +// numberOfFilters: number; +// numberOfInsertedItems: number; +// numberOfDeletedItems: number; +// bucketSize: number; +// expansionRate: number; +// maxIteration: number; +// } -export function transformReply(reply: InfoRawReply): InfoReply { - return { - size: reply[1], - numberOfBuckets: reply[3], - numberOfFilters: reply[5], - numberOfInsertedItems: reply[7], - numberOfDeletedItems: reply[9], - bucketSize: reply[11], - expansionRate: reply[13], - maxIteration: reply[15] - }; -} +// export function transformReply(reply: InfoRawReply): InfoReply { +// return { +// size: reply[1], +// numberOfBuckets: reply[3], +// numberOfFilters: reply[5], +// numberOfInsertedItems: reply[7], +// numberOfDeletedItems: reply[9], +// bucketSize: reply[11], +// expansionRate: reply[13], +// maxIteration: reply[15] +// }; +// } diff --git a/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts b/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts index 9b56b86a6b7..40571f34cb4 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INSERT'; +import INSERT from './INSERT'; -describe('CF INSERT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item', { - CAPACITY: 100, - NOCREATE: true - }), - ['CF.INSERT', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item'] - ); - }); +describe('CF.INSERT', () => { + it('transformArguments', () => { + assert.deepEqual( + INSERT.transformArguments('key', 'item', { + CAPACITY: 100, + NOCREATE: true + }), + ['CF.INSERT', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item'] + ); + }); - testUtils.testWithClient('client.cf.insert', async client => { - assert.deepEqual( - await client.cf.insert('key', 'item'), - [true] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.insert', async client => { + assert.deepEqual( + await client.cf.insert('key', 'item'), + [true] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/INSERT.ts b/packages/bloom/lib/commands/cuckoo/INSERT.ts index bcfd4f13a88..d6df64eea1a 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERT.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERT.ts @@ -1,18 +1,34 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { InsertOptions, pushInsertOptions } from "."; +import { Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments, transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; +export interface CfInsertOptions { + CAPACITY?: number; + NOCREATE?: boolean; +} + +export function transofrmCfInsertArguments( + command: RedisArgument, + key: RedisArgument, + items: RedisVariadicArgument, + options?: CfInsertOptions +) { + const args = [command, key]; + + if (options?.CAPACITY !== undefined) { + args.push('CAPACITY', options.CAPACITY.toString()); + } + + if (options?.NOCREATE) { + args.push('NOCREATE'); + } -export function transformArguments( - key: string, - items: string | Array, - options?: InsertOptions -): RedisCommandArguments { - return pushInsertOptions( - ['CF.INSERT', key], - items, - options - ); + args.push('ITEMS'); + return pushVariadicArguments(args, items); } -export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transofrmCfInsertArguments.bind(undefined, 'CF.INSERT'), + transformReply: transformBooleanArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts b/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts index 7b1d974e5a6..bca4f90546c 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INSERTNX'; +import INSERTNX from './INSERTNX'; -describe('CF INSERTNX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item', { - CAPACITY: 100, - NOCREATE: true - }), - ['CF.INSERTNX', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item'] - ); - }); +describe('CF.INSERTNX', () => { + it('transformArguments', () => { + assert.deepEqual( + INSERTNX.transformArguments('key', 'item', { + CAPACITY: 100, + NOCREATE: true + }), + ['CF.INSERTNX', 'key', 'CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item'] + ); + }); - testUtils.testWithClient('client.cf.insertnx', async client => { - assert.deepEqual( - await client.cf.insertNX('key', 'item'), - [true] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.insertnx', async client => { + assert.deepEqual( + await client.cf.insertNX('key', 'item'), + [true] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/INSERTNX.ts b/packages/bloom/lib/commands/cuckoo/INSERTNX.ts index 17009e35a42..5cd56e794f9 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERTNX.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERTNX.ts @@ -1,18 +1,9 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { InsertOptions, pushInsertOptions } from "."; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import INSERT, { transofrmCfInsertArguments } from './INSERT'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: string, - items: string | Array, - options?: InsertOptions -): RedisCommandArguments { - return pushInsertOptions( - ['CF.INSERTNX', key], - items, - options - ); -} - -export { transformBooleanArrayReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; +export default { + FIRST_KEY_INDEX: INSERT.FIRST_KEY_INDEX, + IS_READ_ONLY: INSERT.IS_READ_ONLY, + transformArguments: transofrmCfInsertArguments.bind(undefined, 'CF.INSERTNX'), + transformReply: INSERT.transformReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts index ca3d6f2f8f7..a2292d78bd3 100644 --- a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts @@ -1,31 +1,36 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './LOADCHUNK'; +import LOADCHUNK from './LOADCHUNK'; +import { RESP_TYPES } from '@redis/client'; -describe('CF LOADCHUNK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('item', 0, ''), - ['CF.LOADCHUNK', 'item', '0', ''] - ); - }); +describe('CF.LOADCHUNK', () => { + it('transformArguments', () => { + assert.deepEqual( + LOADCHUNK.transformArguments('item', 0, ''), + ['CF.LOADCHUNK', 'item', '0', ''] + ); + }); - testUtils.testWithClient('client.cf.loadChunk', async client => { - const [,, { iterator, chunk }] = await Promise.all([ - client.cf.reserve('source', 4), - client.cf.add('source', 'item'), - client.cf.scanDump( - client.commandOptions({ returnBuffers: true }), - 'source', - 0 - ) - ]); + testUtils.testWithClient('client.cf.loadChunk', async client => { + const [, , { iterator, chunk }] = await Promise.all([ + client.cf.reserve('source', 4), + client.cf.add('source', 'item'), + client.cf.scanDump('source', 0) + ]); - assert.ok(Buffer.isBuffer(chunk)); - - assert.equal( - await client.cf.loadChunk('destination', iterator, chunk), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.cf.loadChunk('destination', iterator, chunk), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + ...GLOBAL.SERVERS.OPEN.clientOptions, + commandOptions: { + typeMapping: { + [RESP_TYPES.BLOB_STRING]: Buffer + } + } + } + }); }); diff --git a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.ts b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.ts index 6d960c014e2..08cb749b595 100644 --- a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.ts +++ b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.ts @@ -1,13 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: string, - iterator: number, - chunk: RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, iterator: number, chunk: RedisArgument) { return ['CF.LOADCHUNK', key, iterator.toString(), chunk]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts b/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts index 3145a222c5e..ee4d56af488 100644 --- a/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts @@ -1,48 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './RESERVE'; +import RESERVE from './RESERVE'; -describe('CF RESERVE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 4), - ['CF.RESERVE', 'key', '4'] - ); - }); +describe('CF.RESERVE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 4), + ['CF.RESERVE', 'key', '4'] + ); + }); - it('with EXPANSION', () => { - assert.deepEqual( - transformArguments('key', 4, { - EXPANSION: 1 - }), - ['CF.RESERVE', 'key', '4', 'EXPANSION', '1'] - ); - }); + it('with EXPANSION', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 4, { + EXPANSION: 1 + }), + ['CF.RESERVE', 'key', '4', 'EXPANSION', '1'] + ); + }); - it('with BUCKETSIZE', () => { - assert.deepEqual( - transformArguments('key', 4, { - BUCKETSIZE: 2 - }), - ['CF.RESERVE', 'key', '4', 'BUCKETSIZE', '2'] - ); - }); + it('with BUCKETSIZE', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 4, { + BUCKETSIZE: 2 + }), + ['CF.RESERVE', 'key', '4', 'BUCKETSIZE', '2'] + ); + }); - it('with MAXITERATIONS', () => { - assert.deepEqual( - transformArguments('key', 4, { - MAXITERATIONS: 1 - }), - ['CF.RESERVE', 'key', '4', 'MAXITERATIONS', '1'] - ); - }); + it('with MAXITERATIONS', () => { + assert.deepEqual( + RESERVE.transformArguments('key', 4, { + MAXITERATIONS: 1 + }), + ['CF.RESERVE', 'key', '4', 'MAXITERATIONS', '1'] + ); }); + }); - testUtils.testWithClient('client.cf.reserve', async client => { - assert.equal( - await client.cf.reserve('key', 4), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.cf.reserve', async client => { + assert.equal( + await client.cf.reserve('key', 4), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/RESERVE.ts b/packages/bloom/lib/commands/cuckoo/RESERVE.ts index 114c1fdf441..bc80daa0087 100644 --- a/packages/bloom/lib/commands/cuckoo/RESERVE.ts +++ b/packages/bloom/lib/commands/cuckoo/RESERVE.ts @@ -1,31 +1,34 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -interface ReserveOptions { - BUCKETSIZE?: number; - MAXITERATIONS?: number; - EXPANSION?: number; +export interface CfReserveOptions { + BUCKETSIZE?: number; + MAXITERATIONS?: number; + EXPANSION?: number; } -export function transformArguments( - key: string, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, capacity: number, - options?: ReserveOptions -): Array { + options?: CfReserveOptions + ) { const args = ['CF.RESERVE', key, capacity.toString()]; - if (options?.BUCKETSIZE) { - args.push('BUCKETSIZE', options.BUCKETSIZE.toString()); + if (options?.BUCKETSIZE !== undefined) { + args.push('BUCKETSIZE', options.BUCKETSIZE.toString()); } - if (options?.MAXITERATIONS) { - args.push('MAXITERATIONS', options.MAXITERATIONS.toString()); + if (options?.MAXITERATIONS !== undefined) { + args.push('MAXITERATIONS', options.MAXITERATIONS.toString()); } - if (options?.EXPANSION) { - args.push('EXPANSION', options.EXPANSION.toString()); + if (options?.EXPANSION !== undefined) { + args.push('EXPANSION', options.EXPANSION.toString()); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts b/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts index ec269c62aa5..e84142b4ae6 100644 --- a/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts @@ -1,23 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './SCANDUMP'; +import SCANDUMP from './SCANDUMP'; -describe('CF SCANDUMP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0), - ['CF.SCANDUMP', 'key', '0'] - ); - }); +describe('CF.SCANDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + SCANDUMP.transformArguments('key', 0), + ['CF.SCANDUMP', 'key', '0'] + ); + }); + + testUtils.testWithClient('client.cf.scanDump', async client => { + const [, reply] = await Promise.all([ + client.cf.reserve('key', 4), + client.cf.scanDump('key', 0) + ]); - testUtils.testWithClient('client.cf.scanDump', async client => { - await client.cf.reserve('key', 4); - assert.deepEqual( - await client.cf.scanDump('key', 0), - { - iterator: 0, - chunk: null - } - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, { + iterator: 0, + chunk: null + }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts b/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts index 91476b49a7a..af33315750f 100644 --- a/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts +++ b/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts @@ -1,22 +1,15 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, iterator: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, iterator: number) { return ['CF.SCANDUMP', key, iterator.toString()]; -} - -type ScanDumpRawReply = [ - iterator: number, - chunk: string | null -]; - -interface ScanDumpReply { - iterator: number; - chunk: string | null; -} - -export function transformReply([iterator, chunk]: ScanDumpRawReply): ScanDumpReply { + }, + transformReply(reply: TuplesReply<[NumberReply, BlobStringReply | NullReply]>) { return { - iterator, - chunk + iterator: reply[0], + chunk: reply[1] }; -} + } +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/index.spec.ts b/packages/bloom/lib/commands/cuckoo/index.spec.ts deleted file mode 100644 index 94f3a0ae281..00000000000 --- a/packages/bloom/lib/commands/cuckoo/index.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { strict as assert } from 'assert'; -import { pushInsertOptions } from '.'; - -describe('pushInsertOptions', () => { - describe('single item', () => { - it('single item', () => { - assert.deepEqual( - pushInsertOptions([], 'item'), - ['ITEMS', 'item'] - ); - }); - - it('multiple items', () => { - assert.deepEqual( - pushInsertOptions([], ['1', '2']), - ['ITEMS', '1', '2'] - ); - }); - }); - - it('with CAPACITY', () => { - assert.deepEqual( - pushInsertOptions([], 'item', { - CAPACITY: 100 - }), - ['CAPACITY', '100', 'ITEMS', 'item'] - ); - }); - - it('with NOCREATE', () => { - assert.deepEqual( - pushInsertOptions([], 'item', { - NOCREATE: true - }), - ['NOCREATE', 'ITEMS', 'item'] - ); - }); - - it('with CAPACITY and NOCREATE', () => { - assert.deepEqual( - pushInsertOptions([], 'item', { - CAPACITY: 100, - NOCREATE: true - }), - ['CAPACITY', '100', 'NOCREATE', 'ITEMS', 'item'] - ); - }); -}); diff --git a/packages/bloom/lib/commands/cuckoo/index.ts b/packages/bloom/lib/commands/cuckoo/index.ts index c34bdde503d..2609ea1651d 100644 --- a/packages/bloom/lib/commands/cuckoo/index.ts +++ b/packages/bloom/lib/commands/cuckoo/index.ts @@ -1,62 +1,48 @@ +import ADD from './ADD'; +import ADDNX from './ADDNX'; +import COUNT from './COUNT'; +import DEL from './DEL'; +import EXISTS from './EXISTS'; +// import INFO from './INFO'; +import INSERT from './INSERT'; +import INSERTNX from './INSERTNX'; +import LOADCHUNK from './LOADCHUNK'; +import RESERVE from './RESERVE'; +import SCANDUMP from './SCANDUMP'; -import * as ADD from './ADD'; -import * as ADDNX from './ADDNX'; -import * as COUNT from './COUNT'; -import * as DEL from './DEL'; -import * as EXISTS from './EXISTS'; -import * as INFO from './INFO'; -import * as INSERT from './INSERT'; -import * as INSERTNX from './INSERTNX'; -import * as LOADCHUNK from './LOADCHUNK'; -import * as RESERVE from './RESERVE'; -import * as SCANDUMP from './SCANDUMP'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +type ADD = typeof import('./ADD').default; +type ADDNX = typeof import('./ADDNX').default; +type COUNT = typeof import('./COUNT').default; +type DEL = typeof import('./DEL').default; +type EXISTS = typeof import('./EXISTS').default; +// type INFO = typeof import('./INFO').default; +type INSERT = typeof import('./INSERT').default; +type INSERTNX = typeof import('./INSERTNX').default; +type LOADCHUNK = typeof import('./LOADCHUNK').default; +type RESERVE = typeof import('./RESERVE').default; +type SCANDUMP = typeof import('./SCANDUMP').default; export default { - ADD, - add: ADD, - ADDNX, - addNX: ADDNX, - COUNT, - count: COUNT, - DEL, - del: DEL, - EXISTS, - exists: EXISTS, - INFO, - info: INFO, - INSERT, - insert: INSERT, - INSERTNX, - insertNX: INSERTNX, - LOADCHUNK, - loadChunk: LOADCHUNK, - RESERVE, - reserve: RESERVE, - SCANDUMP, - scanDump: SCANDUMP + ADD: ADD as ADD, + add: ADD as ADD, + ADDNX: ADDNX as ADDNX, + addNX: ADDNX as ADDNX, + COUNT: COUNT as COUNT, + count: COUNT as COUNT, + DEL: DEL as DEL, + del: DEL as DEL, + EXISTS: EXISTS as EXISTS, + exists: EXISTS as EXISTS, + // INFO: INFO as INFO, + // info: INFO as INFO, + INSERT: INSERT as INSERT, + insert: INSERT as INSERT, + INSERTNX: INSERTNX as INSERTNX, + insertNX: INSERTNX as INSERTNX, + LOADCHUNK: LOADCHUNK as LOADCHUNK, + loadChunk: LOADCHUNK as LOADCHUNK, + RESERVE: RESERVE as RESERVE, + reserve: RESERVE as RESERVE, + SCANDUMP: SCANDUMP as SCANDUMP, + scanDump: SCANDUMP as SCANDUMP }; - -export interface InsertOptions { - CAPACITY?: number; - NOCREATE?: true; -} - -export function pushInsertOptions( - args: RedisCommandArguments, - items: string | Array, - options?: InsertOptions -): RedisCommandArguments { - if (options?.CAPACITY) { - args.push('CAPACITY'); - args.push(options.CAPACITY.toString()); - } - - if (options?.NOCREATE) { - args.push('NOCREATE'); - } - - args.push('ITEMS'); - return pushVariadicArguments(args, items); -} diff --git a/packages/bloom/lib/commands/index.ts b/packages/bloom/lib/commands/index.ts index cea55b2a7c0..f1a1afd6923 100644 --- a/packages/bloom/lib/commands/index.ts +++ b/packages/bloom/lib/commands/index.ts @@ -1,3 +1,4 @@ +import { RedisModules } from '@redis/client'; import bf from './bloom'; import cms from './count-min-sketch'; import cf from './cuckoo'; @@ -5,9 +6,9 @@ import tDigest from './t-digest'; import topK from './top-k'; export default { - bf, - cms, - cf, - tDigest, - topK -}; + bf, + cms, + cf, + tDigest, + topK +} satisfies RedisModules; diff --git a/packages/bloom/lib/commands/t-digest/ADD.spec.ts b/packages/bloom/lib/commands/t-digest/ADD.spec.ts index 3e1dbff7f27..e77d67cba2c 100644 --- a/packages/bloom/lib/commands/t-digest/ADD.spec.ts +++ b/packages/bloom/lib/commands/t-digest/ADD.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './ADD'; +import ADD from './ADD'; describe('TDIGEST.ADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.ADD', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ADD.transformArguments('key', [1, 2]), + ['TDIGEST.ADD', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.add', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.add('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.add', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.add('key', [1]) + ]); - assert.equal(reply, 'OK'); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/ADD.ts b/packages/bloom/lib/commands/t-digest/ADD.ts index 941e8531003..e7c6d7c4429 100644 --- a/packages/bloom/lib/commands/t-digest/ADD.ts +++ b/packages/bloom/lib/commands/t-digest/ADD.ts @@ -1,17 +1,16 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - values: Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, values: Array) { const args = ['TDIGEST.ADD', key]; - for (const item of values) { - args.push(item.toString()); + + for (const value of values) { + args.push(value.toString()); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts index 083f09d22af..d6e31f59b4e 100644 --- a/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './BYRANK'; +import BYRANK from './BYRANK'; describe('TDIGEST.BYRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.BYRANK', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BYRANK.transformArguments('key', [1, 2]), + ['TDIGEST.BYRANK', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.byRank', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.byRank('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.byRank', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.byRank('key', [1]) + ]); - assert.deepEqual(reply, [NaN]); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.ts b/packages/bloom/lib/commands/t-digest/BYRANK.ts index 5684385b4d3..88e0cb6c7c8 100644 --- a/packages/bloom/lib/commands/t-digest/BYRANK.ts +++ b/packages/bloom/lib/commands/t-digest/BYRANK.ts @@ -1,19 +1,24 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; +export function transformByRankArguments( + command: RedisArgument, + key: RedisArgument, + ranks: Array +) { + const args = [command, key]; -export const IS_READ_ONLY = true; + for (const rank of ranks) { + args.push(rank.toString()); + } -export function transformArguments( - key: RedisCommandArgument, - ranks: Array -): RedisCommandArguments { - const args = ['TDIGEST.BYRANK', key]; - for (const rank of ranks) { - args.push(rank.toString()); - } - - return args; + return args; } -export { transformDoublesReply as transformReply } from '.'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: transformByRankArguments.bind(undefined, 'TDIGEST.BYRANK'), + transformReply: transformArrayDoubleReply +} as const satisfies Command; + diff --git a/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts index c094f36e71d..7549ea870c2 100644 --- a/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './BYREVRANK'; +import BYREVRANK from './BYREVRANK'; describe('TDIGEST.BYREVRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.BYREVRANK', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + BYREVRANK.transformArguments('key', [1, 2]), + ['TDIGEST.BYREVRANK', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.byRevRank', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.byRevRank('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.byRevRank', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.byRevRank('key', [1]) + ]); - assert.deepEqual(reply, [NaN]); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/BYREVRANK.ts b/packages/bloom/lib/commands/t-digest/BYREVRANK.ts index 3dcf3a973c4..9f62b42d812 100644 --- a/packages/bloom/lib/commands/t-digest/BYREVRANK.ts +++ b/packages/bloom/lib/commands/t-digest/BYREVRANK.ts @@ -1,19 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - ranks: Array -): RedisCommandArguments { - const args = ['TDIGEST.BYREVRANK', key]; - for (const rank of ranks) { - args.push(rank.toString()); - } - - return args; -} - -export { transformDoublesReply as transformReply } from '.'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import BYRANK, { transformByRankArguments } from './BYRANK'; + +export default { + FIRST_KEY_INDEX: BYRANK.FIRST_KEY_INDEX, + IS_READ_ONLY: BYRANK.IS_READ_ONLY, + transformArguments: transformByRankArguments.bind(undefined, 'TDIGEST.BYREVRANK'), + transformReply: BYRANK.transformReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/CDF.spec.ts b/packages/bloom/lib/commands/t-digest/CDF.spec.ts index 36d3564f62c..7ba56ccda6b 100644 --- a/packages/bloom/lib/commands/t-digest/CDF.spec.ts +++ b/packages/bloom/lib/commands/t-digest/CDF.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './CDF'; +import CDF from './CDF'; describe('TDIGEST.CDF', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.CDF', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CDF.transformArguments('key', [1, 2]), + ['TDIGEST.CDF', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.cdf', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.cdf('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.cdf', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.cdf('key', [1]) + ]); - assert.deepEqual(reply, [NaN]); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/CDF.ts b/packages/bloom/lib/commands/t-digest/CDF.ts index fe7ece59d76..ccc6d2c2b46 100644 --- a/packages/bloom/lib/commands/t-digest/CDF.ts +++ b/packages/bloom/lib/commands/t-digest/CDF.ts @@ -1,19 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - values: Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, values: Array) { const args = ['TDIGEST.CDF', key]; + for (const item of values) { - args.push(item.toString()); + args.push(item.toString()); } return args; -} - -export { transformDoublesReply as transformReply } from '.'; + }, + transformReply: transformArrayDoubleReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/CREATE.spec.ts b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts index 4d329cc81ae..f731241ab38 100644 --- a/packages/bloom/lib/commands/t-digest/CREATE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './CREATE'; +import CREATE from './CREATE'; describe('TDIGEST.CREATE', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key'), - ['TDIGEST.CREATE', 'key'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + CREATE.transformArguments('key'), + ['TDIGEST.CREATE', 'key'] + ); + }); - it('with COMPRESSION', () => { - assert.deepEqual( - transformArguments('key', { - COMPRESSION: 100 - }), - ['TDIGEST.CREATE', 'key', 'COMPRESSION', '100'] - ); - }); + it('with COMPRESSION', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + COMPRESSION: 100 + }), + ['TDIGEST.CREATE', 'key', 'COMPRESSION', '100'] + ); }); + }); - testUtils.testWithClient('client.tDigest.create', async client => { - assert.equal( - await client.tDigest.create('key'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.tDigest.create', async client => { + assert.equal( + await client.tDigest.create('key'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/CREATE.ts b/packages/bloom/lib/commands/t-digest/CREATE.ts index 1935d2973dc..8b832487daa 100644 --- a/packages/bloom/lib/commands/t-digest/CREATE.ts +++ b/packages/bloom/lib/commands/t-digest/CREATE.ts @@ -1,16 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { CompressionOption, pushCompressionArgument } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, - options?: CompressionOption -): RedisCommandArguments { - return pushCompressionArgument( - ['TDIGEST.CREATE', key], - options - ); +export interface TDigestCreateOptions { + COMPRESSION?: number; } -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, options?: TDigestCreateOptions) { + const args = ['TDIGEST.CREATE', key]; + + if (options?.COMPRESSION !== undefined) { + args.push('COMPRESSION', options.COMPRESSION.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/INFO.spec.ts b/packages/bloom/lib/commands/t-digest/INFO.spec.ts index 992fda6ea05..b3aa1281cda 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.spec.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.spec.ts @@ -1,25 +1,25 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INFO'; +// import { strict as assert } from 'assert'; +// import testUtils, { GLOBAL } from '../../test-utils'; +// import { transformArguments } from './INFO'; -describe('TDIGEST.INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TDIGEST.INFO', 'key'] - ); - }); +// describe('TDIGEST.INFO', () => { +// it('transformArguments', () => { +// assert.deepEqual( +// transformArguments('key'), +// ['TDIGEST.INFO', 'key'] +// ); +// }); - testUtils.testWithClient('client.tDigest.info', async client => { - await client.tDigest.create('key'); +// testUtils.testWithClient('client.tDigest.info', async client => { +// await client.tDigest.create('key'); - const info = await client.tDigest.info('key'); - assert(typeof info.capacity, 'number'); - assert(typeof info.mergedNodes, 'number'); - assert(typeof info.unmergedNodes, 'number'); - assert(typeof info.mergedWeight, 'number'); - assert(typeof info.unmergedWeight, 'number'); - assert(typeof info.totalCompression, 'number'); - assert(typeof info.totalCompression, 'number'); - }, GLOBAL.SERVERS.OPEN); -}); +// const info = await client.tDigest.info('key'); +// assert(typeof info.capacity, 'number'); +// assert(typeof info.mergedNodes, 'number'); +// assert(typeof info.unmergedNodes, 'number'); +// assert(typeof info.mergedWeight, 'number'); +// assert(typeof info.unmergedWeight, 'number'); +// assert(typeof info.totalCompression, 'number'); +// assert(typeof info.totalCompression, 'number'); +// }, GLOBAL.SERVERS.OPEN); +// }); diff --git a/packages/bloom/lib/commands/t-digest/INFO.ts b/packages/bloom/lib/commands/t-digest/INFO.ts index 44d2083524f..7830f71f9dd 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.ts @@ -1,51 +1,51 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +// import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return [ - 'TDIGEST.INFO', - key - ]; -} +// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +// return [ +// 'TDIGEST.INFO', +// key +// ]; +// } -type InfoRawReply = [ - 'Compression', - number, - 'Capacity', - number, - 'Merged nodes', - number, - 'Unmerged nodes', - number, - 'Merged weight', - string, - 'Unmerged weight', - string, - 'Total compressions', - number -]; +// type InfoRawReply = [ +// 'Compression', +// number, +// 'Capacity', +// number, +// 'Merged nodes', +// number, +// 'Unmerged nodes', +// number, +// 'Merged weight', +// string, +// 'Unmerged weight', +// string, +// 'Total compressions', +// number +// ]; -interface InfoReply { - comperssion: number; - capacity: number; - mergedNodes: number; - unmergedNodes: number; - mergedWeight: number; - unmergedWeight: number; - totalCompression: number; -} +// interface InfoReply { +// comperssion: number; +// capacity: number; +// mergedNodes: number; +// unmergedNodes: number; +// mergedWeight: number; +// unmergedWeight: number; +// totalCompression: number; +// } -export function transformReply(reply: InfoRawReply): InfoReply { - return { - comperssion: reply[1], - capacity: reply[3], - mergedNodes: reply[5], - unmergedNodes: reply[7], - mergedWeight: Number(reply[9]), - unmergedWeight: Number(reply[11]), - totalCompression: reply[13] - }; -} \ No newline at end of file +// export function transformReply(reply: InfoRawReply): InfoReply { +// return { +// comperssion: reply[1], +// capacity: reply[3], +// mergedNodes: reply[5], +// unmergedNodes: reply[7], +// mergedWeight: Number(reply[9]), +// unmergedWeight: Number(reply[11]), +// totalCompression: reply[13] +// }; +// } \ No newline at end of file diff --git a/packages/bloom/lib/commands/t-digest/MAX.spec.ts b/packages/bloom/lib/commands/t-digest/MAX.spec.ts index bf850cbfd83..cd6fc6517db 100644 --- a/packages/bloom/lib/commands/t-digest/MAX.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MAX.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments, transformReply } from './MAX'; +import MAX from './MAX'; describe('TDIGEST.MAX', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TDIGEST.MAX', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MAX.transformArguments('key'), + ['TDIGEST.MAX', 'key'] + ); + }); - testUtils.testWithClient('client.tDigest.max', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.max('key') - ]); + testUtils.testWithClient('client.tDigest.max', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.max('key') + ]); - assert.deepEqual(reply, NaN); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, NaN); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/MAX.ts b/packages/bloom/lib/commands/t-digest/MAX.ts index 90c42ec6067..ef778f832a6 100644 --- a/packages/bloom/lib/commands/t-digest/MAX.ts +++ b/packages/bloom/lib/commands/t-digest/MAX.ts @@ -1,14 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return [ - 'TDIGEST.MAX', - key - ]; -} - -export { transformDoubleReply as transformReply } from '.'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['TDIGEST.MAX', key]; + }, + transformReply: transformDoubleReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/MERGE.spec.ts b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts index 1205cdd9216..a20bf4626d9 100644 --- a/packages/bloom/lib/commands/t-digest/MERGE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts @@ -1,50 +1,50 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments, transformReply } from './MERGE'; +import MERGE from './MERGE'; describe('TDIGEST.MERGE', () => { - describe('transformArguments', () => { - describe('srcKeys', () => { - it('string', () => { - assert.deepEqual( - transformArguments('dest', 'src'), - ['TDIGEST.MERGE', 'dest', '1', 'src'] - ); - }); + describe('transformArguments', () => { + describe('source', () => { + it('string', () => { + assert.deepEqual( + MERGE.transformArguments('destination', 'source'), + ['TDIGEST.MERGE', 'destination', '1', 'source'] + ); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('dest', ['1', '2']), - ['TDIGEST.MERGE', 'dest', '2', '1', '2'] - ); - }); - }); + it('Array', () => { + assert.deepEqual( + MERGE.transformArguments('destination', ['1', '2']), + ['TDIGEST.MERGE', 'destination', '2', '1', '2'] + ); + }); + }); - it('with COMPRESSION', () => { - assert.deepEqual( - transformArguments('dest', 'src', { - COMPRESSION: 100 - }), - ['TDIGEST.MERGE', 'dest', '1', 'src', 'COMPRESSION', '100'] - ); - }); + it('with COMPRESSION', () => { + assert.deepEqual( + MERGE.transformArguments('destination', 'source', { + COMPRESSION: 100 + }), + ['TDIGEST.MERGE', 'destination', '1', 'source', 'COMPRESSION', '100'] + ); + }); - it('with OVERRIDE', () => { - assert.deepEqual( - transformArguments('dest', 'src', { - OVERRIDE: true - }), - ['TDIGEST.MERGE', 'dest', '1', 'src', 'OVERRIDE'] - ); - }); + it('with OVERRIDE', () => { + assert.deepEqual( + MERGE.transformArguments('destination', 'source', { + OVERRIDE: true + }), + ['TDIGEST.MERGE', 'destination', '1', 'source', 'OVERRIDE'] + ); }); + }); - testUtils.testWithClient('client.tDigest.merge', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('src'), - client.tDigest.merge('dest', 'src') - ]); + testUtils.testWithClient('client.tDigest.merge', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('source'), + client.tDigest.merge('destination', 'source') + ]); - assert.equal(reply, 'OK'); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/MERGE.ts b/packages/bloom/lib/commands/t-digest/MERGE.ts index 1aebe6fa47b..e9cd99aabf9 100644 --- a/packages/bloom/lib/commands/t-digest/MERGE.ts +++ b/packages/bloom/lib/commands/t-digest/MERGE.ts @@ -1,30 +1,30 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { CompressionOption, pushCompressionArgument } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -interface MergeOptions extends CompressionOption { - OVERRIDE?: boolean; +export interface TDigestMergeOptions { + COMPRESSION?: number; + OVERRIDE?: boolean; } -export function transformArguments( - destKey: RedisCommandArgument, - srcKeys: RedisCommandArgument | Array, - options?: MergeOptions -): RedisCommandArguments { - const args = pushVariadicArgument( - ['TDIGEST.MERGE', destKey], - srcKeys - ); +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + source: RedisVariadicArgument, + options?: TDigestMergeOptions + ) { + const args = pushVariadicArgument(['TDIGEST.MERGE', destination], source); - pushCompressionArgument(args, options); + if (options?.COMPRESSION !== undefined) { + args.push('COMPRESSION', options.COMPRESSION.toString()); + } if (options?.OVERRIDE) { - args.push('OVERRIDE'); + args.push('OVERRIDE'); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/MIN.spec.ts b/packages/bloom/lib/commands/t-digest/MIN.spec.ts index d48deaca7fb..7fac680558e 100644 --- a/packages/bloom/lib/commands/t-digest/MIN.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MIN.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments, transformReply } from './MIN'; +import MIN from './MIN'; describe('TDIGEST.MIN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TDIGEST.MIN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MIN.transformArguments('key'), + ['TDIGEST.MIN', 'key'] + ); + }); - testUtils.testWithClient('client.tDigest.min', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.min('key') - ]); + testUtils.testWithClient('client.tDigest.min', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.min('key') + ]); - assert.equal(reply, NaN); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, NaN); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/MIN.ts b/packages/bloom/lib/commands/t-digest/MIN.ts index d8be8722b60..914998a1ec4 100644 --- a/packages/bloom/lib/commands/t-digest/MIN.ts +++ b/packages/bloom/lib/commands/t-digest/MIN.ts @@ -1,14 +1,11 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { - return [ - 'TDIGEST.MIN', - key - ]; -} - -export { transformDoubleReply as transformReply } from '.'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['TDIGEST.MIN', key]; + }, + transformReply: transformDoubleReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts index 7790debf0de..7d96d5c9197 100644 --- a/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './QUANTILE'; +import QUANTILE from './QUANTILE'; describe('TDIGEST.QUANTILE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.QUANTILE', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + QUANTILE.transformArguments('key', [1, 2]), + ['TDIGEST.QUANTILE', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.quantile', async client => { - const [, reply] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.quantile('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.quantile', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.quantile('key', [1]) + ]); - assert.deepEqual( - reply, - [NaN] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + reply, + [NaN] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.ts index 2289ffc6f55..6beda56f775 100644 --- a/packages/bloom/lib/commands/t-digest/QUANTILE.ts +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.ts @@ -1,23 +1,17 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - quantiles: Array -): RedisCommandArguments { - const args = [ - 'TDIGEST.QUANTILE', - key - ]; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, quantiles: Array) { + const args = ['TDIGEST.QUANTILE', key]; for (const quantile of quantiles) { - args.push(quantile.toString()); + args.push(quantile.toString()); } return args; -} - -export { transformDoublesReply as transformReply } from '.'; + }, + transformReply: transformArrayDoubleReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/RANK.spec.ts b/packages/bloom/lib/commands/t-digest/RANK.spec.ts index 258bedf3491..8cac177ecc6 100644 --- a/packages/bloom/lib/commands/t-digest/RANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/RANK.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './RANK'; +import RANK from './RANK'; describe('TDIGEST.RANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.RANK', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RANK.transformArguments('key', [1, 2]), + ['TDIGEST.RANK', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.rank', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.rank('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.rank', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.rank('key', [1]) + ]); - assert.deepEqual(reply, [-2]); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [-2]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/RANK.ts b/packages/bloom/lib/commands/t-digest/RANK.ts index 1a6c84bbd4d..8c18ad12778 100644 --- a/packages/bloom/lib/commands/t-digest/RANK.ts +++ b/packages/bloom/lib/commands/t-digest/RANK.ts @@ -1,19 +1,22 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; +export function transformRankArguments( + command: RedisArgument, + key: RedisArgument, + values: Array +) { + const args = [command, key]; -export const IS_READ_ONLY = true; + for (const value of values) { + args.push(value.toString()); + } -export function transformArguments( - key: RedisCommandArgument, - values: Array -): RedisCommandArguments { - const args = ['TDIGEST.RANK', key]; - for (const item of values) { - args.push(item.toString()); - } - - return args; + return args; } -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: transformRankArguments.bind(undefined, 'TDIGEST.RANK'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/RESET.spec.ts b/packages/bloom/lib/commands/t-digest/RESET.spec.ts index 036fbebc8cc..41c4d1491db 100644 --- a/packages/bloom/lib/commands/t-digest/RESET.spec.ts +++ b/packages/bloom/lib/commands/t-digest/RESET.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './RESET'; +import RESET from './RESET'; describe('TDIGEST.RESET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TDIGEST.RESET', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RESET.transformArguments('key'), + ['TDIGEST.RESET', 'key'] + ); + }); - testUtils.testWithClient('client.tDigest.reset', async client => { - const [, reply] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.reset('key') - ]); + testUtils.testWithClient('client.tDigest.reset', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.reset('key') + ]); - assert.equal(reply, 'OK'); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/RESET.ts b/packages/bloom/lib/commands/t-digest/RESET.ts index 6c700e6b932..372a1efd488 100644 --- a/packages/bloom/lib/commands/t-digest/RESET.ts +++ b/packages/bloom/lib/commands/t-digest/RESET.ts @@ -1,9 +1,10 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument) { return ['TDIGEST.RESET', key]; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts index 21d16661dfe..8600ea3645b 100644 --- a/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './REVRANK'; +import REVRANK from './REVRANK'; describe('TDIGEST.REVRANK', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', [1, 2]), - ['TDIGEST.REVRANK', 'key', '1', '2'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + REVRANK.transformArguments('key', [1, 2]), + ['TDIGEST.REVRANK', 'key', '1', '2'] + ); + }); - testUtils.testWithClient('client.tDigest.revRank', async client => { - const [ , reply ] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.revRank('key', [1]) - ]); + testUtils.testWithClient('client.tDigest.revRank', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.revRank('key', [1]) + ]); - assert.deepEqual(reply, [-2]); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [-2]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/REVRANK.ts b/packages/bloom/lib/commands/t-digest/REVRANK.ts index a2465052774..456b2be5a38 100644 --- a/packages/bloom/lib/commands/t-digest/REVRANK.ts +++ b/packages/bloom/lib/commands/t-digest/REVRANK.ts @@ -1,19 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, - values: Array -): RedisCommandArguments { - const args = ['TDIGEST.REVRANK', key]; - for (const item of values) { - args.push(item.toString()); - } - - return args; -} - -export declare function transformReply(): Array; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import RANK, { transformRankArguments } from './RANK'; + +export default { + FIRST_KEY_INDEX: RANK.FIRST_KEY_INDEX, + IS_READ_ONLY: RANK.IS_READ_ONLY, + transformArguments: transformRankArguments.bind(undefined, 'TDIGEST.REVRANK'), + transformReply: RANK.transformReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts index dd07f325c8d..387a605a188 100644 --- a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts +++ b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments, transformReply } from './TRIMMED_MEAN'; +import TRIMMED_MEAN from './TRIMMED_MEAN'; -describe('TDIGEST.RESET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 0, 1), - ['TDIGEST.TRIMMED_MEAN', 'key', '0', '1'] - ); - }); +describe('TDIGEST.TRIMMED_MEAN', () => { + it('transformArguments', () => { + assert.deepEqual( + TRIMMED_MEAN.transformArguments('key', 0, 1), + ['TDIGEST.TRIMMED_MEAN', 'key', '0', '1'] + ); + }); - testUtils.testWithClient('client.tDigest.trimmedMean', async client => { - const [, reply] = await Promise.all([ - client.tDigest.create('key'), - client.tDigest.trimmedMean('key', 0, 1) - ]); + testUtils.testWithClient('client.tDigest.trimmedMean', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.trimmedMean('key', 0, 1) + ]); - assert.equal(reply, NaN); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, NaN); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts index 6de80ba7c7c..f91dd7d8093 100644 --- a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts +++ b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts @@ -1,20 +1,20 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, lowCutPercentile: number, highCutPercentile: number -): RedisCommandArguments { + ) { return [ - 'TDIGEST.TRIMMED_MEAN', - key, - lowCutPercentile.toString(), - highCutPercentile.toString() + 'TDIGEST.TRIMMED_MEAN', + key, + lowCutPercentile.toString(), + highCutPercentile.toString() ]; -} - -export { transformDoubleReply as transformReply } from '.'; + }, + transformReply: transformDoubleReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/index.spec.ts b/packages/bloom/lib/commands/t-digest/index.spec.ts deleted file mode 100644 index 5bef6df04b2..00000000000 --- a/packages/bloom/lib/commands/t-digest/index.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { strict as assert } from 'assert'; -import { pushCompressionArgument, transformDoubleReply, transformDoublesReply } from '.'; - -describe('pushCompressionArgument', () => { - it('undefined', () => { - assert.deepEqual( - pushCompressionArgument([]), - [] - ); - }); - - it('100', () => { - assert.deepEqual( - pushCompressionArgument([], { COMPRESSION: 100 }), - ['COMPRESSION', '100'] - ); - }); -}); - -describe('transformDoubleReply', () => { - it('inf', () => { - assert.equal( - transformDoubleReply('inf'), - Infinity - ); - }); - - it('-inf', () => { - assert.equal( - transformDoubleReply('-inf'), - -Infinity - ); - }); - - it('nan', () => { - assert.equal( - transformDoubleReply('nan'), - NaN - ); - }); - - it('0', () => { - assert.equal( - transformDoubleReply('0'), - 0 - ); - }); -}); - -it('transformDoublesReply', () => { - assert.deepEqual( - transformDoublesReply(['inf', '-inf', 'nan', '0']), - [Infinity, -Infinity, NaN, 0] - ); -}); diff --git a/packages/bloom/lib/commands/t-digest/index.ts b/packages/bloom/lib/commands/t-digest/index.ts index da3b37464d2..70234d450b7 100644 --- a/packages/bloom/lib/commands/t-digest/index.ts +++ b/packages/bloom/lib/commands/t-digest/index.ts @@ -1,81 +1,60 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import * as ADD from './ADD'; -import * as BYRANK from './BYRANK'; -import * as BYREVRANK from './BYREVRANK'; -import * as CDF from './CDF'; -import * as CREATE from './CREATE'; -import * as INFO from './INFO'; -import * as MAX from './MAX'; -import * as MERGE from './MERGE'; -import * as MIN from './MIN'; -import * as QUANTILE from './QUANTILE'; -import * as RANK from './RANK'; -import * as RESET from './RESET'; -import * as REVRANK from './REVRANK'; -import * as TRIMMED_MEAN from './TRIMMED_MEAN'; +import ADD from './ADD'; +import BYRANK from './BYRANK'; +import BYREVRANK from './BYREVRANK'; +import CDF from './CDF'; +import CREATE from './CREATE'; +// import INFO from './INFO'; +import MAX from './MAX'; +import MERGE from './MERGE'; +import MIN from './MIN'; +import QUANTILE from './QUANTILE'; +import RANK from './RANK'; +import RESET from './RESET'; +import REVRANK from './REVRANK'; +import TRIMMED_MEAN from './TRIMMED_MEAN'; + +type ADD = typeof import('./ADD').default; +type BYRANK = typeof import('./BYRANK').default; +type BYREVRANK = typeof import('./BYREVRANK').default; +type CDF = typeof import('./CDF').default; +type CREATE = typeof import('./CREATE').default; +// type INFO = typeof import('./INFO').default; +type MAX = typeof import('./MAX').default; +type MERGE = typeof import('./MERGE').default; +type MIN = typeof import('./MIN').default; +type QUANTILE = typeof import('./QUANTILE').default; +type RANK = typeof import('./RANK').default; +type RESET = typeof import('./RESET').default; +type REVRANK = typeof import('./REVRANK').default; +type TRIMMED_MEAN = typeof import('./TRIMMED_MEAN').default; export default { - ADD, - add: ADD, - BYRANK, - byRank: BYRANK, - BYREVRANK, - byRevRank: BYREVRANK, - CDF, - cdf: CDF, - CREATE, - create: CREATE, - INFO, - info: INFO, - MAX, - max: MAX, - MERGE, - merge: MERGE, - MIN, - min: MIN, - QUANTILE, - quantile: QUANTILE, - RANK, - rank: RANK, - RESET, - reset: RESET, - REVRANK, - revRank: REVRANK, - TRIMMED_MEAN, - trimmedMean: TRIMMED_MEAN + ADD: ADD as ADD, + add: ADD as ADD, + BYRANK: BYRANK as BYRANK, + byRank: BYRANK as BYRANK, + BYREVRANK: BYREVRANK as BYREVRANK, + byRevRank: BYREVRANK as BYREVRANK, + CDF: CDF as CDF, + cdf: CDF as CDF, + CREATE: CREATE as CREATE, + create: CREATE as CREATE, + // INFO: INFO as INFO, + // info: INFO as INFO, + MAX: MAX as MAX, + max: MAX as MAX, + MERGE: MERGE as MERGE, + merge: MERGE as MERGE, + MIN: MIN as MIN, + min: MIN as MIN, + QUANTILE: QUANTILE as QUANTILE, + quantile: QUANTILE as QUANTILE, + RANK: RANK as RANK, + rank: RANK as RANK, + RESET: RESET as RESET, + reset: RESET as RESET, + REVRANK: REVRANK as REVRANK, + revRank: REVRANK as REVRANK, + TRIMMED_MEAN: TRIMMED_MEAN as TRIMMED_MEAN, + trimmedMean: TRIMMED_MEAN as TRIMMED_MEAN }; - -export interface CompressionOption { - COMPRESSION?: number; -} - -export function pushCompressionArgument( - args: RedisCommandArguments, - options?: CompressionOption -): RedisCommandArguments { - if (options?.COMPRESSION) { - args.push('COMPRESSION', options.COMPRESSION.toString()); - } - - return args; -} - -export function transformDoubleReply(reply: string): number { - switch (reply) { - case 'inf': - return Infinity; - - case '-inf': - return -Infinity; - - case 'nan': - return NaN; - - default: - return parseFloat(reply); - } -} - -export function transformDoublesReply(reply: Array): Array { - return reply.map(transformDoubleReply); -} diff --git a/packages/bloom/lib/commands/top-k/ADD.spec.ts b/packages/bloom/lib/commands/top-k/ADD.spec.ts index 149007f81d0..dc29aab803a 100644 --- a/packages/bloom/lib/commands/top-k/ADD.spec.ts +++ b/packages/bloom/lib/commands/top-k/ADD.spec.ts @@ -1,22 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './ADD'; +import ADD from './ADD'; -describe('TOPK ADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['TOPK.ADD', 'key', 'item'] - ); - }); +describe('TOPK.ADD', () => { + it('transformArguments', () => { + assert.deepEqual( + ADD.transformArguments('key', 'item'), + ['TOPK.ADD', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.topK.add', async client => { - await client.topK.reserve('topK', 3); + testUtils.testWithClient('client.topK.add', async client => { + const [, reply] = await Promise.all([ + client.topK.reserve('topK', 3), + client.topK.add('topK', 'item') + ]); - assert.deepEqual( - await client.topK.add('topK', 'item'), - [null] - ); - - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [null]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/ADD.ts b/packages/bloom/lib/commands/top-k/ADD.ts index 125c2e71bef..4043c86c56d 100644 --- a/packages/bloom/lib/commands/top-k/ADD.ts +++ b/packages/bloom/lib/commands/top-k/ADD.ts @@ -1,13 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { ArrayReply, SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: string, - items: string | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { return pushVariadicArguments(['TOPK.ADD', key], items); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/COUNT.spec.ts b/packages/bloom/lib/commands/top-k/COUNT.spec.ts index 318fc74c679..156b6147e90 100644 --- a/packages/bloom/lib/commands/top-k/COUNT.spec.ts +++ b/packages/bloom/lib/commands/top-k/COUNT.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './COUNT'; +import COUNT from './COUNT'; -describe('TOPK COUNT', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['TOPK.COUNT', 'key', 'item'] - ); - }); +describe('TOPK.COUNT', () => { + it('transformArguments', () => { + assert.deepEqual( + COUNT.transformArguments('key', 'item'), + ['TOPK.COUNT', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.topK.count', async client => { - await client.topK.reserve('key', 3); + testUtils.testWithClient('client.topK.count', async client => { + const [, reply] = await Promise.all([ + client.topK.reserve('key', 3), + client.topK.count('key', 'item') + ]); - assert.deepEqual( - await client.topK.count('key', 'item'), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [0]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/COUNT.ts b/packages/bloom/lib/commands/top-k/COUNT.ts index cb877ecc25f..7e3ccc6dc4c 100644 --- a/packages/bloom/lib/commands/top-k/COUNT.ts +++ b/packages/bloom/lib/commands/top-k/COUNT.ts @@ -1,15 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - items: string | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { return pushVariadicArguments(['TOPK.COUNT', key], items); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/INCRBY.spec.ts b/packages/bloom/lib/commands/top-k/INCRBY.spec.ts index b23ca6e0ed1..5e14ba49c28 100644 --- a/packages/bloom/lib/commands/top-k/INCRBY.spec.ts +++ b/packages/bloom/lib/commands/top-k/INCRBY.spec.ts @@ -1,42 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INCRBY'; +import INCRBY from './INCRBY'; -describe('TOPK INCRBY', () => { - describe('transformArguments', () => { - it('single item', () => { - assert.deepEqual( - transformArguments('key', { - item: 'item', - incrementBy: 1 - }), - ['TOPK.INCRBY', 'key', 'item', '1'] - ); - }); +describe('TOPK.INCRBY', () => { + describe('transformArguments', () => { + it('single item', () => { + assert.deepEqual( + INCRBY.transformArguments('key', { + item: 'item', + incrementBy: 1 + }), + ['TOPK.INCRBY', 'key', 'item', '1'] + ); + }); - it('multiple items', () => { - assert.deepEqual( - transformArguments('key', [{ - item: 'a', - incrementBy: 1 - }, { - item: 'b', - incrementBy: 2 - }]), - ['TOPK.INCRBY', 'key', 'a', '1', 'b', '2'] - ); - }); + it('multiple items', () => { + assert.deepEqual( + INCRBY.transformArguments('key', [{ + item: 'a', + incrementBy: 1 + }, { + item: 'b', + incrementBy: 2 + }]), + ['TOPK.INCRBY', 'key', 'a', '1', 'b', '2'] + ); }); + }); - testUtils.testWithClient('client.topK.incrby', async client => { - await client.topK.reserve('key', 5); + testUtils.testWithClient('client.topK.incrby', async client => { + const [, reply] = await Promise.all([ + client.topK.reserve('key', 5), + client.topK.incrBy('key', { + item: 'item', + incrementBy: 1 + }) + ]); - assert.deepEqual( - await client.topK.incrBy('key', { - item: 'item', - incrementBy: 1 - }), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [null]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/INCRBY.ts b/packages/bloom/lib/commands/top-k/INCRBY.ts index 2533cb05594..16decf44dca 100644 --- a/packages/bloom/lib/commands/top-k/INCRBY.ts +++ b/packages/bloom/lib/commands/top-k/INCRBY.ts @@ -1,29 +1,32 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -interface IncrByItem { - item: string; - incrementBy: number; +export interface TopKIncrByItem { + item: string; + incrementBy: number; } -export function transformArguments( - key: string, - items: IncrByItem | Array -): Array { +function pushIncrByItem(args: Array, { item, incrementBy }: TopKIncrByItem) { + args.push(item, incrementBy.toString()); +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, + items: TopKIncrByItem | Array + ) { const args = ['TOPK.INCRBY', key]; if (Array.isArray(items)) { - for (const item of items) { - pushIncrByItem(args, item); - } + for (const item of items) { + pushIncrByItem(args, item); + } } else { - pushIncrByItem(args, items); + pushIncrByItem(args, items); } return args; -} - -function pushIncrByItem(args: Array, { item, incrementBy }: IncrByItem): void { - args.push(item, incrementBy.toString()); -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/INFO.spec.ts b/packages/bloom/lib/commands/top-k/INFO.spec.ts index 2741a58a8ba..d138c90393d 100644 --- a/packages/bloom/lib/commands/top-k/INFO.spec.ts +++ b/packages/bloom/lib/commands/top-k/INFO.spec.ts @@ -1,23 +1,26 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './INFO'; +import INFO from './INFO'; describe('TOPK INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TOPK.INFO', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + INFO.transformArguments('key'), + ['TOPK.INFO', 'key'] + ); + }); - testUtils.testWithClient('client.topK.info', async client => { - await client.topK.reserve('key', 3); + testUtils.testWithClient('client.topK.info', async client => { + const k = 3, + [, reply] = await Promise.all([ + client.topK.reserve('key', 3), + client.topK.info('key') + ]); - const info = await client.topK.info('key'); - assert.equal(typeof info, 'object'); - assert.equal(info.k, 3); - assert.equal(typeof info.width, 'number'); - assert.equal(typeof info.depth, 'number'); - assert.equal(typeof info.decay, 'number'); - }, GLOBAL.SERVERS.OPEN); + assert.equal(typeof reply, 'object'); + assert.equal(reply.k, k); + assert.equal(typeof reply.width, 'number'); + assert.equal(typeof reply.depth, 'number'); + assert.equal(typeof reply.decay, 'number'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/INFO.ts b/packages/bloom/lib/commands/top-k/INFO.ts index 8c9e8d432b3..bd694eace2a 100644 --- a/packages/bloom/lib/commands/top-k/INFO.ts +++ b/packages/bloom/lib/commands/top-k/INFO.ts @@ -1,34 +1,25 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { +export type TopKInfoReply = TuplesToMapReply<[ + [BlobStringReply<'k'>, NumberReply], + [BlobStringReply<'width'>, NumberReply], + [BlobStringReply<'depth'>, NumberReply], + [BlobStringReply<'decay'>, DoubleReply] +]>; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['TOPK.INFO', key]; -} - -export type InfoRawReply = [ - _: string, - k: number, - _: string, - width: number, - _: string, - depth: number, - _: string, - decay: string -]; - -export interface InfoReply { - k: number, - width: number; - depth: number; - decay: number; -} - -export function transformReply(reply: InfoRawReply): InfoReply { - return { - k: reply[1], - width: reply[3], - depth: reply[5], - decay: Number(reply[7]) - }; -} + }, + transformReply: { + 2: (reply: Resp2Reply) => ({ + k: reply[1], + width: reply[3], + depth: reply[5], + decay: Number(reply[7]) + }), + 3: undefined as unknown as () => TopKInfoReply + } +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/LIST.spec.ts b/packages/bloom/lib/commands/top-k/LIST.spec.ts index 709ac7ffc39..b2ba11fcdd2 100644 --- a/packages/bloom/lib/commands/top-k/LIST.spec.ts +++ b/packages/bloom/lib/commands/top-k/LIST.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './LIST'; +import LIST from './LIST'; -describe('TOPK LIST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TOPK.LIST', 'key'] - ); - }); +describe('TOPK.LIST', () => { + it('transformArguments', () => { + assert.deepEqual( + LIST.transformArguments('key'), + ['TOPK.LIST', 'key'] + ); + }); - testUtils.testWithClient('client.topK.list', async client => { - await client.topK.reserve('key', 3); + testUtils.testWithClient('client.topK.list', async client => { + const [, reply] = await Promise.all([ + client.topK.reserve('key', 3), + client.topK.list('key') + ]); - assert.deepEqual( - await client.topK.list('key'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, []); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/LIST.ts b/packages/bloom/lib/commands/top-k/LIST.ts index 8837b86f830..d4c9f4cce78 100644 --- a/packages/bloom/lib/commands/top-k/LIST.ts +++ b/packages/bloom/lib/commands/top-k/LIST.ts @@ -1,9 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['TOPK.LIST', key]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts index 1e55239c243..06d40ad37a8 100644 --- a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts +++ b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts @@ -1,30 +1,27 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './LIST_WITHCOUNT'; +import LIST_WITHCOUNT from './LIST_WITHCOUNT'; -describe('TOPK LIST WITHCOUNT', () => { - testUtils.isVersionGreaterThanHook([2, 2, 9]); - - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['TOPK.LIST', 'key', 'WITHCOUNT'] - ); - }); +describe('TOPK.LIST WITHCOUNT', () => { + testUtils.isVersionGreaterThanHook([2, 2, 9]); - testUtils.testWithClient('client.topK.listWithCount', async client => { - const [,, list] = await Promise.all([ - client.topK.reserve('key', 3), - client.topK.add('key', 'item'), - client.topK.listWithCount('key') - ]); + it('transformArguments', () => { + assert.deepEqual( + LIST_WITHCOUNT.transformArguments('key'), + ['TOPK.LIST', 'key', 'WITHCOUNT'] + ); + }); - assert.deepEqual( - list, - [{ - item: 'item', - count: 1 - }] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.topK.listWithCount', async client => { + const [, , list] = await Promise.all([ + client.topK.reserve('key', 3), + client.topK.add('key', 'item'), + client.topK.listWithCount('key') + ]); + + assert.deepEqual(list, [{ + item: 'item', + count: 1 + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts index 47b7d3848ed..a135e5db46f 100644 --- a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts +++ b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts @@ -1,26 +1,24 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, SimpleStringReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['TOPK.LIST', key, 'WITHCOUNT']; -} - -type ListWithCountRawReply = Array; - -type ListWithCountReply = Array<{ - item: string, - count: number -}>; - -export function transformReply(rawReply: ListWithCountRawReply): ListWithCountReply { - const reply: ListWithCountReply = []; + }, + transformReply(rawReply: ArrayReply) { + const reply = [] as unknown as ArrayReply<{ + item: SimpleStringReply; + count: NumberReply; + }>; + for (let i = 0; i < rawReply.length; i++) { - reply.push({ - item: rawReply[i] as string, - count: rawReply[++i] as number - }); + reply.push({ + item: rawReply[i] as SimpleStringReply, + count: rawReply[++i] as NumberReply + }); } return reply; -} \ No newline at end of file + } +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/QUERY.spec.ts b/packages/bloom/lib/commands/top-k/QUERY.spec.ts index ada9e7e2e39..fdaefe91eab 100644 --- a/packages/bloom/lib/commands/top-k/QUERY.spec.ts +++ b/packages/bloom/lib/commands/top-k/QUERY.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './QUERY'; +import QUERY from './QUERY'; -describe('TOPK QUERY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'item'), - ['TOPK.QUERY', 'key', 'item'] - ); - }); +describe('TOPK.QUERY', () => { + it('transformArguments', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'item'), + ['TOPK.QUERY', 'key', 'item'] + ); + }); - testUtils.testWithClient('client.cms.query', async client => { - await client.topK.reserve('key', 3); + testUtils.testWithClient('client.topK.query', async client => { + const [, reply] = await Promise.all([ + client.topK.reserve('key', 3), + client.topK.query('key', 'item') + ]); - assert.deepEqual( - await client.topK.query('key', 'item'), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [false]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/QUERY.ts b/packages/bloom/lib/commands/top-k/QUERY.ts index 55451df3d45..5529d4ab838 100644 --- a/packages/bloom/lib/commands/top-k/QUERY.ts +++ b/packages/bloom/lib/commands/top-k/QUERY.ts @@ -1,15 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments, transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - items: string | Array -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, items: RedisVariadicArgument) { return pushVariadicArguments(['TOPK.QUERY', key], items); -} - -export declare function transformReply(): Array; + }, + transformReply: transformBooleanArrayReply +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/RESERVE.spec.ts b/packages/bloom/lib/commands/top-k/RESERVE.spec.ts index 54600c0e4f5..f58c5b8b33f 100644 --- a/packages/bloom/lib/commands/top-k/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/top-k/RESERVE.spec.ts @@ -1,32 +1,32 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../../test-utils'; -import { transformArguments } from './RESERVE'; +import RESERVE from './RESERVE'; -describe('TOPK RESERVE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('topK', 3), - ['TOPK.RESERVE', 'topK', '3'] - ); - }); +describe('TOPK.RESERVE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + RESERVE.transformArguments('topK', 3), + ['TOPK.RESERVE', 'topK', '3'] + ); + }); - it('with options', () => { - assert.deepEqual( - transformArguments('topK', 3, { - width: 8, - depth: 7, - decay: 0.9 - }), - ['TOPK.RESERVE', 'topK', '3', '8', '7', '0.9'] - ); - }); + it('with options', () => { + assert.deepEqual( + RESERVE.transformArguments('topK', 3, { + width: 8, + depth: 7, + decay: 0.9 + }), + ['TOPK.RESERVE', 'topK', '3', '8', '7', '0.9'] + ); }); + }); - testUtils.testWithClient('client.topK.reserve', async client => { - assert.equal( - await client.topK.reserve('topK', 3), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.topK.reserve', async client => { + assert.equal( + await client.topK.reserve('topK', 3), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/bloom/lib/commands/top-k/RESERVE.ts b/packages/bloom/lib/commands/top-k/RESERVE.ts index 350d4cd8339..12671728fea 100644 --- a/packages/bloom/lib/commands/top-k/RESERVE.ts +++ b/packages/bloom/lib/commands/top-k/RESERVE.ts @@ -1,29 +1,26 @@ -export const FIRST_KEY_INDEX = 1; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -interface ReserveOptions { - width: number; - depth: number; - decay: number; +export interface TopKReserveOptions { + width: number; + depth: number; + decay: number; } -export function transformArguments( - key: string, - topK: number, - options?: ReserveOptions -): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, topK: number, options?: TopKReserveOptions) { const args = ['TOPK.RESERVE', key, topK.toString()]; if (options) { - args.push( - options.width.toString(), - options.depth.toString(), - options.decay.toString() - ); + args.push( + options.width.toString(), + options.depth.toString(), + options.decay.toString() + ); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/index.ts b/packages/bloom/lib/commands/top-k/index.ts index 750c91dfa88..87394839f63 100644 --- a/packages/bloom/lib/commands/top-k/index.ts +++ b/packages/bloom/lib/commands/top-k/index.ts @@ -1,27 +1,36 @@ -import * as ADD from './ADD'; -import * as COUNT from './COUNT'; -import * as INCRBY from './INCRBY'; -import * as INFO from './INFO'; -import * as LIST_WITHCOUNT from './LIST_WITHCOUNT'; -import * as LIST from './LIST'; -import * as QUERY from './QUERY'; -import * as RESERVE from './RESERVE'; +import ADD from './ADD'; +import COUNT from './COUNT'; +import INCRBY from './INCRBY'; +import INFO from './INFO'; +import LIST_WITHCOUNT from './LIST_WITHCOUNT'; +import LIST from './LIST'; +import QUERY from './QUERY'; +import RESERVE from './RESERVE'; + +type ADD = typeof import('./ADD').default; +type COUNT = typeof import('./COUNT').default; +type INCRBY = typeof import('./INCRBY').default; +type INFO = typeof import('./INFO').default; +type LIST_WITHCOUNT = typeof import('./LIST_WITHCOUNT').default; +type LIST = typeof import('./LIST').default; +type QUERY = typeof import('./QUERY').default; +type RESERVE = typeof import('./RESERVE').default; export default { - ADD, - add: ADD, - COUNT, - count: COUNT, - INCRBY, - incrBy: INCRBY, - INFO, - info: INFO, - LIST_WITHCOUNT, - listWithCount: LIST_WITHCOUNT, - LIST, - list: LIST, - QUERY, - query: QUERY, - RESERVE, - reserve: RESERVE + ADD: ADD as ADD, + add: ADD as ADD, + COUNT: COUNT as COUNT, + count: COUNT as COUNT, + INCRBY: INCRBY as INCRBY, + incrBy: INCRBY as INCRBY, + INFO: INFO as INFO, + info: INFO as INFO, + LIST_WITHCOUNT: LIST_WITHCOUNT as LIST_WITHCOUNT, + listWithCount: LIST_WITHCOUNT as LIST_WITHCOUNT, + LIST: LIST as LIST, + list: LIST as LIST, + QUERY: QUERY as QUERY, + query: QUERY as QUERY, + RESERVE: RESERVE as RESERVE, + reserve: RESERVE as RESERVE }; diff --git a/packages/bloom/lib/test-utils.ts b/packages/bloom/lib/test-utils.ts index a2e059b3b99..70e8a154d60 100644 --- a/packages/bloom/lib/test-utils.ts +++ b/packages/bloom/lib/test-utils.ts @@ -2,18 +2,18 @@ import TestUtils from '@redis/test-utils'; import RedisBloomModules from '.'; export default new TestUtils({ - dockerImageName: 'redislabs/rebloom', - dockerImageVersionArgument: 'redisbloom-version', - defaultDockerVersion: 'edge' + dockerImageName: 'redislabs/rebloom', + dockerImageVersionArgument: 'redisbloom-version', + defaultDockerVersion: 'edge' }); export const GLOBAL = { - SERVERS: { - OPEN: { - serverArguments: ['--loadmodule /usr/lib/redis/modules/redisbloom.so'], - clientOptions: { - modules: RedisBloomModules - } - } + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/redisbloom.so'], + clientOptions: { + modules: RedisBloomModules + } } + } }; diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts index 862b51a4aa6..b78b01c37e6 100644 --- a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts @@ -3,6 +3,8 @@ import testUtils, { GLOBAL } from '../test-utils'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; describe('XADD NOMKSTREAM', () => { + testUtils.isVersionGreaterThanHook([6, 2]); + describe('transformArguments', () => { it('single field', () => { assert.deepEqual( diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 8298a966d8a..91008d013eb 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,4 +1,14 @@ -import { ArrayReply, BlobStringReply, CommandArguments, DoubleReply, NullReply, RedisArgument, Resp2Reply, TuplesReply } from '../RESP/types'; +import { ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; + +export const transformBooleanReply = { + 2: (reply: NumberReply<0 | 1>) => reply === 1, + 3: undefined as unknown as () => BooleanReply +}; + +export const transformBooleanArrayReply = { + 2: (reply: ArrayReply>) => reply.map(transformBooleanReply[2]), + 3: undefined as unknown as () => ArrayReply +}; export type BitValue = 0 | 1; @@ -24,11 +34,14 @@ export function transformStringDoubleArgument(num: RedisArgument | number): Redi export const transformDoubleReply = { 2: (reply: BlobStringReply) => { switch (reply.toString()) { + case 'inf': case '+inf': return Infinity; case '-inf': return -Infinity; + + case 'nan': default: return Number(reply); @@ -37,6 +50,11 @@ export const transformDoubleReply = { 3: undefined as unknown as () => DoubleReply }; +export const transformDoubleArrayReply = { + 2: (reply: Array) => reply.map(transformDoubleReply[2]), + 3: undefined as unknown as () => ArrayReply +} + export const transformNullableDoubleReply = { 2: (reply: BlobStringReply | NullReply) => { if (reply === null) return null; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 3271cf400a2..5e044cbaa1e 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -11,9 +11,6 @@ "./lib/test-utils.ts", "./lib/**/*.spec.ts" ], - "ts-node": { - "transpileOnly": true - }, "typedocOptions": { "entryPoints": [ "./index.ts", diff --git a/tsconfig.base.json b/tsconfig.base.json index f674e2e5c0a..8e9d90d31cb 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -6,6 +6,7 @@ "allowJs": true }, "ts-node": { - "files": true + "files": true, + "transpileOnly": true } } diff --git a/tsconfig.json b/tsconfig.json index 53bc24d8830..3c2207d4ffe 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,10 +3,10 @@ "path": "./packages/client" }, { "path": "./packages/test-utils" + }, { + "path": "./packages/bloom" }], "todo": [{ - "path": "./packages/bloom" - }, { "path": "./packages/graph" }, { "path": "./packages/json" From d298da82dd8f00a4697851595dfa36e5e2ab8f8a Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 5 Jul 2023 16:08:23 -0400 Subject: [PATCH 162/325] wip --- packages/client/lib/commands/BLMOVE.spec.ts | 6 +++--- packages/client/lib/commands/BLMPOP.spec.ts | 6 +++--- packages/client/lib/commands/BLPOP.spec.ts | 4 ++-- packages/client/lib/commands/BRPOP.spec.ts | 4 ++-- packages/client/lib/commands/BRPOPLPUSH.spec.ts | 4 ++-- packages/client/lib/commands/BZMPOP.spec.ts | 6 +++--- packages/client/lib/commands/BZPOPMAX.spec.ts | 6 +++--- packages/client/lib/commands/BZPOPMIN.spec.ts | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/client/lib/commands/BLMOVE.spec.ts b/packages/client/lib/commands/BLMOVE.spec.ts index 3afda7f8a01..489afff09b9 100644 --- a/packages/client/lib/commands/BLMOVE.spec.ts +++ b/packages/client/lib/commands/BLMOVE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, MIN_BLOCKING_TIME } from '../test-utils'; import BLMOVE from './BLMOVE'; describe('BLMOVE', () => { @@ -14,7 +14,7 @@ describe('BLMOVE', () => { testUtils.testAll('blMove - null', async client => { assert.equal( - await client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', Number.MIN_VALUE), + await client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', MIN_BLOCKING_TIME), null ); }, { @@ -25,7 +25,7 @@ describe('BLMOVE', () => { testUtils.testAll('blMove - with member', async client => { const [, reply] = await Promise.all([ client.lPush('{tag}source', 'element'), - client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', Number.MIN_VALUE) + client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', MIN_BLOCKING_TIME) ]); assert.equal(reply, 'element'); }, { diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts index 6e87446ca81..6a2f01c4ed2 100644 --- a/packages/client/lib/commands/BLMPOP.spec.ts +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, MIN_BLOCKING_TIME } from '../test-utils'; import BLMPOP from './BLMPOP'; describe('BLMPOP', () => { @@ -25,7 +25,7 @@ describe('BLMPOP', () => { testUtils.testAll('blmPop - null', async client => { assert.equal( - await client.blmPop(Number.MIN_VALUE, 'key', 'RIGHT'), + await client.blmPop(MIN_BLOCKING_TIME, 'key', 'RIGHT'), null ); }, { @@ -36,7 +36,7 @@ describe('BLMPOP', () => { testUtils.testAll('blmPop - with member', async client => { const [, reply] = await Promise.all([ client.lPush('key', 'element'), - client.blmPop(Number.MIN_VALUE, 'key', 'RIGHT') + client.blmPop(MIN_BLOCKING_TIME, 'key', 'RIGHT') ]); assert.deepEqual(reply, [ 'key', diff --git a/packages/client/lib/commands/BLPOP.spec.ts b/packages/client/lib/commands/BLPOP.spec.ts index 35b9d95396a..ca9dd76ce7c 100644 --- a/packages/client/lib/commands/BLPOP.spec.ts +++ b/packages/client/lib/commands/BLPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLPOP from './BLPOP'; describe('BLPOP', () => { @@ -21,7 +21,7 @@ describe('BLPOP', () => { testUtils.testAll('blPop - null', async client => { assert.equal( - await client.blPop('key', Number.MIN_VALUE), + await client.blPop('key', BLOCKING_MIN_VALUE), null ); }, { diff --git a/packages/client/lib/commands/BRPOP.spec.ts b/packages/client/lib/commands/BRPOP.spec.ts index f484036acad..3e61ff7581a 100644 --- a/packages/client/lib/commands/BRPOP.spec.ts +++ b/packages/client/lib/commands/BRPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BRPOP from './BRPOP'; describe('BRPOP', () => { @@ -21,7 +21,7 @@ describe('BRPOP', () => { testUtils.testAll('brPop - null', async client => { assert.equal( - await client.brPop('key', Number.MIN_VALUE), + await client.brPop('key', BLOCKING_MIN_VALUE), null ); }, { diff --git a/packages/client/lib/commands/BRPOPLPUSH.spec.ts b/packages/client/lib/commands/BRPOPLPUSH.spec.ts index 1c1484868bd..d9f433707db 100644 --- a/packages/client/lib/commands/BRPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/BRPOPLPUSH.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BRPOPLPUSH from './BRPOPLPUSH'; describe('BRPOPLPUSH', () => { @@ -15,7 +15,7 @@ describe('BRPOPLPUSH', () => { await client.brPopLPush( '{tag}source', '{tag}destination', - Number.MIN_VALUE + BLOCKING_MIN_VALUE ), null ); diff --git a/packages/client/lib/commands/BZMPOP.spec.ts b/packages/client/lib/commands/BZMPOP.spec.ts index 60bc3fe4712..dcd480c8720 100644 --- a/packages/client/lib/commands/BZMPOP.spec.ts +++ b/packages/client/lib/commands/BZMPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZMPOP from './BZMPOP'; describe('BZMPOP', () => { @@ -25,7 +25,7 @@ describe('BZMPOP', () => { testUtils.testAll('bzmPop - null', async client => { assert.equal( - await client.bzmPop(Number.MIN_VALUE, 'key', 'MAX'), + await client.bzmPop(BLOCKING_MIN_VALUE, 'key', 'MAX'), null ); }, { @@ -41,7 +41,7 @@ describe('BZMPOP', () => { }, [, reply] = await Promise.all([ client.zAdd(key, member), - client.bzmPop(Number.MIN_VALUE, key, 'MAX') + client.bzmPop(BLOCKING_MIN_VALUE, key, 'MAX') ]); assert.deepEqual(reply, { diff --git a/packages/client/lib/commands/BZPOPMAX.spec.ts b/packages/client/lib/commands/BZPOPMAX.spec.ts index 64fb6b85b7d..53c6187e4e0 100644 --- a/packages/client/lib/commands/BZPOPMAX.spec.ts +++ b/packages/client/lib/commands/BZPOPMAX.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZPOPMAX from './BZPOPMAX'; describe('BZPOPMAX', () => { @@ -21,7 +21,7 @@ describe('BZPOPMAX', () => { testUtils.testAll('bzPopMax - null', async client => { assert.equal( - await client.bzPopMax('key', Number.MIN_VALUE), + await client.bzPopMax('key', BLOCKING_MIN_VALUE), null ); }, { @@ -37,7 +37,7 @@ describe('BZPOPMAX', () => { }, [, reply] = await Promise.all([ client.zAdd(key, member), - client.bzPopMax(key, Number.MIN_VALUE) + client.bzPopMax(key, BLOCKING_MIN_VALUE) ]); assert.deepEqual(reply, { diff --git a/packages/client/lib/commands/BZPOPMIN.spec.ts b/packages/client/lib/commands/BZPOPMIN.spec.ts index 399c8f30b96..96acf25a1e1 100644 --- a/packages/client/lib/commands/BZPOPMIN.spec.ts +++ b/packages/client/lib/commands/BZPOPMIN.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZPOPMIN from './BZPOPMIN'; describe('BZPOPMIN', () => { @@ -21,7 +21,7 @@ describe('BZPOPMIN', () => { testUtils.testAll('bzPopMin - null', async client => { assert.equal( - await client.bzPopMin('key', Number.MIN_VALUE), + await client.bzPopMin('key', BLOCKING_MIN_VALUE), null ); }, { @@ -37,7 +37,7 @@ describe('BZPOPMIN', () => { }, [, reply] = await Promise.all([ client.zAdd(key, member), - client.bzPopMin(key, Number.MIN_VALUE) + client.bzPopMin(key, BLOCKING_MIN_VALUE) ]); assert.deepEqual(reply, { From 2a662a367db02e92178c473b8cfc78651bde12c4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 5 Jul 2023 16:13:05 -0400 Subject: [PATCH 163/325] wip --- packages/client/lib/test-utils.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts index 4aca735c928..e4c86c2f4c9 100644 --- a/packages/client/lib/test-utils.ts +++ b/packages/client/lib/test-utils.ts @@ -61,3 +61,9 @@ export async function waitTillBeenCalled(spy: SinonSpy): Promise { await setTimeout(50); } while (spy.callCount === calls); } + +export const BLOCKING_MIN_VALUE = ( + utils.isVersionGreaterThan([7]) ? Number.MIN_VALUE : + utils.isVersionGreaterThan([6]) ? 0.01 : + 1 +); From 0ed4ee41f441d7bc833ed98c5e884ff8b8ee584d Mon Sep 17 00:00:00 2001 From: dovi Date: Wed, 5 Jul 2023 17:42:39 -0400 Subject: [PATCH 164/325] create JSON.CLEAR --- packages/json/lib/commands/CLEAR.spec.ts | 28 ++++++++++++++++++++++++ packages/json/lib/commands/CLEAR.ts | 14 ++++++++++++ packages/json/lib/commands/index.ts | 3 +++ 3 files changed, 45 insertions(+) create mode 100644 packages/json/lib/commands/CLEAR.spec.ts create mode 100644 packages/json/lib/commands/CLEAR.ts diff --git a/packages/json/lib/commands/CLEAR.spec.ts b/packages/json/lib/commands/CLEAR.spec.ts new file mode 100644 index 00000000000..ce8b2898891 --- /dev/null +++ b/packages/json/lib/commands/CLEAR.spec.ts @@ -0,0 +1,28 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import CLEAR from './CLEAR'; + +describe('CLEAR', () => { + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + CLEAR.transformArguments('key'), + ['JSON.CLEAR', 'key'] + ); + }); + + it('key, path', () => { + assert.deepEqual( + CLEAR.transformArguments('key', '$.path'), + ['JSON.CLEAR', 'key', '$.path'] + ); + }); + }); + + testUtils.testWithClient('client.json.clear', async client => { + assert.deepEqual( + await client.json.clear('key'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/CLEAR.ts b/packages/json/lib/commands/CLEAR.ts new file mode 100644 index 00000000000..a5730f5b4e6 --- /dev/null +++ b/packages/json/lib/commands/CLEAR.ts @@ -0,0 +1,14 @@ +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { + const args = ['JSON.CLEAR', key]; + + if (path) args.push(path); + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index efcf156b84d..218462f4dbf 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -1,6 +1,7 @@ import * as ARRAPPEND from './ARRAPPEND'; import * as ARRINDEX from './ARRINDEX'; import * as ARRINSERT from './ARRINSERT'; +import CLEAR from './CLEAR'; import * as ARRLEN from './ARRLEN'; import * as ARRPOP from './ARRPOP'; import * as ARRTRIM from './ARRTRIM'; @@ -26,6 +27,8 @@ export default { arrIndex: ARRINDEX, ARRINSERT, arrInsert: ARRINSERT, + CLEAR, + clear: CLEAR, ARRLEN, arrLen: ARRLEN, ARRPOP, From ab153a8edaacfb70fc89dfe834899de0ecf7f60d Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 10:38:30 -0400 Subject: [PATCH 165/325] wip --- .../lib/commands/COMMAND_GETKEYSANDFLAGS.ts | 40 +++++++-------- .../client/lib/commands/FUNCTION_LOAD.spec.ts | 2 +- .../client/lib/commands/MEMORY_STATS.spec.ts | 4 +- packages/client/lib/commands/MEMORY_STATS.ts | 1 + .../lib/commands/XINFO_CONSUMERS.spec.ts | 6 ++- .../client/lib/commands/XINFO_GROUPS.spec.ts | 6 ++- .../client/lib/commands/XINFO_STREAM.spec.ts | 8 +-- packages/client/lib/commands/XINFO_STREAM.ts | 51 +++++++++---------- .../lib/commands/XPENDING_RANGE.spec.ts | 3 +- packages/client/lib/commands/index.ts | 36 +++++++++++++ 10 files changed, 97 insertions(+), 60 deletions(-) diff --git a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts index d1232d1999e..a3581237f42 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts @@ -1,24 +1,20 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, Command } from '../RESP/types'; -// export const IS_READ_ONLY = true; +export type CommandGetKeysAndFlagsRawReply = ArrayReply +]>>; -// export function transformArguments(args: Array): RedisCommandArguments { -// return ['COMMAND', 'GETKEYSANDFLAGS', ...args]; -// } - -// type KeysAndFlagsRawReply = Array<[ -// RedisCommandArgument, -// RedisCommandArguments -// ]>; - -// type KeysAndFlagsReply = Array<{ -// key: RedisCommandArgument; -// flags: RedisCommandArguments; -// }>; - -// export function transformReply(reply: KeysAndFlagsRawReply): KeysAndFlagsReply { -// return reply.map(([key, flags]) => ({ -// key, -// flags -// })); -// } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(args: Array) { + return ['COMMAND', 'GETKEYSANDFLAGS', ...args]; + }, + transformReply(reply: CommandGetKeysAndFlagsRawReply) { + return reply.map(([key, flags]) => ({ + key, + flags + })); + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts index fbda1630673..61246c45235 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts @@ -9,7 +9,7 @@ export const MATH_FUNCTION = { engine: 'LUA', code: `#!LUA name=math - redis.register_function{ + redis.register_function { function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } diff --git a/packages/client/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts index 28caa208b8a..d210514d7fa 100644 --- a/packages/client/lib/commands/MEMORY_STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_STATS.spec.ts @@ -18,7 +18,9 @@ describe('MEMORY STATS', () => { assert.equal(typeof memoryStats['replication.backlog'], 'number'); assert.equal(typeof memoryStats['clients.slaves'], 'number'); assert.equal(typeof memoryStats['clients.normal'], 'number'); - assert.equal(typeof memoryStats['cluster.links'], 'number'); + if (testUtils.isVersionGreaterThan([7])) { + assert.equal(typeof memoryStats['cluster.links'], 'number'); + } assert.equal(typeof memoryStats['aof.buffer'], 'number'); assert.equal(typeof memoryStats['lua.caches'], 'number'); assert.equal(typeof memoryStats['functions.caches'], 'number'); diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 2d798ccd2c6..b15db7fb8fa 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -7,6 +7,7 @@ export type MemoryStatsReply = TuplesToMapReply<[ [BlobStringReply<'replication.backlog'>, NumberReply], [BlobStringReply<'clients.slaves'>, NumberReply], [BlobStringReply<'clients.normal'>, NumberReply], + /** added in 7.0 */ [BlobStringReply<'cluster.links'>, NumberReply], [BlobStringReply<'aof.buffer'>, NumberReply], [BlobStringReply<'lua.caches'>, NumberReply], diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts index e57ed72d8ea..ddfba6f27a9 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts @@ -15,7 +15,11 @@ describe('XINFO CONSUMERS', () => { client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), + // using `XREADGROUP` and not `XGROUP CREATECONSUMER` because the latter was introduced in Redis 6.2 + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '0-0' + }), client.xInfoConsumers('key', 'group') ]); diff --git a/packages/client/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts index 7ac02972d6b..20dfb148044 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -25,8 +25,10 @@ describe('XINFO GROUPS', () => { consumers: 0, pending: 0, 'last-delivered-id': '0-0', - 'entries-read': null, - lag: 0 + ...testUtils.isVersionGreaterThan([7, 0]) && { + 'entries-read': null, + lag: 0 + } }] ); }, { diff --git a/packages/client/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts index 99370fb97f1..630d25c3961 100644 --- a/packages/client/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -23,9 +23,11 @@ describe('XINFO STREAM', () => { 'radix-tree-keys': 0, 'radix-tree-nodes': 1, 'last-generated-id': '0-0', - 'max-deleted-entry-id': '0-0', - 'entries-added': 0, - 'recorded-first-entry-id': '0-0', + ...testUtils.isVersionGreaterThan([7, 0]) && { + 'max-deleted-entry-id': '0-0', + 'entries-added': 0, + 'recorded-first-entry-id': '0-0', + }, groups: 1, 'first-entry': null, 'last-entry': null diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index 00b6b0aa4e3..93416ae40ae 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -1,26 +1,16 @@ import { TuplesToMapReply, BlobStringReply, NumberReply, NullReply, Resp2Reply, Command, RespType, RESP_TYPES, RedisArgument } from '../RESP/types'; import { StreamMessageRawReply, transformStreamMessageReply } from './generic-transformers'; -export type XInfoStreamRawReply = TuplesToMapReply<[ - [BlobStringReply<'length'>, NumberReply], - [BlobStringReply<'radix-tree-keys'>, NumberReply], - [BlobStringReply<'radix-tree-nodes'>, NumberReply], - [BlobStringReply<'last-generated-id'>, BlobStringReply], - [BlobStringReply<'max-deleted-entry-id'>, BlobStringReply], - [BlobStringReply<'entries-added'>, NumberReply], - [BlobStringReply<'recorded-first-entry-id'>, BlobStringReply], - [BlobStringReply<'groups'>, NumberReply], - [BlobStringReply<'first-entry'>, StreamMessageRawReply | NullReply], - [BlobStringReply<'last-entry'>, StreamMessageRawReply | NullReply] -]>; - export type XInfoStreamReply = TuplesToMapReply<[ [BlobStringReply<'length'>, NumberReply], [BlobStringReply<'radix-tree-keys'>, NumberReply], [BlobStringReply<'radix-tree-nodes'>, NumberReply], [BlobStringReply<'last-generated-id'>, BlobStringReply], + /** added in 7.2 */ [BlobStringReply<'max-deleted-entry-id'>, BlobStringReply], + /** added in 7.2 */ [BlobStringReply<'entries-added'>, NumberReply], + /** added in 7.2 */ [BlobStringReply<'recorded-first-entry-id'>, BlobStringReply], [BlobStringReply<'groups'>, NumberReply], [BlobStringReply<'first-entry'>, ReturnType | NullReply], @@ -34,22 +24,27 @@ export default { return ['XINFO', 'STREAM', key]; }, transformReply: { - 2(reply: Resp2Reply) { - return { - length: reply[1], - 'radix-tree-keys': reply[3], - 'radix-tree-nodes': reply[5], - 'last-generated-id': reply[7], - 'max-deleted-entry-id': reply[9], - 'entries-added': reply[11], - 'recorded-first-entry-id': reply[13], - groups: reply[15], - 'first-entry': transformEntry(reply[17]), - 'last-entry': transformEntry(reply[19]) - }; + // TODO: is there a "type safe" way to do it? + 2(reply: any) { + const parsedReply: Partial = {}; + + for (let i = 0; i < reply.length; i += 2) { + switch (reply[i]) { + case 'first-entry': + case 'last-entry': + parsedReply[reply[i] as ('first-entry' | 'last-entry')] = transformEntry(reply[i + 1]) as any; + break; + + default: + parsedReply[reply[i] as keyof typeof parsedReply] = reply[i + 1]; + break; + } + } + + return parsedReply as XInfoStreamReply['DEFAULT']; }, - 3(reply: any) { // TODO: is there a "type safe" way to do it? - if (reply instanceof Map) { + 3(reply: any) { + if (reply instanceof Map) { reply.set( 'first-entry', transformEntry(reply.get('first-entry')) diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index ef25b9840cc..7fd2ae0b427 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -41,11 +41,10 @@ describe('XPENDING RANGE', () => { }); testUtils.testAll('xPendingRange', async client => { - const [, , id, , reply] = await Promise.all([ + const [, , id, reply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), client.xAdd('key', '*', { field: 'value' }), client.xReadGroup('group', 'consumer', { key: 'key', diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index cc98529c59f..efba9ad94a4 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -66,6 +66,12 @@ import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH'; import CLUSTER_SETSLOT from './CLUSTER_SETSLOT'; import CLUSTER_SLOTS from './CLUSTER_SLOTS'; +import COMMAND_COUNT from './COMMAND_COUNT'; +import COMMAND_GETKEYS from './COMMAND_GETKEYS'; +import COMMAND_GETKEYSANDFLAGS from './COMMAND_GETKEYSANDFLAGS'; +// import COMMAND_INFO from './COMMAND_INFO'; +// import COMMAND_LIST from './COMMAND_LIST'; +// import COMMAND from './COMMAND'; import CONFIG_GET from './CONFIG_GET'; import CONFIG_RESETASTAT from './CONFIG_RESETSTAT'; import CONFIG_REWRITE from './CONFIG_REWRITE'; @@ -388,6 +394,12 @@ type CLUSTER_SAVECONFIG = typeof import('./CLUSTER_SAVECONFIG').default; type CLUSTER_SET_CONFIG_EPOCH = typeof import('./CLUSTER_SET-CONFIG-EPOCH').default; type CLUSTER_SETSLOT = typeof import('./CLUSTER_SETSLOT').default; type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; +type COMMAND_COUNT = typeof import('./COMMAND_COUNT').default; +type COMMAND_GETKEYS = typeof import('./COMMAND_GETKEYS').default; +type COMMAND_GETKEYSANDFLAGS = typeof import('./COMMAND_GETKEYSANDFLAGS').default; +// type COMMAND_INFO = typeof import('./COMMAND_INFO').default; +// type COMMAND_LIST = typeof import('./COMMAND_LIST').default; +// type COMMAND = typeof import('./COMMAND').default; type CONFIG_GET = typeof import('./CONFIG_GET').default; type CONFIG_RESETASTAT = typeof import('./CONFIG_RESETSTAT').default; type CONFIG_REWRITE = typeof import('./CONFIG_REWRITE').default; @@ -778,6 +790,18 @@ type Commands = { clusterSetSlot: CLUSTER_SETSLOT; CLUSTER_SLOTS: CLUSTER_SLOTS; clusterSlots: CLUSTER_SLOTS; + COMMAND_COUNT: COMMAND_COUNT; + commandCount: COMMAND_COUNT; + COMMAND_GETKEYS: COMMAND_GETKEYS; + commandGetKeys: COMMAND_GETKEYS; + COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS; + commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS; + // COMMAND_INFO: COMMAND_INFO; + // commandInfo: COMMAND_INFO; + // COMMAND_LIST: COMMAND_LIST; + // commandList: COMMAND_LIST; + // COMMAND: COMMAND; + // command: COMMAND; CONFIG_GET: CONFIG_GET; configGet: CONFIG_GET; CONFIG_RESETASTAT: CONFIG_RESETASTAT; @@ -1423,6 +1447,18 @@ export default { clusterSetSlot: CLUSTER_SETSLOT, CLUSTER_SLOTS, clusterSlots: CLUSTER_SLOTS, + COMMAND_COUNT, + commandCount: COMMAND_COUNT, + COMMAND_GETKEYS, + commandGetKeys: COMMAND_GETKEYS, + COMMAND_GETKEYSANDFLAGS, + commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS, + // COMMAND_INFO, + // commandInfo: COMMAND_INFO, + // COMMAND_LIST, + // commandList: COMMAND_LIST, + // COMMAND, + // command: COMMAND, CONFIG_GET, configGet: CONFIG_GET, CONFIG_RESETASTAT, From 4b7784b27a21a834da54779a15df6f3b13e78539 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 10:40:39 -0400 Subject: [PATCH 166/325] workflow --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 97658828676..99ed24f37a2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,7 +34,7 @@ jobs: - name: Build run: npm run build -- ./packages/client ./packages/test-utils/ - name: Run Tests - run: npm run test -w ./packages/client -- --forbid-only --redis-version=${{ matrix.redis-version }} && npm run test -w ./packages/bloom -- --forbid-only + run: npm run test -ws --if-present -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov run: | curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import From 7bb8a32f20e762486befafbb4cdb6391c3eb4fed Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 10:42:08 -0400 Subject: [PATCH 167/325] wip --- packages/client/lib/commands/BLMOVE.spec.ts | 6 +++--- packages/client/lib/commands/BLMPOP.spec.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/client/lib/commands/BLMOVE.spec.ts b/packages/client/lib/commands/BLMOVE.spec.ts index 489afff09b9..27029e61612 100644 --- a/packages/client/lib/commands/BLMOVE.spec.ts +++ b/packages/client/lib/commands/BLMOVE.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL, MIN_BLOCKING_TIME } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLMOVE from './BLMOVE'; describe('BLMOVE', () => { @@ -14,7 +14,7 @@ describe('BLMOVE', () => { testUtils.testAll('blMove - null', async client => { assert.equal( - await client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', MIN_BLOCKING_TIME), + await client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', BLOCKING_MIN_VALUE), null ); }, { @@ -25,7 +25,7 @@ describe('BLMOVE', () => { testUtils.testAll('blMove - with member', async client => { const [, reply] = await Promise.all([ client.lPush('{tag}source', 'element'), - client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', MIN_BLOCKING_TIME) + client.blMove('{tag}source', '{tag}destination', 'LEFT', 'RIGHT', BLOCKING_MIN_VALUE) ]); assert.equal(reply, 'element'); }, { diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts index 6a2f01c4ed2..b47fb68ac4e 100644 --- a/packages/client/lib/commands/BLMPOP.spec.ts +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -1,5 +1,5 @@ import { strict as assert } from 'assert'; -import testUtils, { GLOBAL, MIN_BLOCKING_TIME } from '../test-utils'; +import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLMPOP from './BLMPOP'; describe('BLMPOP', () => { @@ -25,7 +25,7 @@ describe('BLMPOP', () => { testUtils.testAll('blmPop - null', async client => { assert.equal( - await client.blmPop(MIN_BLOCKING_TIME, 'key', 'RIGHT'), + await client.blmPop(BLOCKING_MIN_VALUE, 'key', 'RIGHT'), null ); }, { @@ -36,7 +36,7 @@ describe('BLMPOP', () => { testUtils.testAll('blmPop - with member', async client => { const [, reply] = await Promise.all([ client.lPush('key', 'element'), - client.blmPop(MIN_BLOCKING_TIME, 'key', 'RIGHT') + client.blmPop(BLOCKING_MIN_VALUE, 'key', 'RIGHT') ]); assert.deepEqual(reply, [ 'key', From 4944a53722238bd2411a11746066951af71dea94 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 10:45:13 -0400 Subject: [PATCH 168/325] remove node 19 from workflow ("dead" version) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 99ed24f37a2..048e72f6f76 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: ['16', '18', '19', '20'] + node-version: ['16', '18', '20'] redis-version: ['5', '6.0', '6.2', '7.0', '7.2-rc'] steps: - uses: actions/checkout@v3 From 9e1ec97a551a68302fa23c7f065dca970a7c6bfc Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:04:38 -0400 Subject: [PATCH 169/325] fix nan --- packages/client/lib/commands/generic-transformers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 91008d013eb..50fa903ea1c 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -42,6 +42,7 @@ export const transformDoubleReply = { return -Infinity; case 'nan': + return NaN; default: return Number(reply); From 6ca420f15e91f3214c34355c78d585b6585ffa87 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:07:52 -0400 Subject: [PATCH 170/325] fix #2561 --- docs/v4-to-v5.md | 2 +- packages/client/lib/commands/HSCAN.spec.ts | 31 +++++++++++----------- packages/client/lib/commands/HSCAN.ts | 4 +-- packages/client/lib/commands/SCAN.spec.ts | 14 +++++----- packages/client/lib/commands/SCAN.ts | 6 ++--- packages/client/lib/commands/SSCAN.spec.ts | 12 ++++----- packages/client/lib/commands/SSCAN.ts | 4 +-- packages/client/lib/commands/ZSCAN.spec.ts | 12 ++++----- packages/client/lib/commands/ZSCAN.ts | 4 +-- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index cfe91df18a4..a4cdf09b170 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -131,7 +131,7 @@ Some command arguments/replies have changed to align more closely to data types - `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` - `HEXISTS`: `boolean` -> `number` [^boolean-to-number] - `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). -- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`? +- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: `cursor` type is `string | Buffer` instead of `number` - `HSETNX`: `boolean` -> `number` [^boolean-to-number] - `ZINTER`: instead of `client.ZINTER('key', { WEIGHTS: [1] })` use `client.ZINTER({ key: 'key', weight: 1 }])` - `ZINTER_WITHSCORES`: instead of `client.ZINTER_WITHSCORES('key', { WEIGHTS: [1] })` use `client.ZINTER_WITHSCORES({ key: 'key', weight: 1 }])` diff --git a/packages/client/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts index c655f5a1a50..0a3dfd19be9 100644 --- a/packages/client/lib/commands/HSCAN.spec.ts +++ b/packages/client/lib/commands/HSCAN.spec.ts @@ -6,14 +6,14 @@ describe('HSCAN', () => { describe('transformArguments', () => { it('cusror only', () => { assert.deepEqual( - HSCAN.transformArguments('key', 0), + HSCAN.transformArguments('key', '0'), ['HSCAN', 'key', '0'] ); }); it('with MATCH', () => { assert.deepEqual( - HSCAN.transformArguments('key', 0, { + HSCAN.transformArguments('key', '0', { MATCH: 'pattern' }), ['HSCAN', 'key', '0', 'MATCH', 'pattern'] @@ -22,7 +22,7 @@ describe('HSCAN', () => { it('with COUNT', () => { assert.deepEqual( - HSCAN.transformArguments('key', 0, { + HSCAN.transformArguments('key', '0', { COUNT: 1 }), ['HSCAN', 'key', '0', 'COUNT', '1'] @@ -31,7 +31,7 @@ describe('HSCAN', () => { it('with MATCH & COUNT', () => { assert.deepEqual( - HSCAN.transformArguments('key', 0, { + HSCAN.transformArguments('key', '0', { MATCH: 'pattern', COUNT: 1 }), @@ -41,16 +41,17 @@ describe('HSCAN', () => { }); testUtils.testWithClient('client.hScan', async client => { - await client.hSet('key', 'field', 'value'); - assert.deepEqual( - await client.hScan('key', 0), - { - cursor: 0, - entries: [{ - field: 'field', - value: 'value' - }] - } - ); + const [, reply] = await Promise.all([ + client.hSet('key', 'field', 'value'), + client.hScan('key', '0') + ]); + + assert.deepEqual(reply, { + cursor: '0', + entries: [{ + field: 'field', + value: 'value' + }] + }); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/HSCAN.ts b/packages/client/lib/commands/HSCAN.ts index 2391424eb21..db52db99fef 100644 --- a/packages/client/lib/commands/HSCAN.ts +++ b/packages/client/lib/commands/HSCAN.ts @@ -11,7 +11,7 @@ export default { IS_READ_ONLY: true, transformArguments( key: RedisArgument, - cursor: number, + cursor: RedisArgument, options?: ScanCommonOptions ) { return pushScanArguments(['HSCAN', key], cursor, options); @@ -27,7 +27,7 @@ export default { } return { - cursor: Number(cursor), + cursor, entries }; } diff --git a/packages/client/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts index baf3682954e..ccffde48d2d 100644 --- a/packages/client/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -6,14 +6,14 @@ describe('SCAN', () => { describe('transformArguments', () => { it('cusror only', () => { assert.deepEqual( - SCAN.transformArguments(0), + SCAN.transformArguments('0'), ['SCAN', '0'] ); }); it('with MATCH', () => { assert.deepEqual( - SCAN.transformArguments(0, { + SCAN.transformArguments('0', { MATCH: 'pattern' }), ['SCAN', '0', 'MATCH', 'pattern'] @@ -22,7 +22,7 @@ describe('SCAN', () => { it('with COUNT', () => { assert.deepEqual( - SCAN.transformArguments(0, { + SCAN.transformArguments('0', { COUNT: 1 }), ['SCAN', '0', 'COUNT', '1'] @@ -31,7 +31,7 @@ describe('SCAN', () => { it('with TYPE', () => { assert.deepEqual( - SCAN.transformArguments(0, { + SCAN.transformArguments('0', { TYPE: 'stream' }), ['SCAN', '0', 'TYPE', 'stream'] @@ -40,7 +40,7 @@ describe('SCAN', () => { it('with MATCH & COUNT & TYPE', () => { assert.deepEqual( - SCAN.transformArguments(0, { + SCAN.transformArguments('0', { MATCH: 'pattern', COUNT: 1, TYPE: 'stream' @@ -52,9 +52,9 @@ describe('SCAN', () => { testUtils.testAll('scan', async client => { assert.deepEqual( - await client.scan(0), + await client.scan('0'), { - cursor: 0, + cursor: '0', keys: [] } ); diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index da64a7969ef..b8db505b00e 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -7,7 +7,7 @@ export interface ScanCommonOptions { export function pushScanArguments( args: CommandArguments, - cursor: number, + cursor: RedisArgument, options?: ScanOptions ): CommandArguments { args.push(cursor.toString()); @@ -30,7 +30,7 @@ export interface ScanOptions extends ScanCommonOptions { export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(cursor: number, options?: ScanOptions) { + transformArguments(cursor: string, options?: ScanOptions) { const args = pushScanArguments(['SCAN'], cursor, options); if (options?.TYPE) { @@ -41,7 +41,7 @@ export default { }, transformReply([cursor, keys]: [BlobStringReply, ArrayReply]) { return { - cursor: Number(cursor), + cursor, keys }; } diff --git a/packages/client/lib/commands/SSCAN.spec.ts b/packages/client/lib/commands/SSCAN.spec.ts index 3fe9edec8c2..2b394511f56 100644 --- a/packages/client/lib/commands/SSCAN.spec.ts +++ b/packages/client/lib/commands/SSCAN.spec.ts @@ -6,14 +6,14 @@ describe('SSCAN', () => { describe('transformArguments', () => { it('cusror only', () => { assert.deepEqual( - SSCAN.transformArguments('key', 0), + SSCAN.transformArguments('key', '0'), ['SSCAN', 'key', '0'] ); }); it('with MATCH', () => { assert.deepEqual( - SSCAN.transformArguments('key', 0, { + SSCAN.transformArguments('key', '0', { MATCH: 'pattern' }), ['SSCAN', 'key', '0', 'MATCH', 'pattern'] @@ -22,7 +22,7 @@ describe('SSCAN', () => { it('with COUNT', () => { assert.deepEqual( - SSCAN.transformArguments('key', 0, { + SSCAN.transformArguments('key', '0', { COUNT: 1 }), ['SSCAN', 'key', '0', 'COUNT', '1'] @@ -31,7 +31,7 @@ describe('SSCAN', () => { it('with MATCH & COUNT', () => { assert.deepEqual( - SSCAN.transformArguments('key', 0, { + SSCAN.transformArguments('key', '0', { MATCH: 'pattern', COUNT: 1 }), @@ -42,9 +42,9 @@ describe('SSCAN', () => { testUtils.testAll('sScan', async client => { assert.deepEqual( - await client.sScan('key', 0), + await client.sScan('key', '0'), { - cursor: 0, + cursor: '0', members: [] } ); diff --git a/packages/client/lib/commands/SSCAN.ts b/packages/client/lib/commands/SSCAN.ts index c36bc52ca1e..f47144d834c 100644 --- a/packages/client/lib/commands/SSCAN.ts +++ b/packages/client/lib/commands/SSCAN.ts @@ -6,14 +6,14 @@ export default { IS_READ_ONLY: true, transformArguments( key: RedisArgument, - cursor: number, + cursor: RedisArgument, options?: ScanCommonOptions ) { return pushScanArguments(['SSCAN', key], cursor, options); }, transformReply([cursor, members]: [BlobStringReply, Array]) { return { - cursor: Number(cursor), + cursor, members }; } diff --git a/packages/client/lib/commands/ZSCAN.spec.ts b/packages/client/lib/commands/ZSCAN.spec.ts index f420fc0806a..d4d5f565465 100644 --- a/packages/client/lib/commands/ZSCAN.spec.ts +++ b/packages/client/lib/commands/ZSCAN.spec.ts @@ -6,14 +6,14 @@ describe('ZSCAN', () => { describe('transformArguments', () => { it('cusror only', () => { assert.deepEqual( - ZSCAN.transformArguments('key', 0), + ZSCAN.transformArguments('key', '0'), ['ZSCAN', 'key', '0'] ); }); it('with MATCH', () => { assert.deepEqual( - ZSCAN.transformArguments('key', 0, { + ZSCAN.transformArguments('key', '0', { MATCH: 'pattern' }), ['ZSCAN', 'key', '0', 'MATCH', 'pattern'] @@ -22,7 +22,7 @@ describe('ZSCAN', () => { it('with COUNT', () => { assert.deepEqual( - ZSCAN.transformArguments('key', 0, { + ZSCAN.transformArguments('key', '0', { COUNT: 1 }), ['ZSCAN', 'key', '0', 'COUNT', '1'] @@ -31,7 +31,7 @@ describe('ZSCAN', () => { it('with MATCH & COUNT', () => { assert.deepEqual( - ZSCAN.transformArguments('key', 0, { + ZSCAN.transformArguments('key', '0', { MATCH: 'pattern', COUNT: 1 }), @@ -42,9 +42,9 @@ describe('ZSCAN', () => { testUtils.testWithClient('zScan', async client => { assert.deepEqual( - await client.zScan('key', 0), + await client.zScan('key', '0'), { - cursor: 0, + cursor: '0', members: [] } ); diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index 1938e67da24..68186afc0e0 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -12,14 +12,14 @@ export default { IS_READ_ONLY: true, transformArguments( key: RedisArgument, - cursor: number, + cursor: RedisArgument, options?: ScanCommonOptions ) { return pushScanArguments(['ZSCAN', key], cursor, options); }, transformReply([cursor, rawMembers]: [BlobStringReply, ArrayReply]) { return { - cursor: Number(cursor), + cursor, members: transformSortedSetReply[2](rawMembers) }; } From 926ce510ddec584d91231a7c011f51a6fc622bea Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:11:04 -0400 Subject: [PATCH 171/325] fix for 6ca420f15e91f3214c34355c78d585b6585ffa87 - fix cursor, add tests --- packages/client/lib/client/index.spec.ts | 129 ++++++++++++----------- packages/client/lib/client/index.ts | 18 ++-- 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 7a259720ef4..5efcdb2aa00 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -11,6 +11,7 @@ import { once } from 'events'; // import { promisify } from 'util'; import { MATH_FUNCTION, loadMathFunction } from '../commands/FUNCTION_LOAD.spec'; import { RESP_TYPES } from '../RESP/decoder'; +import { SortedSetMember } from '../commands/generic-transformers'; export const SQUARE_SCRIPT = defineScript({ SCRIPT: 'return ARGV[1] * ARGV[1];', @@ -435,84 +436,84 @@ describe('Client', () => { // return client.executeIsolated(isolated => killClient(isolated, client)); // }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('scanIterator', async client => { -// const promises = [], -// keys = new Set(); -// for (let i = 0; i < 100; i++) { -// const key = i.toString(); -// keys.add(key); -// promises.push(client.set(key, '')); -// } - -// await Promise.all(promises); - -// const results = new Set(); -// for await (const key of client.scanIterator()) { -// results.add(key); -// } - -// assert.deepEqual(keys, results); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('scanIterator', async client => { + const promises = [], + keys = new Set(); + for (let i = 0; i < 100; i++) { + const key = i.toString(); + keys.add(key); + promises.push(client.set(key, '')); + } -// testUtils.testWithClient('hScanIterator', async client => { -// const hash: Record = {}; -// for (let i = 0; i < 100; i++) { -// hash[i.toString()] = i.toString(); -// } + await Promise.all(promises); -// await client.hSet('key', hash); + const results = new Set(); + for await (const keys of client.scanIterator()) { + results.add(...keys); + } -// const results: Record = {}; -// for await (const { field, value } of client.hScanIterator('key')) { -// results[field] = value; -// } + assert.deepEqual(keys, results); + }, GLOBAL.SERVERS.OPEN); -// assert.deepEqual(hash, results); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('hScanIterator', async client => { + const hash: Record = {}; + for (let i = 0; i < 100; i++) { + hash[i.toString()] = i.toString(); + } -// testUtils.testWithClient('sScanIterator', async client => { -// const members = new Set(); -// for (let i = 0; i < 100; i++) { -// members.add(i.toString()); -// } + await client.hSet('key', hash); -// await client.sAdd('key', Array.from(members)); + const results: Record = {}; + for await (const entries of client.hScanIterator('key')) { + for (const [field, value] of entries) { + results[field] = value; + } + } -// const results = new Set(); -// for await (const key of client.sScanIterator('key')) { -// results.add(key); -// } + assert.deepEqual(hash, results); + }, GLOBAL.SERVERS.OPEN); -// assert.deepEqual(members, results); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('sScanIterator', async client => { + const members = new Set(); + for (let i = 0; i < 100; i++) { + members.add(i.toString()); + } -// testUtils.testWithClient('zScanIterator', async client => { -// const members = []; -// for (let i = 0; i < 100; i++) { -// members.push({ -// score: 1, -// value: i.toString() -// }); -// } + await client.sAdd('key', Array.from(members)); -// await client.zAdd('key', members); + const results = new Set(); + for await (const members of client.sScanIterator('key')) { + for (const member of members) { + results.add(member); + } + } -// const map = new Map(); -// for await (const member of client.zScanIterator('key')) { -// map.set(member.value, member.score); -// } + assert.deepEqual(members, results); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('zScanIterator', async client => { + const members: Array = [], + map = new Map(); + for (let i = 0; i < 100; i++) { + const member = { + value: i.toString(), + score: 1 + }; + map.set(member.value, member.score); + members.push(member); + } -// type MemberTuple = [string, number]; + await client.zAdd('key', members); -// function sort(a: MemberTuple, b: MemberTuple) { -// return Number(b[0]) - Number(a[0]); -// } + const results = new Map(); + for await (const members of client.zScanIterator('key')) { + for (const { value, score } of members) { + results.set(value, score); + } + } -// assert.deepEqual( -// [...map.entries()].sort(sort), -// members.map(member => [member.value, member.score]).sort(sort) -// ); -// }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(members, results); + }, GLOBAL.SERVERS.OPEN); // describe('PubSub', () => { // testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index d53f8bec604..5a96388b4df 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -141,7 +141,7 @@ type ProxyClient = RedisClient; type NamespaceProxyClient = { self: ProxyClient }; interface ScanIteratorOptions { - cursor?: number; + cursor?: RedisArgument; } export default class RedisClient< @@ -799,12 +799,12 @@ export default class RedisClient< this: RedisClientType, options?: ScanOptions & ScanIteratorOptions ) { - let cursor = options?.cursor ?? 0; + let cursor = options?.cursor ?? '0'; do { const reply = await this.scan(cursor, options); cursor = reply.cursor; yield reply.keys; - } while (cursor !== 0); + } while (cursor !== '0'); } async* hScanIterator( @@ -812,12 +812,12 @@ export default class RedisClient< key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { - let cursor = options?.cursor ?? 0; + let cursor = options?.cursor ?? '0'; do { const reply = await this.hScan(key, cursor, options); cursor = reply.cursor; yield reply.entries; - } while (cursor !== 0); + } while (cursor !== '0'); } async* sScanIterator( @@ -825,12 +825,12 @@ export default class RedisClient< key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { - let cursor = options?.cursor ?? 0; + let cursor = options?.cursor ?? '0'; do { const reply = await this.sScan(key, cursor, options); cursor = reply.cursor; yield reply.members; - } while (cursor !== 0); + } while (cursor !== '0'); } async* zScanIterator( @@ -838,12 +838,12 @@ export default class RedisClient< key: RedisArgument, options?: ScanCommonOptions & ScanIteratorOptions ) { - let cursor = options?.cursor ?? 0; + let cursor = options?.cursor ?? '0'; do { const reply = await this.zScan(key, cursor, options); cursor = reply.cursor; yield reply.members; - } while (cursor !== 0); + } while (cursor !== '0'); } /** From cffefd03377e7227bc4adb36c85114b67c58995d Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:12:37 -0400 Subject: [PATCH 172/325] fix SCAN --- packages/client/lib/commands/SCAN.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/SCAN.ts b/packages/client/lib/commands/SCAN.ts index b8db505b00e..13f54440443 100644 --- a/packages/client/lib/commands/SCAN.ts +++ b/packages/client/lib/commands/SCAN.ts @@ -30,7 +30,7 @@ export interface ScanOptions extends ScanCommonOptions { export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, - transformArguments(cursor: string, options?: ScanOptions) { + transformArguments(cursor: RedisArgument, options?: ScanOptions) { const args = pushScanArguments(['SCAN'], cursor, options); if (options?.TYPE) { From 172d32923456c6c5a4d6581e5cec5004cbb31b1f Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:37:56 -0400 Subject: [PATCH 173/325] fix scan iterators --- docs/scan-iterators.md | 2 +- packages/client/lib/client/index.spec.ts | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/scan-iterators.md b/docs/scan-iterators.md index f8e317fcef7..ead3a346a2e 100644 --- a/docs/scan-iterators.md +++ b/docs/scan-iterators.md @@ -22,7 +22,7 @@ You can override the default options by providing a configuration object: ```typescript client.scanIterator({ - cursor: 0, // 0 by default + cursor: '0', // optional, defaults to '0' TYPE: 'string', // `SCAN` only MATCH: 'patter*', COUNT: 100 diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 5efcdb2aa00..0312aa9d0c3 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -437,19 +437,21 @@ describe('Client', () => { // }, GLOBAL.SERVERS.OPEN); testUtils.testWithClient('scanIterator', async client => { - const promises = [], - keys = new Set(); + const entries: Array = [], + keys = new Set(); for (let i = 0; i < 100; i++) { const key = i.toString(); keys.add(key); - promises.push(client.set(key, '')); + entries.push(key, ''); } - await Promise.all(promises); + await client.mSet(entries); const results = new Set(); for await (const keys of client.scanIterator()) { - results.add(...keys); + for (const key of keys) { + results.add(key); + } } assert.deepEqual(keys, results); @@ -465,7 +467,7 @@ describe('Client', () => { const results: Record = {}; for await (const entries of client.hScanIterator('key')) { - for (const [field, value] of entries) { + for (const { field, value } of entries) { results[field] = value; } } @@ -512,7 +514,7 @@ describe('Client', () => { } } - assert.deepEqual(members, results); + assert.deepEqual(map, results); }, GLOBAL.SERVERS.OPEN); // describe('PubSub', () => { From 0614f909a0758aef7ebde518ba3e787c5a37ad68 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 11:52:44 -0400 Subject: [PATCH 174/325] fix XINFO GROUPS test --- packages/client/lib/commands/XINFO_GROUPS.spec.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/client/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts index 20dfb148044..59326898a5f 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -25,10 +25,8 @@ describe('XINFO GROUPS', () => { consumers: 0, pending: 0, 'last-delivered-id': '0-0', - ...testUtils.isVersionGreaterThan([7, 0]) && { - 'entries-read': null, - lag: 0 - } + 'entries-read': testUtils.isVersionGreaterThan([7, 0]) ? null : undefined, + lag: testUtils.isVersionGreaterThan([7, 0]) ? 0 : undefined }] ); }, { From 1b363624d85d6dfe6dfd76b5ac173d32e8add8a2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 12:00:15 -0400 Subject: [PATCH 175/325] fix XPENDING_RANGE test --- packages/client/lib/commands/XPENDING_RANGE.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index 7fd2ae0b427..586914d7b4e 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -41,7 +41,7 @@ describe('XPENDING RANGE', () => { }); testUtils.testAll('xPendingRange', async client => { - const [, , id, reply] = await Promise.all([ + const [, id, , reply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), From 5bd6141b22a092e6469743406d61a9eab2faa65a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 12:10:03 -0400 Subject: [PATCH 176/325] wip --- packages/bloom/lib/commands/bloom/index.ts | 2 +- .../lib/commands/count-min-sketch/index.ts | 2 +- packages/bloom/lib/commands/cuckoo/index.ts | 3 +- packages/bloom/lib/commands/index.ts | 2 +- .../bloom/lib/commands/t-digest/BYRANK.ts | 4 +- packages/bloom/lib/commands/t-digest/CDF.ts | 4 +- .../bloom/lib/commands/t-digest/QUANTILE.ts | 4 +- packages/bloom/lib/commands/t-digest/index.ts | 3 +- packages/bloom/lib/commands/top-k/index.ts | 3 +- .../client/lib/commands/CLIENT_TRACKING.ts | 3 +- packages/client/lib/commands/index.ts | 1947 ++++++----------- 11 files changed, 662 insertions(+), 1315 deletions(-) diff --git a/packages/bloom/lib/commands/bloom/index.ts b/packages/bloom/lib/commands/bloom/index.ts index 1e87c8bd455..c29039d2d46 100644 --- a/packages/bloom/lib/commands/bloom/index.ts +++ b/packages/bloom/lib/commands/bloom/index.ts @@ -42,4 +42,4 @@ export default { reserve: RESERVE as RESERVE, SCANDUMP: SCANDUMP as SCANDUMP, scanDump: SCANDUMP as SCANDUMP -} satisfies RedisCommands; +} as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/count-min-sketch/index.ts b/packages/bloom/lib/commands/count-min-sketch/index.ts index 3a2dfa40ac5..cac390ba980 100644 --- a/packages/bloom/lib/commands/count-min-sketch/index.ts +++ b/packages/bloom/lib/commands/count-min-sketch/index.ts @@ -26,4 +26,4 @@ export default { merge: MERGE as MERGE, QUERY: QUERY as QUERY, query: QUERY as QUERY, -} satisfies RedisCommands; +} as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/cuckoo/index.ts b/packages/bloom/lib/commands/cuckoo/index.ts index 2609ea1651d..b76a01032af 100644 --- a/packages/bloom/lib/commands/cuckoo/index.ts +++ b/packages/bloom/lib/commands/cuckoo/index.ts @@ -1,3 +1,4 @@ +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import ADDNX from './ADDNX'; import COUNT from './COUNT'; @@ -45,4 +46,4 @@ export default { reserve: RESERVE as RESERVE, SCANDUMP: SCANDUMP as SCANDUMP, scanDump: SCANDUMP as SCANDUMP -}; +} as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/index.ts b/packages/bloom/lib/commands/index.ts index f1a1afd6923..6f91089460a 100644 --- a/packages/bloom/lib/commands/index.ts +++ b/packages/bloom/lib/commands/index.ts @@ -11,4 +11,4 @@ export default { cf, tDigest, topK -} satisfies RedisModules; +} as const satisfies RedisModules; diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.ts b/packages/bloom/lib/commands/t-digest/BYRANK.ts index 88e0cb6c7c8..8b48acd1b1b 100644 --- a/packages/bloom/lib/commands/t-digest/BYRANK.ts +++ b/packages/bloom/lib/commands/t-digest/BYRANK.ts @@ -1,5 +1,5 @@ import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; export function transformByRankArguments( command: RedisArgument, @@ -19,6 +19,6 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments: transformByRankArguments.bind(undefined, 'TDIGEST.BYRANK'), - transformReply: transformArrayDoubleReply + transformReply: transformDoubleArrayReply } as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/CDF.ts b/packages/bloom/lib/commands/t-digest/CDF.ts index ccc6d2c2b46..0fbdedb3a47 100644 --- a/packages/bloom/lib/commands/t-digest/CDF.ts +++ b/packages/bloom/lib/commands/t-digest/CDF.ts @@ -1,5 +1,5 @@ import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: transformArrayDoubleReply + transformReply: transformDoubleArrayReply } as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.ts index 6beda56f775..f7057a37d1c 100644 --- a/packages/bloom/lib/commands/t-digest/QUANTILE.ts +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.ts @@ -1,5 +1,5 @@ import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -import { transformArrayDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformDoubleArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { FIRST_KEY_INDEX: 1, @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: transformArrayDoubleReply + transformReply: transformDoubleArrayReply } as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/index.ts b/packages/bloom/lib/commands/t-digest/index.ts index 70234d450b7..161f832a4dc 100644 --- a/packages/bloom/lib/commands/t-digest/index.ts +++ b/packages/bloom/lib/commands/t-digest/index.ts @@ -1,3 +1,4 @@ +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import BYRANK from './BYRANK'; import BYREVRANK from './BYREVRANK'; @@ -57,4 +58,4 @@ export default { revRank: REVRANK as REVRANK, TRIMMED_MEAN: TRIMMED_MEAN as TRIMMED_MEAN, trimmedMean: TRIMMED_MEAN as TRIMMED_MEAN -}; +} as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/top-k/index.ts b/packages/bloom/lib/commands/top-k/index.ts index 87394839f63..0f3b17c523f 100644 --- a/packages/bloom/lib/commands/top-k/index.ts +++ b/packages/bloom/lib/commands/top-k/index.ts @@ -1,3 +1,4 @@ +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import COUNT from './COUNT'; import INCRBY from './INCRBY'; @@ -33,4 +34,4 @@ export default { query: QUERY as QUERY, RESERVE: RESERVE as RESERVE, reserve: RESERVE as RESERVE -}; +} as const satisfies RedisCommands; diff --git a/packages/client/lib/commands/CLIENT_TRACKING.ts b/packages/client/lib/commands/CLIENT_TRACKING.ts index 5eebb8492ac..a783ce35894 100644 --- a/packages/client/lib/commands/CLIENT_TRACKING.ts +++ b/packages/client/lib/commands/CLIENT_TRACKING.ts @@ -1,5 +1,6 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { RedisVariadicArgument } from './generic-transformers'; + interface CommonOptions { REDIRECT?: number; NOLOOP?: boolean; @@ -18,7 +19,7 @@ interface OptOutOptions { OPTOUT?: boolean; } -type ClientTrackingOptions = CommonOptions & ( +export type ClientTrackingOptions = CommonOptions & ( BroadcastOptions | OptInOptions | OptOutOptions diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index efba9ad94a4..c848b7ba583 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -1,3 +1,4 @@ +import type { RedisCommands } from '../RESP/types'; import ACL_CAT from './ACL_CAT'; import ACL_DELUSER from './ACL_DELUSER'; import ACL_DRYRUN from './ACL_DRYRUN'; @@ -324,7 +325,6 @@ import ZSCORE from './ZSCORE'; import ZUNION_WITHSCORES from './ZUNION_WITHSCORES'; import ZUNION from './ZUNION'; import ZUNIONSTORE from './ZUNIONSTORE'; -import { Command } from '../RESP/types'; type ACL_CAT = typeof import('./ACL_CAT').default; type ACL_DELUSER = typeof import('./ACL_DELUSER').default; @@ -653,1316 +653,659 @@ type ZUNION_WITHSCORES = typeof import('./ZUNION_WITHSCORES').default; type ZUNION = typeof import('./ZUNION').default; type ZUNIONSTORE = typeof import('./ZUNIONSTORE').default; -type Commands = { - ACL_CAT: ACL_CAT; - aclCat: ACL_CAT; - ACL_DELUSER: ACL_DELUSER; - aclDelUser: ACL_DELUSER; - ACL_DRYRUN: ACL_DRYRUN; - aclDryRun: ACL_DRYRUN; - ACL_GENPASS: ACL_GENPASS; - aclGenPass: ACL_GENPASS; - ACL_GETUSER: ACL_GETUSER; - aclGetUser: ACL_GETUSER; - ACL_LIST: ACL_LIST; - aclList: ACL_LIST; - ACL_LOAD: ACL_LOAD; - aclLoad: ACL_LOAD; - ACL_LOG_RESET: ACL_LOG_RESET; - aclLogReset: ACL_LOG_RESET; - ACL_LOG: ACL_LOG; - aclLog: ACL_LOG; - ACL_SAVE: ACL_SAVE; - aclSave: ACL_SAVE; - ACL_SETUSER: ACL_SETUSER; - aclSetUser: ACL_SETUSER; - ACL_USERS: ACL_USERS; - aclUsers: ACL_USERS; - ACL_WHOAMI: ACL_WHOAMI; - aclWhoAmI: ACL_WHOAMI; - APPEND: APPEND; - append: APPEND; - ASKING: ASKING; - asking: ASKING; - AUTH: AUTH; - auth: AUTH; - BGREWRITEAOF: BGREWRITEAOF; - bgRewriteAof: BGREWRITEAOF; - BGSAVE: BGSAVE; - bgSave: BGSAVE; - BITCOUNT: BITCOUNT; - bitCount: BITCOUNT; - BITFIELD_RO: BITFIELD_RO; - bitFieldRo: BITFIELD_RO; - BITFIELD: BITFIELD; - bitField: BITFIELD; - BITOP: BITOP; - bitOp: BITOP; - BITPOS: BITPOS; - bitPos: BITPOS; - BLMOVE: BLMOVE; - blMove: BLMOVE; - BLMPOP: BLMPOP; - blmPop: BLMPOP; - BLPOP: BLPOP; - blPop: BLPOP; - BRPOP: BRPOP; - brPop: BRPOP; - BRPOPLPUSH: BRPOPLPUSH; - brPopLPush: BRPOPLPUSH; - BZMPOP: BZMPOP; - bzmPop: BZMPOP; - BZPOPMAX: BZPOPMAX; - bzPopMax: BZPOPMAX; - BZPOPMIN: BZPOPMIN; - bzPopMin: BZPOPMIN; - CLIENT_CACHING: CLIENT_CACHING; - clientCaching: CLIENT_CACHING; - CLIENT_GETNAME: CLIENT_GETNAME; - clientGetName: CLIENT_GETNAME; - CLIENT_GETREDIR: CLIENT_GETREDIR; - clientGetRedir: CLIENT_GETREDIR; - CLIENT_ID: CLIENT_ID; - clientId: CLIENT_ID; - CLIENT_INFO: CLIENT_INFO; - clientInfo: CLIENT_INFO; - CLIENT_KILL: CLIENT_KILL; - clientKill: CLIENT_KILL; - CLIENT_LIST: CLIENT_LIST; - clientList: CLIENT_LIST; - 'CLIENT_NO-EVICT': CLIENT_NO_EVICT; - clientNoEvict: CLIENT_NO_EVICT; - CLIENT_PAUSE: CLIENT_PAUSE; - clientPause: CLIENT_PAUSE; - CLIENT_SETNAME: CLIENT_SETNAME; - clientSetName: CLIENT_SETNAME; - CLIENT_TRACKING: CLIENT_TRACKING; - clientTracking: CLIENT_TRACKING; - CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO; - clientTrackingInfo: CLIENT_TRACKINGINFO; - CLIENT_UNPAUSE: CLIENT_UNPAUSE; - clientUnpause: CLIENT_UNPAUSE; - CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS; - clusterAddSlots: CLUSTER_ADDSLOTS; - CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE; - clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE; - CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH; - clusterBumpEpoch: CLUSTER_BUMPEPOCH; - 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS; - clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS; - CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT; - clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT; - CLUSTER_DELSLOTS: CLUSTER_DELSLOTS; - clusterDelSlots: CLUSTER_DELSLOTS; - CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE; - clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE; - CLUSTER_FAILOVER: CLUSTER_FAILOVER; - clusterFailover: CLUSTER_FAILOVER; - CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS; - clusterFlushSlots: CLUSTER_FLUSHSLOTS; - CLUSTER_FORGET: CLUSTER_FORGET; - clusterForget: CLUSTER_FORGET; - CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT; - clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT; - // CLUSTER_INFO: CLUSTER_INFO; - // clusterInfo: CLUSTER_INFO; - CLUSTER_KEYSLOT: CLUSTER_KEYSLOT; - clusterKeySlot: CLUSTER_KEYSLOT; - CLUSTER_LINKS: CLUSTER_LINKS; - clusterLinks: CLUSTER_LINKS; - CLUSTER_MEET: CLUSTER_MEET; - clusterMeet: CLUSTER_MEET; - CLUSTER_MYID: CLUSTER_MYID; - clusterMyId: CLUSTER_MYID; - // CLUSTER_NODES: CLUSTER_NODES; - // clusterNodes: CLUSTER_NODES; - // CLUSTER_REPLICAS: CLUSTER_REPLICAS; - // clusterReplicas: CLUSTER_REPLICAS; - CLUSTER_REPLICATE: CLUSTER_REPLICATE; - clusterReplicate: CLUSTER_REPLICATE; - CLUSTER_RESET: CLUSTER_RESET; - clusterReset: CLUSTER_RESET; - CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG; - clusterSaveConfig: CLUSTER_SAVECONFIG; - 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH; - clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH; - CLUSTER_SETSLOT: CLUSTER_SETSLOT; - clusterSetSlot: CLUSTER_SETSLOT; - CLUSTER_SLOTS: CLUSTER_SLOTS; - clusterSlots: CLUSTER_SLOTS; - COMMAND_COUNT: COMMAND_COUNT; - commandCount: COMMAND_COUNT; - COMMAND_GETKEYS: COMMAND_GETKEYS; - commandGetKeys: COMMAND_GETKEYS; - COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS; - commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS; - // COMMAND_INFO: COMMAND_INFO; - // commandInfo: COMMAND_INFO; - // COMMAND_LIST: COMMAND_LIST; - // commandList: COMMAND_LIST; - // COMMAND: COMMAND; - // command: COMMAND; - CONFIG_GET: CONFIG_GET; - configGet: CONFIG_GET; - CONFIG_RESETASTAT: CONFIG_RESETASTAT; - configResetStat: CONFIG_RESETASTAT; - CONFIG_REWRITE: CONFIG_REWRITE; - configRewrite: CONFIG_REWRITE; - CONFIG_SET: CONFIG_SET; - configSet: CONFIG_SET; - COPY: COPY; - copy: COPY; - DBSIZE: DBSIZE; - dbSize: DBSIZE; - DECR: DECR; - decr: DECR; - DECRBY: DECRBY; - decrBy: DECRBY; - DEL: DEL; - del: DEL; - DUMP: DUMP; - dump: DUMP; - ECHO: ECHO; - echo: ECHO; - EVAL_RO: EVAL_RO; - evalRo: EVAL_RO; - EVAL: EVAL; - eval: EVAL; - EVALSHA_RO: EVALSHA_RO; - evalShaRo: EVALSHA_RO; - EVALSHA: EVALSHA; - evalSha: EVALSHA; - EXISTS: EXISTS; - exists: EXISTS; - EXPIRE: EXPIRE; - expire: EXPIRE; - EXPIREAT: EXPIREAT; - expireAt: EXPIREAT; - EXPIRETIME: EXPIRETIME; - expireTime: EXPIRETIME; - FLUSHALL: FLUSHALL; - flushAll: FLUSHALL; - FLUSHDB: FLUSHDB; - flushDb: FLUSHDB; - FCALL: FCALL; - fCall: FCALL; - FCALL_RO: FCALL_RO; - fCallRo: FCALL_RO; - FUNCTION_DELETE: FUNCTION_DELETE; - functionDelete: FUNCTION_DELETE; - FUNCTION_DUMP: FUNCTION_DUMP; - functionDump: FUNCTION_DUMP; - FUNCTION_FLUSH: FUNCTION_FLUSH; - functionFlush: FUNCTION_FLUSH; - FUNCTION_KILL: FUNCTION_KILL; - functionKill: FUNCTION_KILL; - FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE; - functionListWithCode: FUNCTION_LIST_WITHCODE; - FUNCTION_LIST: FUNCTION_LIST; - functionList: FUNCTION_LIST; - FUNCTION_LOAD: FUNCTION_LOAD; - functionLoad: FUNCTION_LOAD; - FUNCTION_RESTORE: FUNCTION_RESTORE; - functionRestore: FUNCTION_RESTORE; - // FUNCTION_STATS: FUNCTION_STATS; - // functionStats: FUNCTION_STATS; - GEOADD: GEOADD; - geoAdd: GEOADD; - GEODIST: GEODIST; - geoDist: GEODIST; - GEOHASH: GEOHASH; - geoHash: GEOHASH; - GEOPOS: GEOPOS; - geoPos: GEOPOS; - GEORADIUS_RO_WITH: GEORADIUS_RO_WITH; - geoRadiusRoWith: GEORADIUS_RO_WITH; - GEORADIUS_RO: GEORADIUS_RO; - geoRadiusRo: GEORADIUS_RO - GEORADIUS_STORE: GEORADIUS_STORE; - geoRadiusStore: GEORADIUS_STORE; - GEORADIUS_WITH: GEORADIUS_WITH; - geoRadiusWith: GEORADIUS_WITH; - GEORADIUS: GEORADIUS; - geoRadius: GEORADIUS; - GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH; - geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH; - GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO; - geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO; - GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE; - geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE; - GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH; - geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH; - GEORADIUSBYMEMBER: GEORADIUSBYMEMBER; - geoRadiusByMember: GEORADIUSBYMEMBER; - GEOSEARCH_WITH: GEOSEARCH_WITH; - geoSearchWith: GEOSEARCH_WITH; - GEOSEARCH: GEOSEARCH; - geoSearch: GEOSEARCH; - GEOSEARCHSTORE: GEOSEARCHSTORE; - geoSearchStore: GEOSEARCHSTORE; - GET: GET; - get: GET; - GETBIT: GETBIT; - getBit: GETBIT; - GETDEL: GETDEL; - getDel: GETDEL; - GETEX: GETEX; - getEx: GETEX; - GETRANGE: GETRANGE; - getRange: GETRANGE; - GETSET: GETSET; - getSet: GETSET; - HDEL: HDEL; - hDel: HDEL; - HELLO: HELLO; - hello: HELLO; - HEXISTS: HEXISTS; - hExists: HEXISTS; - HGET: HGET; - hGet: HGET; - HGETALL: HGETALL; - hGetAll: HGETALL; - HINCRBY: HINCRBY; - hIncrBy: HINCRBY; - HINCRBYFLOAT: HINCRBYFLOAT; - hIncrByFloat: HINCRBYFLOAT; - HKEYS: HKEYS; - hKeys: HKEYS; - HLEN: HLEN; - hLen: HLEN; - HMGET: HMGET; - hmGet: HMGET; - HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES; - hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES; - HRANDFIELD_COUNT: HRANDFIELD_COUNT; - hRandFieldCount: HRANDFIELD_COUNT; - HRANDFIELD: HRANDFIELD; - hRandField: HRANDFIELD; - HSCAN: HSCAN; - hScan: HSCAN; - HSET: HSET; - hSet: HSET; - HSETNX: HSETNX; - hSetNX: HSETNX; - HSTRLEN: HSTRLEN; - hStrLen: HSTRLEN; - HVALS: HVALS; - hVals: HVALS; - INCR: INCR; - incr: INCR; - INCRBY: INCRBY; - incrBy: INCRBY; - INCRBYFLOAT: INCRBYFLOAT; - incrByFloat: INCRBYFLOAT; - INFO: INFO; - info: INFO; - KEYS: KEYS; - keys: KEYS; - LASTSAVE: LASTSAVE; - lastSave: LASTSAVE; - LATENCY_DOCTOR: LATENCY_DOCTOR; - latencyDoctor: LATENCY_DOCTOR; - LATENCY_GRAPH: LATENCY_GRAPH; - latencyGraph: LATENCY_GRAPH; - LATENCY_LATEST: LATENCY_LATEST; - latencyLatest: LATENCY_LATEST; - LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN; - lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN; - LCS_IDX: LCS_IDX; - lcsIdx: LCS_IDX; - LCS_LEN: LCS_LEN; - lcsLen: LCS_LEN; - LCS: LCS; - lcs: LCS; - LINDEX: LINDEX; - lIndex: LINDEX; - LINSERT: LINSERT; - lInsert: LINSERT; - LLEN: LLEN; - lLen: LLEN; - LMOVE: LMOVE; - lMove: LMOVE; - LMPOP: LMPOP; - lmPop: LMPOP; - LOLWUT: LOLWUT; - LPOP_COUNT: LPOP_COUNT; - lPopCount: LPOP_COUNT; - LPOP: LPOP; - lPop: LPOP; - LPOS_COUNT: LPOS_COUNT; - lPosCount: LPOS_COUNT; - LPOS: LPOS; - lPos: LPOS; - LPUSH: LPUSH; - lPush: LPUSH; - LPUSHX: LPUSHX; - lPushX: LPUSHX; - LRANGE: LRANGE; - lRange: LRANGE; - LREM: LREM; - lRem: LREM; - LSET: LSET; - lSet: LSET; - LTRIM: LTRIM; - lTrim: LTRIM; - MEMORY_DOCTOR: MEMORY_DOCTOR; - memoryDoctor: MEMORY_DOCTOR; - 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS; - memoryMallocStats: MEMORY_MALLOC_STATS; - MEMORY_PURGE: MEMORY_PURGE; - memoryPurge: MEMORY_PURGE; - MEMORY_STATS: MEMORY_STATS; - memoryStats: MEMORY_STATS; - MEMORY_USAGE: MEMORY_USAGE; - memoryUsage: MEMORY_USAGE; - MGET: MGET; - mGet: MGET; - MODULE_LIST: MODULE_LIST; - moduleList: MODULE_LIST; - MODULE_LOAD: MODULE_LOAD; - moduleLoad: MODULE_LOAD; - MODULE_UNLOAD: MODULE_UNLOAD; - moduleUnload: MODULE_UNLOAD; - MOVE: MOVE; - move: MOVE; - MSET: MSET; - mSet: MSET; - MSETNX: MSETNX; - mSetNX: MSETNX; - OBJECT_ENCODING: OBJECT_ENCODING; - objectEncoding: OBJECT_ENCODING; - OBJECT_FREQ: OBJECT_FREQ; - objectFreq: OBJECT_FREQ; - OBJECT_IDLETIME: OBJECT_IDLETIME; - objectIdleTime: OBJECT_IDLETIME; - OBJECT_REFCOUNT: OBJECT_REFCOUNT - objectRefCount: OBJECT_REFCOUNT; - PERSIST: PERSIST; - persist: PERSIST; - PEXPIRE: PEXPIRE; - pExpire: PEXPIRE; - PEXPIREAT: PEXPIREAT; - pExpireAt: PEXPIREAT; - PEXPIRETIME: PEXPIRETIME; - pExpireTime: PEXPIRETIME; - PFADD: PFADD; - pfAdd: PFADD; - PFCOUNT: PFCOUNT; - pfCount: PFCOUNT; - PFMERGE: PFMERGE; - pfMerge: PFMERGE; - PING: PING; - /** - * ping jsdoc - */ - ping: PING; - PSETEX: PSETEX; - pSetEx: PSETEX; - PTTL: PTTL; - pTTL: PTTL; - PUBLISH: PUBLISH; - publish: PUBLISH; - PUBSUB_CHANNELS: PUBSUB_CHANNELS; - pubSubChannels: PUBSUB_CHANNELS; - PUBSUB_NUMPAT: PUBSUB_NUMPAT; - pubSubNumPat: PUBSUB_NUMPAT; - PUBSUB_NUMSUB: PUBSUB_NUMSUB; - pubSubNumSub: PUBSUB_NUMSUB; - PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS; - pubSubShardChannels: PUBSUB_SHARDCHANNELS; - RANDOMKEY: RANDOMKEY; - randomKey: RANDOMKEY; - READONLY: READONLY; - readonly: READONLY; - RENAME: RENAME; - rename: RENAME; - RENAMENX: RENAMENX; - renameNX: RENAMENX; - RPOP_COUNT: RPOP_COUNT; - rPopCount: RPOP_COUNT; - ROLE: ROLE; - role: ROLE; - RPOP: RPOP; - rPop: RPOP; - RPOPLPUSH: RPOPLPUSH; - rPopLPush: RPOPLPUSH; - RPUSH: RPUSH; - rPush: RPUSH; - RPUSHX: RPUSHX; - rPushX: RPUSHX; - SADD: SADD; - sAdd: SADD; - SCAN: SCAN; - scan: SCAN; - SCARD: SCARD; - sCard: SCARD; - SCRIPT_DEBUG: SCRIPT_DEBUG; - scriptDebug: SCRIPT_DEBUG; - SCRIPT_EXISTS: SCRIPT_EXISTS; - scriptExists: SCRIPT_EXISTS; - SCRIPT_FLUSH: SCRIPT_FLUSH; - scriptFlush: SCRIPT_FLUSH; - SCRIPT_KILL: SCRIPT_KILL; - scriptKill: SCRIPT_KILL; - SCRIPT_LOAD: SCRIPT_LOAD; - scriptLoad: SCRIPT_LOAD; - SDIFF: SDIFF; - sDiff: SDIFF; - SDIFFSTORE: SDIFFSTORE; - sDiffStore: SDIFFSTORE; - SET: SET; - set: SET; - SETBIT: SETBIT; - setBit: SETBIT; - SETEX: SETEX; - setEx: SETEX; - SETNX: SETNX; - setNX: SETNX; - SETRANGE: SETRANGE; - setRange: SETRANGE; - SINTER: SINTER; - sInter: SINTER; - SINTERCARD: SINTERCARD; - sInterCard: SINTERCARD; - SINTERSTORE: SINTERSTORE; - sInterStore: SINTERSTORE; - SISMEMBER: SISMEMBER; - sIsMember: SISMEMBER; - SMEMBERS: SMEMBERS; - sMembers: SMEMBERS; - SMISMEMBER: SMISMEMBER; - smIsMember: SMISMEMBER; - SMOVE: SMOVE; - sMove: SMOVE; - SORT_RO: SORT_RO; - sortRo: SORT_RO; - SORT_STORE: SORT_STORE; - sortStore: SORT_STORE; - SORT: SORT; - sort: SORT; - SPOP_COUNT: SPOP_COUNT; - sPopCount: SPOP_COUNT; - SPOP: SPOP; - sPop: SPOP; - SPUBLISH: SPUBLISH; - sPublish: SPUBLISH; - SRANDMEMBER_COUNT: SRANDMEMBER_COUNT; - sRandMemberCount: SRANDMEMBER_COUNT; - SRANDMEMBER: SRANDMEMBER; - sRandMember: SRANDMEMBER; - SREM: SREM; - sRem: SREM; - SSCAN: SSCAN; - sScan: SSCAN; - STRLEN: STRLEN; - strLen: STRLEN; - SUNION: SUNION; - sUnion: SUNION; - SUNIONSTORE: SUNIONSTORE; - sUnionStore: SUNIONSTORE; - SWAPDB: SWAPDB; - swapDb: SWAPDB; - TIME: TIME; - time: TIME; - TOUCH: TOUCH; - touch: TOUCH; - TTL: TTL; - ttl: TTL; - TYPE: TYPE; - type: TYPE; - UNLINK: UNLINK; - unlink: UNLINK; - UNWATCH: UNWATCH; - unwatch: UNWATCH; - WAIT: WAIT; - wait: WAIT; - WATCH: WATCH; - watch: WATCH; - XACK: XACK; - xAck: XACK; - XADD_NOMKSTREAM: XADD_NOMKSTREAM; - xAddNoMkStream: XADD_NOMKSTREAM; - XADD: XADD; - xAdd: XADD; - XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID; - xAutoClaimJustId: XAUTOCLAIM_JUSTID; - XAUTOCLAIM: XAUTOCLAIM; - xAutoClaim: XAUTOCLAIM; - XCLAIM_JUSTID: XCLAIM_JUSTID; - xClaimJustId: XCLAIM_JUSTID; - XCLAIM: XCLAIM; - xClaim: XCLAIM; - XDEL: XDEL; - xDel: XDEL; - XGROUP_CREATE: XGROUP_CREATE; - xGroupCreate: XGROUP_CREATE; - XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER; - xGroupCreateConsumer: XGROUP_CREATECONSUMER; - XGROUP_DELCONSUMER: XGROUP_DELCONSUMER; - xGroupDelConsumer: XGROUP_DELCONSUMER; - XGROUP_DESTROY: XGROUP_DESTROY; - xGroupDestroy: XGROUP_DESTROY; - XGROUP_SETID: XGROUP_SETID; - xGroupSetId: XGROUP_SETID; - XINFO_CONSUMERS: XINFO_CONSUMERS; - xInfoConsumers: XINFO_CONSUMERS; - XINFO_GROUPS: XINFO_GROUPS; - xInfoGroups: XINFO_GROUPS; - XINFO_STREAM: XINFO_STREAM; - xInfoStream: XINFO_STREAM; - XLEN: XLEN; - xLen: XLEN; - XPENDING_RANGE: XPENDING_RANGE; - xPendingRange: XPENDING_RANGE; - XPENDING: XPENDING; - xPending: XPENDING; - XRANGE: XRANGE; - xRange: XRANGE; - XREAD: XREAD; - xRead: XREAD; - XREADGROUP: XREADGROUP; - xReadGroup: XREADGROUP; - XREVRANGE: XREVRANGE; - xRevRange: XREVRANGE; - XSETID: XSETID; - xSetId: XSETID; - XTRIM: XTRIM; - xTrim: XTRIM; - ZADD_INCR: ZADD_INCR; - zAddIncr: ZADD_INCR; - ZADD: ZADD; - zAdd: ZADD; - ZCARD: ZCARD; - zCard: ZCARD; - ZCOUNT: ZCOUNT; - zCount: ZCOUNT; - ZDIFF_WITHSCORES: ZDIFF_WITHSCORES; - zDiffWithScores: ZDIFF_WITHSCORES; - ZDIFF: ZDIFF; - zDiff: ZDIFF; - ZDIFFSTORE: ZDIFFSTORE; - zDiffStore: ZDIFFSTORE; - ZINCRBY: ZINCRBY; - zIncrBy: ZINCRBY; - ZINTER_WITHSCORES: ZINTER_WITHSCORES; - zInterWithScores: ZINTER_WITHSCORES; - ZINTER: ZINTER; - zInter: ZINTER; - ZINTERCARD: ZINTERCARD; - zInterCard: ZINTERCARD; - ZINTERSTORE: ZINTERSTORE; - zInterStore: ZINTERSTORE; - ZLEXCOUNT: ZLEXCOUNT; - zLexCount: ZLEXCOUNT; - ZMPOP: ZMPOP; - zmPop: ZMPOP; - ZMSCORE: ZMSCORE; - zmScore: ZMSCORE; - ZPOPMAX_COUNT: ZPOPMAX_COUNT; - zPopMaxCount: ZPOPMAX_COUNT; - ZPOPMAX: ZPOPMAX; - zPopMax: ZPOPMAX; - ZPOPMIN_COUNT: ZPOPMIN_COUNT; - zPopMinCount: ZPOPMIN_COUNT; - ZPOPMIN: ZPOPMIN; - zPopMin: ZPOPMIN; - ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES; - zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES; - ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT; - zRandMemberCount: ZRANDMEMBER_COUNT; - ZRANDMEMBER: ZRANDMEMBER; - zRandMember: ZRANDMEMBER; - ZRANGE_WITHSCORES: ZRANGE_WITHSCORES; - zRangeWithScores: ZRANGE_WITHSCORES; - ZRANGE: ZRANGE; - zRange: ZRANGE; - ZRANGEBYLEX: ZRANGEBYLEX; - zRangeByLex: ZRANGEBYLEX; - ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES; - zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES; - ZRANGEBYSCORE: ZRANGEBYSCORE; - zRangeByScore: ZRANGEBYSCORE; - ZRANGESTORE: ZRANGESTORE; - zRangeStore: ZRANGESTORE; - ZRANK_WITHSCORE: ZRANK_WITHSCORE; - zRankWithScore: ZRANK_WITHSCORE; - ZRANK: ZRANK; - zRank: ZRANK; - ZREM: ZREM; - zRem: ZREM; - ZREMRANGEBYLEX: ZREMRANGEBYLEX; - zRemRangeByLex: ZREMRANGEBYLEX; - ZREMRANGEBYRANK: ZREMRANGEBYRANK; - zRemRangeByRank: ZREMRANGEBYRANK; - ZREMRANGEBYSCORE: ZREMRANGEBYSCORE; - zRemRangeByScore: ZREMRANGEBYSCORE; - ZREVRANK: ZREVRANK; - zRevRank: ZREVRANK; - ZSCAN: ZSCAN; - zScan: ZSCAN; - ZSCORE: ZSCORE; - zScore: ZSCORE; - ZUNION_WITHSCORES: ZUNION_WITHSCORES; - zUnionWithScores: ZUNION_WITHSCORES; - ZUNION: ZUNION; - zUnion: ZUNION; - ZUNIONSTORE: ZUNIONSTORE; - zUnionStore: ZUNIONSTORE; -}; - export default { - ACL_CAT, - aclCat: ACL_CAT, - ACL_DELUSER, - aclDelUser: ACL_DELUSER, - ACL_DRYRUN, - aclDryRun: ACL_DRYRUN, - ACL_GENPASS, - aclGenPass: ACL_GENPASS, - ACL_GETUSER, - aclGetUser: ACL_GETUSER, - ACL_LIST, - aclList: ACL_LIST, - ACL_LOAD, - aclLoad: ACL_LOAD, - ACL_LOG_RESET, - aclLogReset: ACL_LOG_RESET, - ACL_LOG, - aclLog: ACL_LOG, - ACL_SAVE, - aclSave: ACL_SAVE, - ACL_SETUSER, - aclSetUser: ACL_SETUSER, - ACL_USERS, - aclUsers: ACL_USERS, - ACL_WHOAMI, - aclWhoAmI: ACL_WHOAMI, - APPEND, - append: APPEND, - ASKING, - asking: ASKING, - AUTH, - auth: AUTH, - BGREWRITEAOF, - bgRewriteAof: BGREWRITEAOF, - BGSAVE, - bgSave: BGSAVE, - BITCOUNT, - bitCount: BITCOUNT, - BITFIELD_RO, - bitFieldRo: BITFIELD_RO, - BITFIELD, - bitField: BITFIELD, - BITOP, - bitOp: BITOP, - BITPOS, - bitPos: BITPOS, - BLMOVE, - blMove: BLMOVE, - BLMPOP, - blmPop: BLMPOP, - BLPOP, - blPop: BLPOP, - BRPOP, - brPop: BRPOP, - BRPOPLPUSH, - brPopLPush: BRPOPLPUSH, - BZMPOP, - bzmPop: BZMPOP, - BZPOPMAX, - bzPopMax: BZPOPMAX, - BZPOPMIN, - bzPopMin: BZPOPMIN, - CLIENT_CACHING, - clientCaching: CLIENT_CACHING, - CLIENT_GETNAME, - clientGetName: CLIENT_GETNAME, - CLIENT_GETREDIR, - clientGetRedir: CLIENT_GETREDIR, - CLIENT_ID, - clientId: CLIENT_ID, - CLIENT_INFO, - clientInfo: CLIENT_INFO, - CLIENT_KILL, - clientKill: CLIENT_KILL, - CLIENT_LIST, - clientList: CLIENT_LIST, - 'CLIENT_NO-EVICT': CLIENT_NO_EVICT, - clientNoEvict: CLIENT_NO_EVICT, - CLIENT_PAUSE, - clientPause: CLIENT_PAUSE, - CLIENT_SETNAME, - clientSetName: CLIENT_SETNAME, - CLIENT_TRACKING, - clientTracking: CLIENT_TRACKING, - CLIENT_TRACKINGINFO, - clientTrackingInfo: CLIENT_TRACKINGINFO, - CLIENT_UNPAUSE, - clientUnpause: CLIENT_UNPAUSE, - CLUSTER_ADDSLOTS, - clusterAddSlots: CLUSTER_ADDSLOTS, - CLUSTER_ADDSLOTSRANGE, - clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE, - CLUSTER_BUMPEPOCH, - clusterBumpEpoch: CLUSTER_BUMPEPOCH, - 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS, - clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS, - CLUSTER_COUNTKEYSINSLOT, - clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT, - CLUSTER_DELSLOTS, - clusterDelSlots: CLUSTER_DELSLOTS, - CLUSTER_DELSLOTSRANGE, - clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE, - CLUSTER_FAILOVER, - clusterFailover: CLUSTER_FAILOVER, - CLUSTER_FLUSHSLOTS, - clusterFlushSlots: CLUSTER_FLUSHSLOTS, - CLUSTER_FORGET, - clusterForget: CLUSTER_FORGET, - CLUSTER_GETKEYSINSLOT, - clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT, + ACL_CAT: ACL_CAT as ACL_CAT, + aclCat: ACL_CAT as ACL_CAT, + ACL_DELUSER: ACL_DELUSER as ACL_DELUSER, + aclDelUser: ACL_DELUSER as ACL_DELUSER, + ACL_DRYRUN: ACL_DRYRUN as ACL_DRYRUN, + aclDryRun: ACL_DRYRUN as ACL_DRYRUN, + ACL_GENPASS: ACL_GENPASS as ACL_GENPASS, + aclGenPass: ACL_GENPASS as ACL_GENPASS, + ACL_GETUSER: ACL_GETUSER as ACL_GETUSER, + aclGetUser: ACL_GETUSER as ACL_GETUSER, + ACL_LIST: ACL_LIST as ACL_LIST, + aclList: ACL_LIST as ACL_LIST, + ACL_LOAD: ACL_LOAD as ACL_LOAD, + aclLoad: ACL_LOAD as ACL_LOAD, + ACL_LOG_RESET: ACL_LOG_RESET as ACL_LOG_RESET, + aclLogReset: ACL_LOG_RESET as ACL_LOG_RESET, + ACL_LOG: ACL_LOG as ACL_LOG, + aclLog: ACL_LOG as ACL_LOG, + ACL_SAVE: ACL_SAVE as ACL_SAVE, + aclSave: ACL_SAVE as ACL_SAVE, + ACL_SETUSER: ACL_SETUSER as ACL_SETUSER, + aclSetUser: ACL_SETUSER as ACL_SETUSER, + ACL_USERS: ACL_USERS as ACL_USERS, + aclUsers: ACL_USERS as ACL_USERS, + ACL_WHOAMI: ACL_WHOAMI as ACL_WHOAMI, + aclWhoAmI: ACL_WHOAMI as ACL_WHOAMI, + APPEND: APPEND as APPEND, + append: APPEND as APPEND, + ASKING: ASKING as ASKING, + asking: ASKING as ASKING, + AUTH: AUTH as AUTH, + auth: AUTH as AUTH, + BGREWRITEAOF: BGREWRITEAOF as BGREWRITEAOF, + bgRewriteAof: BGREWRITEAOF as BGREWRITEAOF, + BGSAVE: BGSAVE as BGSAVE, + bgSave: BGSAVE as BGSAVE, + BITCOUNT: BITCOUNT as BITCOUNT, + bitCount: BITCOUNT as BITCOUNT, + BITFIELD_RO: BITFIELD_RO as BITFIELD_RO, + bitFieldRo: BITFIELD_RO as BITFIELD_RO, + BITFIELD: BITFIELD as BITFIELD, + bitField: BITFIELD as BITFIELD, + BITOP: BITOP as BITOP, + bitOp: BITOP as BITOP, + BITPOS: BITPOS as BITPOS, + bitPos: BITPOS as BITPOS, + BLMOVE: BLMOVE as BLMOVE, + blMove: BLMOVE as BLMOVE, + BLMPOP: BLMPOP as BLMPOP, + blmPop: BLMPOP as BLMPOP, + BLPOP: BLPOP as BLPOP, + blPop: BLPOP as BLPOP, + BRPOP: BRPOP as BRPOP, + brPop: BRPOP as BRPOP, + BRPOPLPUSH: BRPOPLPUSH as BRPOPLPUSH, + brPopLPush: BRPOPLPUSH as BRPOPLPUSH, + BZMPOP: BZMPOP as BZMPOP, + bzmPop: BZMPOP as BZMPOP, + BZPOPMAX: BZPOPMAX as BZPOPMAX, + bzPopMax: BZPOPMAX as BZPOPMAX, + BZPOPMIN: BZPOPMIN as BZPOPMIN, + bzPopMin: BZPOPMIN as BZPOPMIN, + CLIENT_CACHING: CLIENT_CACHING as CLIENT_CACHING, + clientCaching: CLIENT_CACHING as CLIENT_CACHING, + CLIENT_GETNAME: CLIENT_GETNAME as CLIENT_GETNAME, + clientGetName: CLIENT_GETNAME as CLIENT_GETNAME, + CLIENT_GETREDIR: CLIENT_GETREDIR as CLIENT_GETREDIR, + clientGetRedir: CLIENT_GETREDIR as CLIENT_GETREDIR, + CLIENT_ID: CLIENT_ID as CLIENT_ID, + clientId: CLIENT_ID as CLIENT_ID, + CLIENT_INFO: CLIENT_INFO as CLIENT_INFO, + clientInfo: CLIENT_INFO as CLIENT_INFO, + CLIENT_KILL: CLIENT_KILL as CLIENT_KILL, + clientKill: CLIENT_KILL as CLIENT_KILL, + CLIENT_LIST: CLIENT_LIST as CLIENT_LIST, + clientList: CLIENT_LIST as CLIENT_LIST, + 'CLIENT_NO-EVICT': CLIENT_NO_EVICT as CLIENT_NO_EVICT, + clientNoEvict: CLIENT_NO_EVICT as CLIENT_NO_EVICT, + CLIENT_PAUSE: CLIENT_PAUSE as CLIENT_PAUSE, + clientPause: CLIENT_PAUSE as CLIENT_PAUSE, + CLIENT_SETNAME: CLIENT_SETNAME as CLIENT_SETNAME, + clientSetName: CLIENT_SETNAME as CLIENT_SETNAME, + CLIENT_TRACKING: CLIENT_TRACKING as CLIENT_TRACKING, + clientTracking: CLIENT_TRACKING as CLIENT_TRACKING, + CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO as CLIENT_TRACKINGINFO, + clientTrackingInfo: CLIENT_TRACKINGINFO as CLIENT_TRACKINGINFO, + CLIENT_UNPAUSE: CLIENT_UNPAUSE as CLIENT_UNPAUSE, + clientUnpause: CLIENT_UNPAUSE as CLIENT_UNPAUSE, + CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS as CLUSTER_ADDSLOTS, + clusterAddSlots: CLUSTER_ADDSLOTS as CLUSTER_ADDSLOTS, + CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE as CLUSTER_ADDSLOTSRANGE, + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE as CLUSTER_ADDSLOTSRANGE, + CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH as CLUSTER_BUMPEPOCH, + clusterBumpEpoch: CLUSTER_BUMPEPOCH as CLUSTER_BUMPEPOCH, + 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS as CLUSTER_COUNT_FAILURE_REPORTS, + clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS as CLUSTER_COUNT_FAILURE_REPORTS, + CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT as CLUSTER_COUNTKEYSINSLOT, + clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT as CLUSTER_COUNTKEYSINSLOT, + CLUSTER_DELSLOTS: CLUSTER_DELSLOTS as CLUSTER_DELSLOTS, + clusterDelSlots: CLUSTER_DELSLOTS as CLUSTER_DELSLOTS, + CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE as CLUSTER_DELSLOTSRANGE, + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE as CLUSTER_DELSLOTSRANGE, + CLUSTER_FAILOVER: CLUSTER_FAILOVER as CLUSTER_FAILOVER, + clusterFailover: CLUSTER_FAILOVER as CLUSTER_FAILOVER, + CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS as CLUSTER_FLUSHSLOTS, + clusterFlushSlots: CLUSTER_FLUSHSLOTS as CLUSTER_FLUSHSLOTS, + CLUSTER_FORGET: CLUSTER_FORGET as CLUSTER_FORGET, + clusterForget: CLUSTER_FORGET as CLUSTER_FORGET, + CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT as CLUSTER_GETKEYSINSLOT, + clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT as CLUSTER_GETKEYSINSLOT, // CLUSTER_INFO, - // clusterInfo: CLUSTER_INFO, - CLUSTER_KEYSLOT, - clusterKeySlot: CLUSTER_KEYSLOT, - CLUSTER_LINKS, - clusterLinks: CLUSTER_LINKS, - CLUSTER_MEET, - clusterMeet: CLUSTER_MEET, - CLUSTER_MYID, - clusterMyId: CLUSTER_MYID, + // clusterInfo: CLUSTER_INFO as CLUSTER_INFO, + CLUSTER_KEYSLOT: CLUSTER_KEYSLOT as CLUSTER_KEYSLOT, + clusterKeySlot: CLUSTER_KEYSLOT as CLUSTER_KEYSLOT, + CLUSTER_LINKS: CLUSTER_LINKS as CLUSTER_LINKS, + clusterLinks: CLUSTER_LINKS as CLUSTER_LINKS, + CLUSTER_MEET: CLUSTER_MEET as CLUSTER_MEET, + clusterMeet: CLUSTER_MEET as CLUSTER_MEET, + CLUSTER_MYID: CLUSTER_MYID as CLUSTER_MYID, + clusterMyId: CLUSTER_MYID as CLUSTER_MYID, // CLUSTER_NODES, - // clusterNodes: CLUSTER_NODES, + // clusterNodes: CLUSTER_NODES as CLUSTER_NODES, // CLUSTER_REPLICAS, - // clusterReplicas: CLUSTER_REPLICAS, - CLUSTER_REPLICATE, - clusterReplicate: CLUSTER_REPLICATE, - CLUSTER_RESET, - clusterReset: CLUSTER_RESET, - CLUSTER_SAVECONFIG, - clusterSaveConfig: CLUSTER_SAVECONFIG, - 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH, - clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH, - CLUSTER_SETSLOT, - clusterSetSlot: CLUSTER_SETSLOT, - CLUSTER_SLOTS, - clusterSlots: CLUSTER_SLOTS, - COMMAND_COUNT, - commandCount: COMMAND_COUNT, - COMMAND_GETKEYS, - commandGetKeys: COMMAND_GETKEYS, - COMMAND_GETKEYSANDFLAGS, - commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS, + // clusterReplicas: CLUSTER_REPLICAS as CLUSTER_REPLICAS, + CLUSTER_REPLICATE: CLUSTER_REPLICATE as CLUSTER_REPLICATE, + clusterReplicate: CLUSTER_REPLICATE as CLUSTER_REPLICATE, + CLUSTER_RESET: CLUSTER_RESET as CLUSTER_RESET, + clusterReset: CLUSTER_RESET as CLUSTER_RESET, + CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG as CLUSTER_SAVECONFIG, + clusterSaveConfig: CLUSTER_SAVECONFIG as CLUSTER_SAVECONFIG, + 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH as CLUSTER_SET_CONFIG_EPOCH, + clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH as CLUSTER_SET_CONFIG_EPOCH, + CLUSTER_SETSLOT: CLUSTER_SETSLOT as CLUSTER_SETSLOT, + clusterSetSlot: CLUSTER_SETSLOT as CLUSTER_SETSLOT, + CLUSTER_SLOTS: CLUSTER_SLOTS as CLUSTER_SLOTS, + clusterSlots: CLUSTER_SLOTS as CLUSTER_SLOTS, + COMMAND_COUNT: COMMAND_COUNT as COMMAND_COUNT, + commandCount: COMMAND_COUNT as COMMAND_COUNT, + COMMAND_GETKEYS: COMMAND_GETKEYS as COMMAND_GETKEYS, + commandGetKeys: COMMAND_GETKEYS as COMMAND_GETKEYS, + COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS as COMMAND_GETKEYSANDFLAGS, + commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS as COMMAND_GETKEYSANDFLAGS, // COMMAND_INFO, - // commandInfo: COMMAND_INFO, + // commandInfo: COMMAND_INFO as COMMAND_INFO, // COMMAND_LIST, - // commandList: COMMAND_LIST, + // commandList: COMMAND_LIST as COMMAND_LIST, // COMMAND, - // command: COMMAND, - CONFIG_GET, - configGet: CONFIG_GET, - CONFIG_RESETASTAT, - configResetStat: CONFIG_RESETASTAT, - CONFIG_REWRITE, - configRewrite: CONFIG_REWRITE, - CONFIG_SET, - configSet: CONFIG_SET, - COPY, - copy: COPY, - DBSIZE, - dbSize: DBSIZE, - DECR, - decr: DECR, - DECRBY, - decrBy: DECRBY, - DEL, - del: DEL, - DUMP, - dump: DUMP, - ECHO, - echo: ECHO, - EVAL_RO, - evalRo: EVAL_RO, - EVAL, - eval: EVAL, - EVALSHA_RO, - evalShaRo: EVALSHA_RO, - EVALSHA, - evalSha: EVALSHA, - EXISTS, - exists: EXISTS, - EXPIRE, - expire: EXPIRE, - EXPIREAT, - expireAt: EXPIREAT, - EXPIRETIME, - expireTime: EXPIRETIME, - FLUSHALL, - flushAll: FLUSHALL, - FLUSHDB, - flushDb: FLUSHDB, - FCALL, - fCall: FCALL, - FCALL_RO, - fCallRo: FCALL_RO, - FUNCTION_DELETE, - functionDelete: FUNCTION_DELETE, - FUNCTION_DUMP, - functionDump: FUNCTION_DUMP, - FUNCTION_FLUSH, - functionFlush: FUNCTION_FLUSH, - FUNCTION_KILL, - functionKill: FUNCTION_KILL, - FUNCTION_LIST_WITHCODE, - functionListWithCode: FUNCTION_LIST_WITHCODE, - FUNCTION_LIST, - functionList: FUNCTION_LIST, - FUNCTION_LOAD, - functionLoad: FUNCTION_LOAD, - FUNCTION_RESTORE, - functionRestore: FUNCTION_RESTORE, + // command: COMMAND as COMMAND, + CONFIG_GET: CONFIG_GET as CONFIG_GET, + configGet: CONFIG_GET as CONFIG_GET, + CONFIG_RESETASTAT: CONFIG_RESETASTAT as CONFIG_RESETASTAT, + configResetStat: CONFIG_RESETASTAT as CONFIG_RESETASTAT, + CONFIG_REWRITE: CONFIG_REWRITE as CONFIG_REWRITE, + configRewrite: CONFIG_REWRITE as CONFIG_REWRITE, + CONFIG_SET: CONFIG_SET as CONFIG_SET, + configSet: CONFIG_SET as CONFIG_SET, + COPY: COPY as COPY, + copy: COPY as COPY, + DBSIZE: DBSIZE as DBSIZE, + dbSize: DBSIZE as DBSIZE, + DECR: DECR as DECR, + decr: DECR as DECR, + DECRBY: DECRBY as DECRBY, + decrBy: DECRBY as DECRBY, + DEL: DEL as DEL, + del: DEL as DEL, + DUMP: DUMP as DUMP, + dump: DUMP as DUMP, + ECHO: ECHO as ECHO, + echo: ECHO as ECHO, + EVAL_RO: EVAL_RO as EVAL_RO, + evalRo: EVAL_RO as EVAL_RO, + EVAL: EVAL as EVAL, + eval: EVAL as EVAL, + EVALSHA_RO: EVALSHA_RO as EVALSHA_RO, + evalShaRo: EVALSHA_RO as EVALSHA_RO, + EVALSHA: EVALSHA as EVALSHA, + evalSha: EVALSHA as EVALSHA, + EXISTS: EXISTS as EXISTS, + exists: EXISTS as EXISTS, + EXPIRE: EXPIRE as EXPIRE, + expire: EXPIRE as EXPIRE, + EXPIREAT: EXPIREAT as EXPIREAT, + expireAt: EXPIREAT as EXPIREAT, + EXPIRETIME: EXPIRETIME as EXPIRETIME, + expireTime: EXPIRETIME as EXPIRETIME, + FLUSHALL: FLUSHALL as FLUSHALL, + flushAll: FLUSHALL as FLUSHALL, + FLUSHDB: FLUSHDB as FLUSHDB, + flushDb: FLUSHDB as FLUSHDB, + FCALL: FCALL as FCALL, + fCall: FCALL as FCALL, + FCALL_RO: FCALL_RO as FCALL_RO, + fCallRo: FCALL_RO as FCALL_RO, + FUNCTION_DELETE: FUNCTION_DELETE as FUNCTION_DELETE, + functionDelete: FUNCTION_DELETE as FUNCTION_DELETE, + FUNCTION_DUMP: FUNCTION_DUMP as FUNCTION_DUMP, + functionDump: FUNCTION_DUMP as FUNCTION_DUMP, + FUNCTION_FLUSH: FUNCTION_FLUSH as FUNCTION_FLUSH, + functionFlush: FUNCTION_FLUSH as FUNCTION_FLUSH, + FUNCTION_KILL: FUNCTION_KILL as FUNCTION_KILL, + functionKill: FUNCTION_KILL as FUNCTION_KILL, + FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE as FUNCTION_LIST_WITHCODE, + functionListWithCode: FUNCTION_LIST_WITHCODE as FUNCTION_LIST_WITHCODE, + FUNCTION_LIST: FUNCTION_LIST as FUNCTION_LIST, + functionList: FUNCTION_LIST as FUNCTION_LIST, + FUNCTION_LOAD: FUNCTION_LOAD as FUNCTION_LOAD, + functionLoad: FUNCTION_LOAD as FUNCTION_LOAD, + FUNCTION_RESTORE: FUNCTION_RESTORE as FUNCTION_RESTORE, + functionRestore: FUNCTION_RESTORE as FUNCTION_RESTORE, // FUNCTION_STATS, - // functionStats: FUNCTION_STATS, - GEOADD, - geoAdd: GEOADD, - GEODIST, - geoDist: GEODIST, - GEOHASH, - geoHash: GEOHASH, - GEOPOS, - geoPos: GEOPOS, - GEORADIUS_RO_WITH, - geoRadiusRoWith: GEORADIUS_RO_WITH, - GEORADIUS_RO, - geoRadiusRo: GEORADIUS_RO, - GEORADIUS_STORE, - geoRadiusStore: GEORADIUS_STORE, - GEORADIUS_WITH, - geoRadiusWith: GEORADIUS_WITH, - GEORADIUS, - geoRadius: GEORADIUS, - GEORADIUSBYMEMBER_RO_WITH, - geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH, - GEORADIUSBYMEMBER_RO, - geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO, - GEORADIUSBYMEMBER_STORE, - geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE, - GEORADIUSBYMEMBER_WITH, - geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH, - GEORADIUSBYMEMBER, - geoRadiusByMember: GEORADIUSBYMEMBER, - GEOSEARCH_WITH, - geoSearchWith: GEOSEARCH_WITH, - GEOSEARCH, - geoSearch: GEOSEARCH, - GEOSEARCHSTORE, - geoSearchStore: GEOSEARCHSTORE, - GET, - get: GET, - GETBIT, - getBit: GETBIT, - GETDEL, - getDel: GETDEL, - GETEX, - getEx: GETEX, - GETRANGE, - getRange: GETRANGE, - GETSET, - getSet: GETSET, - HDEL, - hDel: HDEL, - HELLO, - hello: HELLO, - HEXISTS, - hExists: HEXISTS, - HGET, - hGet: HGET, - HGETALL, - hGetAll: HGETALL, - HINCRBY, - hIncrBy: HINCRBY, - HINCRBYFLOAT, - hIncrByFloat: HINCRBYFLOAT, - HKEYS, - hKeys: HKEYS, - HLEN, - hLen: HLEN, - HMGET, - hmGet: HMGET, - HRANDFIELD_COUNT_WITHVALUES, - hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, - HRANDFIELD_COUNT, - hRandFieldCount: HRANDFIELD_COUNT, - HRANDFIELD, - hRandField: HRANDFIELD, - HSCAN, - hScan: HSCAN, - HSET, - hSet: HSET, - HSETNX, - hSetNX: HSETNX, - HSTRLEN, - hStrLen: HSTRLEN, - HVALS, - hVals: HVALS, - INCR, - incr: INCR, - INCRBY, - incrBy: INCRBY, - INCRBYFLOAT, - incrByFloat: INCRBYFLOAT, - INFO, - info: INFO, - KEYS, - keys: KEYS, - LASTSAVE, - lastSave: LASTSAVE, - LATENCY_DOCTOR, - latencyDoctor: LATENCY_DOCTOR, - LATENCY_GRAPH, - latencyGraph: LATENCY_GRAPH, - LATENCY_LATEST, - latencyLatest: LATENCY_LATEST, - LCS_IDX_WITHMATCHLEN, - lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN, - LCS_IDX, - lcsIdx: LCS_IDX, - LCS_LEN, - lcsLen: LCS_LEN, - LCS, - lcs: LCS, - LINDEX, - lIndex: LINDEX, - LINSERT, - lInsert: LINSERT, - LLEN, - lLen: LLEN, - LMOVE, - lMove: LMOVE, - LMPOP, - lmPop: LMPOP, - LOLWUT, - LPOP_COUNT, - lPopCount: LPOP_COUNT, - LPOP, - lPop: LPOP, - LPOS_COUNT, - lPosCount: LPOS_COUNT, - LPOS, - lPos: LPOS, - LPUSH, - lPush: LPUSH, - LPUSHX, - lPushX: LPUSHX, - LRANGE, - lRange: LRANGE, - LREM, - lRem: LREM, - LSET, - lSet: LSET, - LTRIM, - lTrim: LTRIM, - MEMORY_DOCTOR, - memoryDoctor: MEMORY_DOCTOR, - 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS, - memoryMallocStats: MEMORY_MALLOC_STATS, - MEMORY_PURGE, - memoryPurge: MEMORY_PURGE, - MEMORY_STATS, - memoryStats: MEMORY_STATS, - MEMORY_USAGE, - memoryUsage: MEMORY_USAGE, - MGET, - mGet: MGET, - MODULE_LIST, - moduleList: MODULE_LIST, - MODULE_LOAD, - moduleLoad: MODULE_LOAD, - MODULE_UNLOAD, - moduleUnload: MODULE_UNLOAD, - MOVE, - move: MOVE, - MSET, - mSet: MSET, - MSETNX, - mSetNX: MSETNX, - OBJECT_ENCODING, - objectEncoding: OBJECT_ENCODING, - OBJECT_FREQ, - objectFreq: OBJECT_FREQ, - OBJECT_IDLETIME, - objectIdleTime: OBJECT_IDLETIME, - OBJECT_REFCOUNT, - objectRefCount: OBJECT_REFCOUNT, - PERSIST, - persist: PERSIST, - PEXPIRE, - pExpire: PEXPIRE, - PEXPIREAT, - pExpireAt: PEXPIREAT, - PEXPIRETIME, - pExpireTime: PEXPIRETIME, - PFADD, - pfAdd: PFADD, - PFCOUNT, - pfCount: PFCOUNT, - PFMERGE, - pfMerge: PFMERGE, - PING, + // functionStats: FUNCTION_STATS as FUNCTION_STATS, + GEOADD: GEOADD as GEOADD, + geoAdd: GEOADD as GEOADD, + GEODIST: GEODIST as GEODIST, + geoDist: GEODIST as GEODIST, + GEOHASH: GEOHASH as GEOHASH, + geoHash: GEOHASH as GEOHASH, + GEOPOS: GEOPOS as GEOPOS, + geoPos: GEOPOS as GEOPOS, + GEORADIUS_RO_WITH: GEORADIUS_RO_WITH as GEORADIUS_RO_WITH, + geoRadiusRoWith: GEORADIUS_RO_WITH as GEORADIUS_RO_WITH, + GEORADIUS_RO: GEORADIUS_RO as GEORADIUS_RO, + geoRadiusRo: GEORADIUS_RO as GEORADIUS_RO, + GEORADIUS_STORE: GEORADIUS_STORE as GEORADIUS_STORE, + geoRadiusStore: GEORADIUS_STORE as GEORADIUS_STORE, + GEORADIUS_WITH: GEORADIUS_WITH as GEORADIUS_WITH, + geoRadiusWith: GEORADIUS_WITH as GEORADIUS_WITH, + GEORADIUS: GEORADIUS as GEORADIUS, + geoRadius: GEORADIUS as GEORADIUS, + GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH as GEORADIUSBYMEMBER_RO_WITH, + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH as GEORADIUSBYMEMBER_RO_WITH, + GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO as GEORADIUSBYMEMBER_RO, + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO as GEORADIUSBYMEMBER_RO, + GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE as GEORADIUSBYMEMBER_STORE, + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE as GEORADIUSBYMEMBER_STORE, + GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH as GEORADIUSBYMEMBER_WITH, + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH as GEORADIUSBYMEMBER_WITH, + GEORADIUSBYMEMBER: GEORADIUSBYMEMBER as GEORADIUSBYMEMBER, + geoRadiusByMember: GEORADIUSBYMEMBER as GEORADIUSBYMEMBER, + GEOSEARCH_WITH: GEOSEARCH_WITH as GEOSEARCH_WITH, + geoSearchWith: GEOSEARCH_WITH as GEOSEARCH_WITH, + GEOSEARCH: GEOSEARCH as GEOSEARCH, + geoSearch: GEOSEARCH as GEOSEARCH, + GEOSEARCHSTORE: GEOSEARCHSTORE as GEOSEARCHSTORE, + geoSearchStore: GEOSEARCHSTORE as GEOSEARCHSTORE, + GET: GET as GET, + get: GET as GET, + GETBIT: GETBIT as GETBIT, + getBit: GETBIT as GETBIT, + GETDEL: GETDEL as GETDEL, + getDel: GETDEL as GETDEL, + GETEX: GETEX as GETEX, + getEx: GETEX as GETEX, + GETRANGE: GETRANGE as GETRANGE, + getRange: GETRANGE as GETRANGE, + GETSET: GETSET as GETSET, + getSet: GETSET as GETSET, + HDEL: HDEL as HDEL, + hDel: HDEL as HDEL, + HELLO: HELLO as HELLO, + hello: HELLO as HELLO, + HEXISTS: HEXISTS as HEXISTS, + hExists: HEXISTS as HEXISTS, + HGET: HGET as HGET, + hGet: HGET as HGET, + HGETALL: HGETALL as HGETALL, + hGetAll: HGETALL as HGETALL, + HINCRBY: HINCRBY as HINCRBY, + hIncrBy: HINCRBY as HINCRBY, + HINCRBYFLOAT: HINCRBYFLOAT as HINCRBYFLOAT, + hIncrByFloat: HINCRBYFLOAT as HINCRBYFLOAT, + HKEYS: HKEYS as HKEYS, + hKeys: HKEYS as HKEYS, + HLEN: HLEN as HLEN, + hLen: HLEN as HLEN, + HMGET: HMGET as HMGET, + hmGet: HMGET as HMGET, + HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES as HRANDFIELD_COUNT_WITHVALUES, + hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES as HRANDFIELD_COUNT_WITHVALUES, + HRANDFIELD_COUNT: HRANDFIELD_COUNT as HRANDFIELD_COUNT, + hRandFieldCount: HRANDFIELD_COUNT as HRANDFIELD_COUNT, + HRANDFIELD: HRANDFIELD as HRANDFIELD, + hRandField: HRANDFIELD as HRANDFIELD, + HSCAN: HSCAN as HSCAN, + hScan: HSCAN as HSCAN, + HSET: HSET as HSET, + hSet: HSET as HSET, + HSETNX: HSETNX as HSETNX, + hSetNX: HSETNX as HSETNX, + HSTRLEN: HSTRLEN as HSTRLEN, + hStrLen: HSTRLEN as HSTRLEN, + HVALS: HVALS as HVALS, + hVals: HVALS as HVALS, + INCR: INCR as INCR, + incr: INCR as INCR, + INCRBY: INCRBY as INCRBY, + incrBy: INCRBY as INCRBY, + INCRBYFLOAT: INCRBYFLOAT as INCRBYFLOAT, + incrByFloat: INCRBYFLOAT as INCRBYFLOAT, + INFO: INFO as INFO, + info: INFO as INFO, + KEYS: KEYS as KEYS, + keys: KEYS as KEYS, + LASTSAVE: LASTSAVE as LASTSAVE, + lastSave: LASTSAVE as LASTSAVE, + LATENCY_DOCTOR: LATENCY_DOCTOR as LATENCY_DOCTOR, + latencyDoctor: LATENCY_DOCTOR as LATENCY_DOCTOR, + LATENCY_GRAPH: LATENCY_GRAPH as LATENCY_GRAPH, + latencyGraph: LATENCY_GRAPH as LATENCY_GRAPH, + LATENCY_LATEST: LATENCY_LATEST as LATENCY_LATEST, + latencyLatest: LATENCY_LATEST as LATENCY_LATEST, + LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN as LCS_IDX_WITHMATCHLEN, + lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN as LCS_IDX_WITHMATCHLEN, + LCS_IDX: LCS_IDX as LCS_IDX, + lcsIdx: LCS_IDX as LCS_IDX, + LCS_LEN: LCS_LEN as LCS_LEN, + lcsLen: LCS_LEN as LCS_LEN, + LCS: LCS as LCS, + lcs: LCS as LCS, + LINDEX: LINDEX as LINDEX, + lIndex: LINDEX as LINDEX, + LINSERT: LINSERT as LINSERT, + lInsert: LINSERT as LINSERT, + LLEN: LLEN as LLEN, + lLen: LLEN as LLEN, + LMOVE: LMOVE as LMOVE, + lMove: LMOVE as LMOVE, + LMPOP: LMPOP as LMPOP, + lmPop: LMPOP as LMPOP, + LOLWUT: LOLWUT as LOLWUT, + LPOP_COUNT: LPOP_COUNT as LPOP_COUNT, + lPopCount: LPOP_COUNT as LPOP_COUNT, + LPOP: LPOP as LPOP, + lPop: LPOP as LPOP, + LPOS_COUNT: LPOS_COUNT as LPOS_COUNT, + lPosCount: LPOS_COUNT as LPOS_COUNT, + LPOS: LPOS as LPOS, + lPos: LPOS as LPOS, + LPUSH: LPUSH as LPUSH, + lPush: LPUSH as LPUSH, + LPUSHX: LPUSHX as LPUSHX, + lPushX: LPUSHX as LPUSHX, + LRANGE: LRANGE as LRANGE, + lRange: LRANGE as LRANGE, + LREM: LREM as LREM, + lRem: LREM as LREM, + LSET: LSET as LSET, + lSet: LSET as LSET, + LTRIM: LTRIM as LTRIM, + lTrim: LTRIM as LTRIM, + MEMORY_DOCTOR: MEMORY_DOCTOR as MEMORY_DOCTOR, + memoryDoctor: MEMORY_DOCTOR as MEMORY_DOCTOR, + 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS as MEMORY_MALLOC_STATS, + memoryMallocStats: MEMORY_MALLOC_STATS as MEMORY_MALLOC_STATS, + MEMORY_PURGE: MEMORY_PURGE as MEMORY_PURGE, + memoryPurge: MEMORY_PURGE as MEMORY_PURGE, + MEMORY_STATS: MEMORY_STATS as MEMORY_STATS, + memoryStats: MEMORY_STATS as MEMORY_STATS, + MEMORY_USAGE: MEMORY_USAGE as MEMORY_USAGE, + memoryUsage: MEMORY_USAGE as MEMORY_USAGE, + MGET: MGET as MGET, + mGet: MGET as MGET, + MODULE_LIST: MODULE_LIST as MODULE_LIST, + moduleList: MODULE_LIST as MODULE_LIST, + MODULE_LOAD: MODULE_LOAD as MODULE_LOAD, + moduleLoad: MODULE_LOAD as MODULE_LOAD, + MODULE_UNLOAD: MODULE_UNLOAD as MODULE_UNLOAD, + moduleUnload: MODULE_UNLOAD as MODULE_UNLOAD, + MOVE: MOVE as MOVE, + move: MOVE as MOVE, + MSET: MSET as MSET, + mSet: MSET as MSET, + MSETNX: MSETNX as MSETNX, + mSetNX: MSETNX as MSETNX, + OBJECT_ENCODING: OBJECT_ENCODING as OBJECT_ENCODING, + objectEncoding: OBJECT_ENCODING as OBJECT_ENCODING, + OBJECT_FREQ: OBJECT_FREQ as OBJECT_FREQ, + objectFreq: OBJECT_FREQ as OBJECT_FREQ, + OBJECT_IDLETIME: OBJECT_IDLETIME as OBJECT_IDLETIME, + objectIdleTime: OBJECT_IDLETIME as OBJECT_IDLETIME, + OBJECT_REFCOUNT: OBJECT_REFCOUNT as OBJECT_REFCOUNT, + objectRefCount: OBJECT_REFCOUNT as OBJECT_REFCOUNT, + PERSIST: PERSIST as PERSIST, + persist: PERSIST as PERSIST, + PEXPIRE: PEXPIRE as PEXPIRE, + pExpire: PEXPIRE as PEXPIRE, + PEXPIREAT: PEXPIREAT as PEXPIREAT, + pExpireAt: PEXPIREAT as PEXPIREAT, + PEXPIRETIME: PEXPIRETIME as PEXPIRETIME, + pExpireTime: PEXPIRETIME as PEXPIRETIME, + PFADD: PFADD as PFADD, + pfAdd: PFADD as PFADD, + PFCOUNT: PFCOUNT as PFCOUNT, + pfCount: PFCOUNT as PFCOUNT, + PFMERGE: PFMERGE as PFMERGE, + pfMerge: PFMERGE as PFMERGE, + PING: PING as PING, /** * ping jsdoc */ - ping: PING, - PSETEX, - pSetEx: PSETEX, - PTTL, - pTTL: PTTL, - PUBLISH, - publish: PUBLISH, - PUBSUB_CHANNELS, - pubSubChannels: PUBSUB_CHANNELS, - PUBSUB_NUMPAT, - pubSubNumPat: PUBSUB_NUMPAT, - PUBSUB_NUMSUB, - pubSubNumSub: PUBSUB_NUMSUB, - PUBSUB_SHARDCHANNELS, - pubSubShardChannels: PUBSUB_SHARDCHANNELS, - RANDOMKEY, - randomKey: RANDOMKEY, - READONLY, - readonly: READONLY, - RENAME, - rename: RENAME, - RENAMENX, - renameNX: RENAMENX, - RPOP_COUNT, - rPopCount: RPOP_COUNT, - ROLE, - role: ROLE, - RPOP, - rPop: RPOP, - RPOPLPUSH, - rPopLPush: RPOPLPUSH, - RPUSH, - rPush: RPUSH, - RPUSHX, - rPushX: RPUSHX, - SADD, - sAdd: SADD, - SCAN, - scan: SCAN, - SCARD, - sCard: SCARD, - SCRIPT_DEBUG, - scriptDebug: SCRIPT_DEBUG, - SCRIPT_EXISTS, - scriptExists: SCRIPT_EXISTS, - SCRIPT_FLUSH, - scriptFlush: SCRIPT_FLUSH, - SCRIPT_KILL, - scriptKill: SCRIPT_KILL, - SCRIPT_LOAD, - scriptLoad: SCRIPT_LOAD, - SDIFF, - sDiff: SDIFF, - SDIFFSTORE, - sDiffStore: SDIFFSTORE, - SET, - set: SET, - SETBIT, - setBit: SETBIT, - SETEX, - setEx: SETEX, - SETNX, - setNX: SETNX, - SETRANGE, - setRange: SETRANGE, - SINTER, - sInter: SINTER, - SINTERCARD, - sInterCard: SINTERCARD, - SINTERSTORE, - sInterStore: SINTERSTORE, - SISMEMBER, - sIsMember: SISMEMBER, - SMEMBERS, - sMembers: SMEMBERS, - SMISMEMBER, - smIsMember: SMISMEMBER, - SMOVE, - sMove: SMOVE, - SORT_RO, - sortRo: SORT_RO, - SORT_STORE, - sortStore: SORT_STORE, - SORT, - sort: SORT, - SPOP_COUNT, - sPopCount: SPOP_COUNT, - SPOP, - sPop: SPOP, - SPUBLISH, - sPublish: SPUBLISH, - SRANDMEMBER_COUNT, - sRandMemberCount: SRANDMEMBER_COUNT, - SRANDMEMBER, - sRandMember: SRANDMEMBER, - SREM, - sRem: SREM, - SSCAN, - sScan: SSCAN, - STRLEN, - strLen: STRLEN, - SUNION, - sUnion: SUNION, - SUNIONSTORE, - sUnionStore: SUNIONSTORE, - SWAPDB, - swapDb: SWAPDB, - TIME, - time: TIME, - TOUCH, - touch: TOUCH, - TTL, - ttl: TTL, - TYPE, - type: TYPE, - UNLINK, - unlink: UNLINK, - UNWATCH, - unwatch: UNWATCH, - WAIT, - wait: WAIT, - WATCH, - watch: WATCH, - XACK, - xAck: XACK, - XADD_NOMKSTREAM, - xAddNoMkStream: XADD_NOMKSTREAM, - XADD, - xAdd: XADD, - XAUTOCLAIM_JUSTID, - xAutoClaimJustId: XAUTOCLAIM_JUSTID, - XAUTOCLAIM, - xAutoClaim: XAUTOCLAIM, - XCLAIM_JUSTID, - xClaimJustId: XCLAIM_JUSTID, - XCLAIM, - xClaim: XCLAIM, - XDEL, - xDel: XDEL, - XGROUP_CREATE, - xGroupCreate: XGROUP_CREATE, - XGROUP_CREATECONSUMER, - xGroupCreateConsumer: XGROUP_CREATECONSUMER, - XGROUP_DELCONSUMER, - xGroupDelConsumer: XGROUP_DELCONSUMER, - XGROUP_DESTROY, - xGroupDestroy: XGROUP_DESTROY, - XGROUP_SETID, - xGroupSetId: XGROUP_SETID, - XINFO_CONSUMERS, - xInfoConsumers: XINFO_CONSUMERS, - XINFO_GROUPS, - xInfoGroups: XINFO_GROUPS, - XINFO_STREAM, - xInfoStream: XINFO_STREAM, - XLEN, - xLen: XLEN, - XPENDING_RANGE, - xPendingRange: XPENDING_RANGE, - XPENDING, - xPending: XPENDING, - XRANGE, - xRange: XRANGE, - XREAD, - xRead: XREAD, - XREADGROUP, - xReadGroup: XREADGROUP, - XREVRANGE, - xRevRange: XREVRANGE, - XSETID, - xSetId: XSETID, - XTRIM, - xTrim: XTRIM, - ZADD_INCR, - zAddIncr: ZADD_INCR, - ZADD, - zAdd: ZADD, - ZCARD, - zCard: ZCARD, - ZCOUNT, - zCount: ZCOUNT, - ZDIFF_WITHSCORES, - zDiffWithScores: ZDIFF_WITHSCORES, - ZDIFF, - zDiff: ZDIFF, - ZDIFFSTORE, - zDiffStore: ZDIFFSTORE, - ZINCRBY, - zIncrBy: ZINCRBY, - ZINTER_WITHSCORES, - zInterWithScores: ZINTER_WITHSCORES, - ZINTER, - zInter: ZINTER, - ZINTERCARD, - zInterCard: ZINTERCARD, - ZINTERSTORE, - zInterStore: ZINTERSTORE, - ZLEXCOUNT, - zLexCount: ZLEXCOUNT, - ZMPOP, - zmPop: ZMPOP, - ZMSCORE, - zmScore: ZMSCORE, - ZPOPMAX_COUNT, - zPopMaxCount: ZPOPMAX_COUNT, - ZPOPMAX, - zPopMax: ZPOPMAX, - ZPOPMIN_COUNT, - zPopMinCount: ZPOPMIN_COUNT, - ZPOPMIN, - zPopMin: ZPOPMIN, - ZRANDMEMBER_COUNT_WITHSCORES, - zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES, - ZRANDMEMBER_COUNT, - zRandMemberCount: ZRANDMEMBER_COUNT, - ZRANDMEMBER, - zRandMember: ZRANDMEMBER, - ZRANGE_WITHSCORES, - zRangeWithScores: ZRANGE_WITHSCORES, - ZRANGE, - zRange: ZRANGE, - ZRANGEBYLEX, - zRangeByLex: ZRANGEBYLEX, - ZRANGEBYSCORE_WITHSCORES, - zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, - ZRANGEBYSCORE, - zRangeByScore: ZRANGEBYSCORE, - ZRANGESTORE, - zRangeStore: ZRANGESTORE, - ZRANK_WITHSCORE, - zRankWithScore: ZRANK_WITHSCORE, - ZRANK, - zRank: ZRANK, - ZREM, - zRem: ZREM, - ZREMRANGEBYLEX, - zRemRangeByLex: ZREMRANGEBYLEX, - ZREMRANGEBYRANK, - zRemRangeByRank: ZREMRANGEBYRANK, - ZREMRANGEBYSCORE, - zRemRangeByScore: ZREMRANGEBYSCORE, - ZREVRANK, - zRevRank: ZREVRANK, - ZSCAN, - zScan: ZSCAN, - ZSCORE, - zScore: ZSCORE, - ZUNION_WITHSCORES, - zUnionWithScores: ZUNION_WITHSCORES, - ZUNION, - zUnion: ZUNION, - ZUNIONSTORE, + ping: PING as PING, + PSETEX: PSETEX as PSETEX, + pSetEx: PSETEX as PSETEX, + PTTL: PTTL as PTTL, + pTTL: PTTL as PTTL, + PUBLISH: PUBLISH as PUBLISH, + publish: PUBLISH as PUBLISH, + PUBSUB_CHANNELS: PUBSUB_CHANNELS as PUBSUB_CHANNELS, + pubSubChannels: PUBSUB_CHANNELS as PUBSUB_CHANNELS, + PUBSUB_NUMPAT: PUBSUB_NUMPAT as PUBSUB_NUMPAT, + pubSubNumPat: PUBSUB_NUMPAT as PUBSUB_NUMPAT, + PUBSUB_NUMSUB: PUBSUB_NUMSUB as PUBSUB_NUMSUB, + pubSubNumSub: PUBSUB_NUMSUB as PUBSUB_NUMSUB, + PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS as PUBSUB_SHARDCHANNELS, + pubSubShardChannels: PUBSUB_SHARDCHANNELS as PUBSUB_SHARDCHANNELS, + RANDOMKEY: RANDOMKEY as RANDOMKEY, + randomKey: RANDOMKEY as RANDOMKEY, + READONLY: READONLY as READONLY, + readonly: READONLY as READONLY, + RENAME: RENAME as RENAME, + rename: RENAME as RENAME, + RENAMENX: RENAMENX as RENAMENX, + renameNX: RENAMENX as RENAMENX, + RPOP_COUNT: RPOP_COUNT as RPOP_COUNT, + rPopCount: RPOP_COUNT as RPOP_COUNT, + ROLE: ROLE as ROLE, + role: ROLE as ROLE, + RPOP: RPOP as RPOP, + rPop: RPOP as RPOP, + RPOPLPUSH: RPOPLPUSH as RPOPLPUSH, + rPopLPush: RPOPLPUSH as RPOPLPUSH, + RPUSH: RPUSH as RPUSH, + rPush: RPUSH as RPUSH, + RPUSHX: RPUSHX as RPUSHX, + rPushX: RPUSHX as RPUSHX, + SADD: SADD as SADD, + sAdd: SADD as SADD, + SCAN: SCAN as SCAN, + scan: SCAN as SCAN, + SCARD: SCARD as SCARD, + sCard: SCARD as SCARD, + SCRIPT_DEBUG: SCRIPT_DEBUG as SCRIPT_DEBUG, + scriptDebug: SCRIPT_DEBUG as SCRIPT_DEBUG, + SCRIPT_EXISTS: SCRIPT_EXISTS as SCRIPT_EXISTS, + scriptExists: SCRIPT_EXISTS as SCRIPT_EXISTS, + SCRIPT_FLUSH: SCRIPT_FLUSH as SCRIPT_FLUSH, + scriptFlush: SCRIPT_FLUSH as SCRIPT_FLUSH, + SCRIPT_KILL: SCRIPT_KILL as SCRIPT_KILL, + scriptKill: SCRIPT_KILL as SCRIPT_KILL, + SCRIPT_LOAD: SCRIPT_LOAD as SCRIPT_LOAD, + scriptLoad: SCRIPT_LOAD as SCRIPT_LOAD, + SDIFF: SDIFF as SDIFF, + sDiff: SDIFF as SDIFF, + SDIFFSTORE: SDIFFSTORE as SDIFFSTORE, + sDiffStore: SDIFFSTORE as SDIFFSTORE, + SET: SET as SET, + set: SET as SET, + SETBIT: SETBIT as SETBIT, + setBit: SETBIT as SETBIT, + SETEX: SETEX as SETEX, + setEx: SETEX as SETEX, + SETNX: SETNX as SETNX, + setNX: SETNX as SETNX, + SETRANGE: SETRANGE as SETRANGE, + setRange: SETRANGE as SETRANGE, + SINTER: SINTER as SINTER, + sInter: SINTER as SINTER, + SINTERCARD: SINTERCARD as SINTERCARD, + sInterCard: SINTERCARD as SINTERCARD, + SINTERSTORE: SINTERSTORE as SINTERSTORE, + sInterStore: SINTERSTORE as SINTERSTORE, + SISMEMBER: SISMEMBER as SISMEMBER, + sIsMember: SISMEMBER as SISMEMBER, + SMEMBERS: SMEMBERS as SMEMBERS, + sMembers: SMEMBERS as SMEMBERS, + SMISMEMBER: SMISMEMBER as SMISMEMBER, + smIsMember: SMISMEMBER as SMISMEMBER, + SMOVE: SMOVE as SMOVE, + sMove: SMOVE as SMOVE, + SORT_RO: SORT_RO as SORT_RO, + sortRo: SORT_RO as SORT_RO, + SORT_STORE: SORT_STORE as SORT_STORE, + sortStore: SORT_STORE as SORT_STORE, + SORT: SORT as SORT, + sort: SORT as SORT, + SPOP_COUNT: SPOP_COUNT as SPOP_COUNT, + sPopCount: SPOP_COUNT as SPOP_COUNT, + SPOP: SPOP as SPOP, + sPop: SPOP as SPOP, + SPUBLISH: SPUBLISH as SPUBLISH, + sPublish: SPUBLISH as SPUBLISH, + SRANDMEMBER_COUNT: SRANDMEMBER_COUNT as SRANDMEMBER_COUNT, + sRandMemberCount: SRANDMEMBER_COUNT as SRANDMEMBER_COUNT, + SRANDMEMBER: SRANDMEMBER as SRANDMEMBER, + sRandMember: SRANDMEMBER as SRANDMEMBER, + SREM: SREM as SREM, + sRem: SREM as SREM, + SSCAN: SSCAN as SSCAN, + sScan: SSCAN as SSCAN, + STRLEN: STRLEN as STRLEN, + strLen: STRLEN as STRLEN, + SUNION: SUNION as SUNION, + sUnion: SUNION as SUNION, + SUNIONSTORE: SUNIONSTORE as SUNIONSTORE, + sUnionStore: SUNIONSTORE as SUNIONSTORE, + SWAPDB: SWAPDB as SWAPDB, + swapDb: SWAPDB as SWAPDB, + TIME: TIME as TIME, + time: TIME as TIME, + TOUCH: TOUCH as TOUCH, + touch: TOUCH as TOUCH, + TTL: TTL as TTL, + ttl: TTL as TTL, + TYPE: TYPE as TYPE, + type: TYPE as TYPE, + UNLINK: UNLINK as UNLINK, + unlink: UNLINK as UNLINK, + UNWATCH: UNWATCH as UNWATCH, + unwatch: UNWATCH as UNWATCH, + WAIT: WAIT as WAIT, + wait: WAIT as WAIT, + WATCH: WATCH as WATCH, + watch: WATCH as WATCH, + XACK: XACK as XACK, + xAck: XACK as XACK, + XADD_NOMKSTREAM: XADD_NOMKSTREAM as XADD_NOMKSTREAM, + xAddNoMkStream: XADD_NOMKSTREAM as XADD_NOMKSTREAM, + XADD: XADD as XADD, + xAdd: XADD as XADD, + XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID as XAUTOCLAIM_JUSTID, + xAutoClaimJustId: XAUTOCLAIM_JUSTID as XAUTOCLAIM_JUSTID, + XAUTOCLAIM: XAUTOCLAIM as XAUTOCLAIM, + xAutoClaim: XAUTOCLAIM as XAUTOCLAIM, + XCLAIM_JUSTID: XCLAIM_JUSTID as XCLAIM_JUSTID, + xClaimJustId: XCLAIM_JUSTID as XCLAIM_JUSTID, + XCLAIM: XCLAIM as XCLAIM, + xClaim: XCLAIM as XCLAIM, + XDEL: XDEL as XDEL, + xDel: XDEL as XDEL, + XGROUP_CREATE: XGROUP_CREATE as XGROUP_CREATE, + xGroupCreate: XGROUP_CREATE as XGROUP_CREATE, + XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER as XGROUP_CREATECONSUMER, + xGroupCreateConsumer: XGROUP_CREATECONSUMER as XGROUP_CREATECONSUMER, + XGROUP_DELCONSUMER: XGROUP_DELCONSUMER as XGROUP_DELCONSUMER, + xGroupDelConsumer: XGROUP_DELCONSUMER as XGROUP_DELCONSUMER, + XGROUP_DESTROY: XGROUP_DESTROY as XGROUP_DESTROY, + xGroupDestroy: XGROUP_DESTROY as XGROUP_DESTROY, + XGROUP_SETID: XGROUP_SETID as XGROUP_SETID, + xGroupSetId: XGROUP_SETID as XGROUP_SETID, + XINFO_CONSUMERS: XINFO_CONSUMERS as XINFO_CONSUMERS, + xInfoConsumers: XINFO_CONSUMERS as XINFO_CONSUMERS, + XINFO_GROUPS: XINFO_GROUPS as XINFO_GROUPS, + xInfoGroups: XINFO_GROUPS as XINFO_GROUPS, + XINFO_STREAM: XINFO_STREAM as XINFO_STREAM, + xInfoStream: XINFO_STREAM as XINFO_STREAM, + XLEN: XLEN as XLEN, + xLen: XLEN as XLEN, + XPENDING_RANGE: XPENDING_RANGE as XPENDING_RANGE, + xPendingRange: XPENDING_RANGE as XPENDING_RANGE, + XPENDING: XPENDING as XPENDING, + xPending: XPENDING as XPENDING, + XRANGE: XRANGE as XRANGE, + xRange: XRANGE as XRANGE, + XREAD: XREAD as XREAD, + xRead: XREAD as XREAD, + XREADGROUP: XREADGROUP as XREADGROUP, + xReadGroup: XREADGROUP as XREADGROUP, + XREVRANGE: XREVRANGE as XREVRANGE, + xRevRange: XREVRANGE as XREVRANGE, + XSETID: XSETID as XSETID, + xSetId: XSETID as XSETID, + XTRIM: XTRIM as XTRIM, + xTrim: XTRIM as XTRIM, + ZADD_INCR: ZADD_INCR as ZADD_INCR, + zAddIncr: ZADD_INCR as ZADD_INCR, + ZADD: ZADD as ZADD, + zAdd: ZADD as ZADD, + ZCARD: ZCARD as ZCARD, + zCard: ZCARD as ZCARD, + ZCOUNT: ZCOUNT as ZCOUNT, + zCount: ZCOUNT as ZCOUNT, + ZDIFF_WITHSCORES: ZDIFF_WITHSCORES as ZDIFF_WITHSCORES, + zDiffWithScores: ZDIFF_WITHSCORES as ZDIFF_WITHSCORES, + ZDIFF: ZDIFF as ZDIFF, + zDiff: ZDIFF as ZDIFF, + ZDIFFSTORE: ZDIFFSTORE as ZDIFFSTORE, + zDiffStore: ZDIFFSTORE as ZDIFFSTORE, + ZINCRBY: ZINCRBY as ZINCRBY, + zIncrBy: ZINCRBY as ZINCRBY, + ZINTER_WITHSCORES: ZINTER_WITHSCORES as ZINTER_WITHSCORES, + zInterWithScores: ZINTER_WITHSCORES as ZINTER_WITHSCORES, + ZINTER: ZINTER as ZINTER, + zInter: ZINTER as ZINTER, + ZINTERCARD: ZINTERCARD as ZINTERCARD, + zInterCard: ZINTERCARD as ZINTERCARD, + ZINTERSTORE: ZINTERSTORE as ZINTERSTORE, + zInterStore: ZINTERSTORE as ZINTERSTORE, + ZLEXCOUNT: ZLEXCOUNT as ZLEXCOUNT, + zLexCount: ZLEXCOUNT as ZLEXCOUNT, + ZMPOP: ZMPOP as ZMPOP, + zmPop: ZMPOP as ZMPOP, + ZMSCORE: ZMSCORE as ZMSCORE, + zmScore: ZMSCORE as ZMSCORE, + ZPOPMAX_COUNT: ZPOPMAX_COUNT as ZPOPMAX_COUNT, + zPopMaxCount: ZPOPMAX_COUNT as ZPOPMAX_COUNT, + ZPOPMAX: ZPOPMAX as ZPOPMAX, + zPopMax: ZPOPMAX as ZPOPMAX, + ZPOPMIN_COUNT: ZPOPMIN_COUNT as ZPOPMIN_COUNT, + zPopMinCount: ZPOPMIN_COUNT as ZPOPMIN_COUNT, + ZPOPMIN: ZPOPMIN as ZPOPMIN, + zPopMin: ZPOPMIN as ZPOPMIN, + ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES as ZRANDMEMBER_COUNT_WITHSCORES, + zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES as ZRANDMEMBER_COUNT_WITHSCORES, + ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT as ZRANDMEMBER_COUNT, + zRandMemberCount: ZRANDMEMBER_COUNT as ZRANDMEMBER_COUNT, + ZRANDMEMBER: ZRANDMEMBER as ZRANDMEMBER, + zRandMember: ZRANDMEMBER as ZRANDMEMBER, + ZRANGE_WITHSCORES: ZRANGE_WITHSCORES as ZRANGE_WITHSCORES, + zRangeWithScores: ZRANGE_WITHSCORES as ZRANGE_WITHSCORES, + ZRANGE: ZRANGE as ZRANGE, + zRange: ZRANGE as ZRANGE, + ZRANGEBYLEX: ZRANGEBYLEX as ZRANGEBYLEX, + zRangeByLex: ZRANGEBYLEX as ZRANGEBYLEX, + ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES as ZRANGEBYSCORE_WITHSCORES, + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES as ZRANGEBYSCORE_WITHSCORES, + ZRANGEBYSCORE: ZRANGEBYSCORE as ZRANGEBYSCORE, + zRangeByScore: ZRANGEBYSCORE as ZRANGEBYSCORE, + ZRANGESTORE: ZRANGESTORE as ZRANGESTORE, + zRangeStore: ZRANGESTORE as ZRANGESTORE, + ZRANK_WITHSCORE: ZRANK_WITHSCORE as ZRANK_WITHSCORE, + zRankWithScore: ZRANK_WITHSCORE as ZRANK_WITHSCORE, + ZRANK: ZRANK as ZRANK, + zRank: ZRANK as ZRANK, + ZREM: ZREM as ZREM, + zRem: ZREM as ZREM, + ZREMRANGEBYLEX: ZREMRANGEBYLEX as ZREMRANGEBYLEX, + zRemRangeByLex: ZREMRANGEBYLEX as ZREMRANGEBYLEX, + ZREMRANGEBYRANK: ZREMRANGEBYRANK as ZREMRANGEBYRANK, + zRemRangeByRank: ZREMRANGEBYRANK as ZREMRANGEBYRANK, + ZREMRANGEBYSCORE: ZREMRANGEBYSCORE as ZREMRANGEBYSCORE, + zRemRangeByScore: ZREMRANGEBYSCORE as ZREMRANGEBYSCORE, + ZREVRANK: ZREVRANK as ZREVRANK, + zRevRank: ZREVRANK as ZREVRANK, + ZSCAN: ZSCAN as ZSCAN, + zScan: ZSCAN as ZSCAN, + ZSCORE: ZSCORE as ZSCORE, + zScore: ZSCORE as ZSCORE, + ZUNION_WITHSCORES: ZUNION_WITHSCORES as ZUNION_WITHSCORES, + zUnionWithScores: ZUNION_WITHSCORES as ZUNION_WITHSCORES, + ZUNION: ZUNION as ZUNION, + zUnion: ZUNION as ZUNION, + ZUNIONSTORE: ZUNIONSTORE as ZUNIONSTORE, zUnionStore: ZUNIONSTORE -} satisfies Record as Commands; +} as const satisfies RedisCommands; From 7eaf3cdf3da5b9b0757b04382d11f33308977307 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 12:20:23 -0400 Subject: [PATCH 177/325] wip --- .github/workflows/tests.yml | 2 +- packages/bloom/lib/commands/bloom/index.ts | 51 +- .../lib/commands/count-min-sketch/index.ts | 31 +- packages/bloom/lib/commands/cuckoo/index.ts | 56 +- packages/bloom/lib/commands/t-digest/index.ts | 71 +- packages/bloom/lib/commands/top-k/index.ts | 41 +- packages/client/lib/commands/index.ts | 1613 +++++++---------- 7 files changed, 742 insertions(+), 1123 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 048e72f6f76..883ad8e25e9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Install Packages run: npm ci - name: Build - run: npm run build -- ./packages/client ./packages/test-utils/ + run: npm run build -- ./packages/client ./packages/test-utils - name: Run Tests run: npm run test -ws --if-present -- --forbid-only --redis-version=${{ matrix.redis-version }} - name: Upload to Codecov diff --git a/packages/bloom/lib/commands/bloom/index.ts b/packages/bloom/lib/commands/bloom/index.ts index c29039d2d46..7483467d867 100644 --- a/packages/bloom/lib/commands/bloom/index.ts +++ b/packages/bloom/lib/commands/bloom/index.ts @@ -10,36 +10,25 @@ import MEXISTS from './MEXISTS'; import RESERVE from './RESERVE'; import SCANDUMP from './SCANDUMP'; -type ADD = typeof import('./ADD').default; -type CARD = typeof import('./CARD').default; -type EXISTS = typeof import('./EXISTS').default; -// type INFO = typeof import('./INFO').default; -type INSERT = typeof import('./INSERT').default; -type LOADCHUNK = typeof import('./LOADCHUNK').default; -type MADD = typeof import('./MADD').default; -type MEXISTS = typeof import('./MEXISTS').default; -type RESERVE = typeof import('./RESERVE').default; -type SCANDUMP = typeof import('./SCANDUMP').default; - export default { - ADD: ADD as ADD, - add: ADD as ADD, - CARD: CARD as CARD, - card: CARD as CARD, - EXISTS: EXISTS as EXISTS, - exists: EXISTS as EXISTS, - // INFO: INFO as INFO, - // info: INFO as INFO, - INSERT: INSERT as INSERT, - insert: INSERT as INSERT, - LOADCHUNK: LOADCHUNK as LOADCHUNK, - loadChunk: LOADCHUNK as LOADCHUNK, - MADD: MADD as MADD, - mAdd: MADD as MADD, - MEXISTS: MEXISTS as MEXISTS, - mExists: MEXISTS as MEXISTS, - RESERVE: RESERVE as RESERVE, - reserve: RESERVE as RESERVE, - SCANDUMP: SCANDUMP as SCANDUMP, - scanDump: SCANDUMP as SCANDUMP + ADD, + add: ADD, + CARD, + card: CARD, + EXISTS, + exists: EXISTS, + // INFO, + // info: INFO, + INSERT, + insert: INSERT, + LOADCHUNK, + loadChunk: LOADCHUNK, + MADD, + mAdd: MADD, + MEXISTS, + mExists: MEXISTS, + RESERVE, + reserve: RESERVE, + SCANDUMP, + scanDump: SCANDUMP } as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/count-min-sketch/index.ts b/packages/bloom/lib/commands/count-min-sketch/index.ts index cac390ba980..4f0f395ca3d 100644 --- a/packages/bloom/lib/commands/count-min-sketch/index.ts +++ b/packages/bloom/lib/commands/count-min-sketch/index.ts @@ -6,24 +6,17 @@ import INITBYPROB from './INITBYPROB'; import MERGE from './MERGE'; import QUERY from './QUERY'; -type INCRBY = typeof import('./INCRBY').default; -type INFO = typeof import('./INFO').default; -type INITBYDIM = typeof import('./INITBYDIM').default; -type INITBYPROB = typeof import('./INITBYPROB').default; -type MERGE = typeof import('./MERGE').default; -type QUERY = typeof import('./QUERY').default; - export default { - INCRBY: INCRBY as INCRBY, - incrBy: INCRBY as INCRBY, - INFO: INFO as INFO, - info: INFO as INFO, - INITBYDIM: INITBYDIM as INITBYDIM, - initByDim: INITBYDIM as INITBYDIM, - INITBYPROB: INITBYPROB as INITBYPROB, - initByProb: INITBYPROB as INITBYPROB, - MERGE: MERGE as MERGE, - merge: MERGE as MERGE, - QUERY: QUERY as QUERY, - query: QUERY as QUERY, + INCRBY, + incrBy: INCRBY, + INFO, + info: INFO, + INITBYDIM, + initByDim: INITBYDIM, + INITBYPROB, + initByProb: INITBYPROB, + MERGE, + merge: MERGE, + QUERY, + query: QUERY } as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/cuckoo/index.ts b/packages/bloom/lib/commands/cuckoo/index.ts index b76a01032af..f8eaed93059 100644 --- a/packages/bloom/lib/commands/cuckoo/index.ts +++ b/packages/bloom/lib/commands/cuckoo/index.ts @@ -11,39 +11,27 @@ import LOADCHUNK from './LOADCHUNK'; import RESERVE from './RESERVE'; import SCANDUMP from './SCANDUMP'; -type ADD = typeof import('./ADD').default; -type ADDNX = typeof import('./ADDNX').default; -type COUNT = typeof import('./COUNT').default; -type DEL = typeof import('./DEL').default; -type EXISTS = typeof import('./EXISTS').default; -// type INFO = typeof import('./INFO').default; -type INSERT = typeof import('./INSERT').default; -type INSERTNX = typeof import('./INSERTNX').default; -type LOADCHUNK = typeof import('./LOADCHUNK').default; -type RESERVE = typeof import('./RESERVE').default; -type SCANDUMP = typeof import('./SCANDUMP').default; - export default { - ADD: ADD as ADD, - add: ADD as ADD, - ADDNX: ADDNX as ADDNX, - addNX: ADDNX as ADDNX, - COUNT: COUNT as COUNT, - count: COUNT as COUNT, - DEL: DEL as DEL, - del: DEL as DEL, - EXISTS: EXISTS as EXISTS, - exists: EXISTS as EXISTS, - // INFO: INFO as INFO, - // info: INFO as INFO, - INSERT: INSERT as INSERT, - insert: INSERT as INSERT, - INSERTNX: INSERTNX as INSERTNX, - insertNX: INSERTNX as INSERTNX, - LOADCHUNK: LOADCHUNK as LOADCHUNK, - loadChunk: LOADCHUNK as LOADCHUNK, - RESERVE: RESERVE as RESERVE, - reserve: RESERVE as RESERVE, - SCANDUMP: SCANDUMP as SCANDUMP, - scanDump: SCANDUMP as SCANDUMP + ADD, + add: ADD, + ADDNX, + addNX: ADDNX, + COUNT, + count: COUNT, + DEL, + del: DEL, + EXISTS, + exists: EXISTS, + // INFO, + // info: INFO, + INSERT, + insert: INSERT, + INSERTNX, + insertNX: INSERTNX, + LOADCHUNK, + loadChunk: LOADCHUNK, + RESERVE, + reserve: RESERVE, + SCANDUMP, + scanDump: SCANDUMP } as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/t-digest/index.ts b/packages/bloom/lib/commands/t-digest/index.ts index 161f832a4dc..de3d07bdb7b 100644 --- a/packages/bloom/lib/commands/t-digest/index.ts +++ b/packages/bloom/lib/commands/t-digest/index.ts @@ -14,48 +14,33 @@ import RESET from './RESET'; import REVRANK from './REVRANK'; import TRIMMED_MEAN from './TRIMMED_MEAN'; -type ADD = typeof import('./ADD').default; -type BYRANK = typeof import('./BYRANK').default; -type BYREVRANK = typeof import('./BYREVRANK').default; -type CDF = typeof import('./CDF').default; -type CREATE = typeof import('./CREATE').default; -// type INFO = typeof import('./INFO').default; -type MAX = typeof import('./MAX').default; -type MERGE = typeof import('./MERGE').default; -type MIN = typeof import('./MIN').default; -type QUANTILE = typeof import('./QUANTILE').default; -type RANK = typeof import('./RANK').default; -type RESET = typeof import('./RESET').default; -type REVRANK = typeof import('./REVRANK').default; -type TRIMMED_MEAN = typeof import('./TRIMMED_MEAN').default; - export default { - ADD: ADD as ADD, - add: ADD as ADD, - BYRANK: BYRANK as BYRANK, - byRank: BYRANK as BYRANK, - BYREVRANK: BYREVRANK as BYREVRANK, - byRevRank: BYREVRANK as BYREVRANK, - CDF: CDF as CDF, - cdf: CDF as CDF, - CREATE: CREATE as CREATE, - create: CREATE as CREATE, - // INFO: INFO as INFO, - // info: INFO as INFO, - MAX: MAX as MAX, - max: MAX as MAX, - MERGE: MERGE as MERGE, - merge: MERGE as MERGE, - MIN: MIN as MIN, - min: MIN as MIN, - QUANTILE: QUANTILE as QUANTILE, - quantile: QUANTILE as QUANTILE, - RANK: RANK as RANK, - rank: RANK as RANK, - RESET: RESET as RESET, - reset: RESET as RESET, - REVRANK: REVRANK as REVRANK, - revRank: REVRANK as REVRANK, - TRIMMED_MEAN: TRIMMED_MEAN as TRIMMED_MEAN, - trimmedMean: TRIMMED_MEAN as TRIMMED_MEAN + ADD, + add: ADD, + BYRANK, + byRank: BYRANK, + BYREVRANK, + byRevRank: BYREVRANK, + CDF, + cdf: CDF, + CREATE, + create: CREATE, + // INFO, + // info: INFO, + MAX, + max: MAX, + MERGE, + merge: MERGE, + MIN, + min: MIN, + QUANTILE, + quantile: QUANTILE, + RANK, + rank: RANK, + RESET, + reset: RESET, + REVRANK, + revRank: REVRANK, + TRIMMED_MEAN, + trimmedMean: TRIMMED_MEAN } as const satisfies RedisCommands; diff --git a/packages/bloom/lib/commands/top-k/index.ts b/packages/bloom/lib/commands/top-k/index.ts index 0f3b17c523f..fb5de543cab 100644 --- a/packages/bloom/lib/commands/top-k/index.ts +++ b/packages/bloom/lib/commands/top-k/index.ts @@ -8,30 +8,21 @@ import LIST from './LIST'; import QUERY from './QUERY'; import RESERVE from './RESERVE'; -type ADD = typeof import('./ADD').default; -type COUNT = typeof import('./COUNT').default; -type INCRBY = typeof import('./INCRBY').default; -type INFO = typeof import('./INFO').default; -type LIST_WITHCOUNT = typeof import('./LIST_WITHCOUNT').default; -type LIST = typeof import('./LIST').default; -type QUERY = typeof import('./QUERY').default; -type RESERVE = typeof import('./RESERVE').default; - export default { - ADD: ADD as ADD, - add: ADD as ADD, - COUNT: COUNT as COUNT, - count: COUNT as COUNT, - INCRBY: INCRBY as INCRBY, - incrBy: INCRBY as INCRBY, - INFO: INFO as INFO, - info: INFO as INFO, - LIST_WITHCOUNT: LIST_WITHCOUNT as LIST_WITHCOUNT, - listWithCount: LIST_WITHCOUNT as LIST_WITHCOUNT, - LIST: LIST as LIST, - list: LIST as LIST, - QUERY: QUERY as QUERY, - query: QUERY as QUERY, - RESERVE: RESERVE as RESERVE, - reserve: RESERVE as RESERVE + ADD, + add: ADD, + COUNT, + count: COUNT, + INCRBY, + incrBy: INCRBY, + INFO, + info: INFO, + LIST_WITHCOUNT, + listWithCount: LIST_WITHCOUNT, + LIST, + list: LIST, + QUERY, + query: QUERY, + RESERVE, + reserve: RESERVE } as const satisfies RedisCommands; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index c848b7ba583..d8eb66b66af 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -326,986 +326,659 @@ import ZUNION_WITHSCORES from './ZUNION_WITHSCORES'; import ZUNION from './ZUNION'; import ZUNIONSTORE from './ZUNIONSTORE'; -type ACL_CAT = typeof import('./ACL_CAT').default; -type ACL_DELUSER = typeof import('./ACL_DELUSER').default; -type ACL_DRYRUN = typeof import('./ACL_DRYRUN').default; -type ACL_GENPASS = typeof import('./ACL_GENPASS').default; -type ACL_GETUSER = typeof import('./ACL_GETUSER').default; -type ACL_LIST = typeof import('./ACL_LIST').default; -type ACL_LOAD = typeof import('./ACL_LOAD').default; -type ACL_LOG_RESET = typeof import('./ACL_LOG_RESET').default; -type ACL_LOG = typeof import('./ACL_LOG').default; -type ACL_SAVE = typeof import('./ACL_SAVE').default; -type ACL_SETUSER = typeof import('./ACL_SETUSER').default; -type ACL_USERS = typeof import('./ACL_USERS').default; -type ACL_WHOAMI = typeof import('./ACL_WHOAMI').default; -type APPEND = typeof import('./APPEND').default; -type ASKING = typeof import('./ASKING').default; -type AUTH = typeof import('./AUTH').default; -type BGREWRITEAOF = typeof import('./BGREWRITEAOF').default; -type BGSAVE = typeof import('./BGSAVE').default; -type BITCOUNT = typeof import('./BITCOUNT').default; -type BITFIELD_RO = typeof import('./BITFIELD_RO').default; -type BITFIELD = typeof import('./BITFIELD').default; -type BITOP = typeof import('./BITOP').default; -type BITPOS = typeof import('./BITPOS').default; -type BLMOVE = typeof import('./BLMOVE').default; -type BLMPOP = typeof import('./BLMPOP').default; -type BLPOP = typeof import('./BLPOP').default; -type BRPOP = typeof import('./BRPOP').default; -type BRPOPLPUSH = typeof import('./BRPOPLPUSH').default; -type BZMPOP = typeof import('./BZMPOP').default; -type BZPOPMAX = typeof import('./BZPOPMAX').default; -type BZPOPMIN = typeof import('./BZPOPMIN').default; -type CLIENT_CACHING = typeof import('./CLIENT_CACHING').default; -type CLIENT_GETNAME = typeof import('./CLIENT_GETNAME').default; -type CLIENT_GETREDIR = typeof import('./CLIENT_GETREDIR').default; -type CLIENT_ID = typeof import('./CLIENT_ID').default; -type CLIENT_INFO = typeof import('./CLIENT_INFO').default; -type CLIENT_KILL = typeof import('./CLIENT_KILL').default; -type CLIENT_LIST = typeof import('./CLIENT_LIST').default; -type CLIENT_NO_EVICT = typeof import('./CLIENT_NO-EVICT').default; -type CLIENT_PAUSE = typeof import('./CLIENT_PAUSE').default; -type CLIENT_SETNAME = typeof import('./CLIENT_SETNAME').default; -type CLIENT_TRACKING = typeof import('./CLIENT_TRACKING').default; -type CLIENT_TRACKINGINFO = typeof import('./CLIENT_TRACKINGINFO').default; -type CLIENT_UNPAUSE = typeof import('./CLIENT_UNPAUSE').default; -type CLUSTER_ADDSLOTS = typeof import('./CLUSTER_ADDSLOTS').default; -type CLUSTER_ADDSLOTSRANGE = typeof import('./CLUSTER_ADDSLOTSRANGE').default; -type CLUSTER_BUMPEPOCH = typeof import('./CLUSTER_BUMPEPOCH').default; -type CLUSTER_COUNT_FAILURE_REPORTS = typeof import('./CLUSTER_COUNT-FAILURE-REPORTS').default; -type CLUSTER_COUNTKEYSINSLOT = typeof import('./CLUSTER_COUNTKEYSINSLOT').default; -type CLUSTER_DELSLOTS = typeof import('./CLUSTER_DELSLOTS').default; -type CLUSTER_DELSLOTSRANGE = typeof import('./CLUSTER_DELSLOTSRANGE').default; -type CLUSTER_FAILOVER = typeof import('./CLUSTER_FAILOVER').default; -type CLUSTER_FLUSHSLOTS = typeof import('./CLUSTER_FLUSHSLOTS').default; -type CLUSTER_FORGET = typeof import('./CLUSTER_FORGET').default; -type CLUSTER_GETKEYSINSLOT = typeof import('./CLUSTER_GETKEYSINSLOT').default; -// type CLUSTER_INFO = typeof import('./CLUSTER_INFO').default; -type CLUSTER_KEYSLOT = typeof import('./CLUSTER_KEYSLOT').default; -type CLUSTER_LINKS = typeof import('./CLUSTER_LINKS').default; -type CLUSTER_MEET = typeof import('./CLUSTER_MEET').default; -type CLUSTER_MYID = typeof import('./CLUSTER_MYID').default; -// type CLUSTER_NODES = typeof import('./CLUSTER_NODES').default; -// type CLUSTER_REPLICAS = typeof import('./CLUSTER_REPLICAS').default; -type CLUSTER_REPLICATE = typeof import('./CLUSTER_REPLICATE').default; -type CLUSTER_RESET = typeof import('./CLUSTER_RESET').default; -type CLUSTER_SAVECONFIG = typeof import('./CLUSTER_SAVECONFIG').default; -type CLUSTER_SET_CONFIG_EPOCH = typeof import('./CLUSTER_SET-CONFIG-EPOCH').default; -type CLUSTER_SETSLOT = typeof import('./CLUSTER_SETSLOT').default; -type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default; -type COMMAND_COUNT = typeof import('./COMMAND_COUNT').default; -type COMMAND_GETKEYS = typeof import('./COMMAND_GETKEYS').default; -type COMMAND_GETKEYSANDFLAGS = typeof import('./COMMAND_GETKEYSANDFLAGS').default; -// type COMMAND_INFO = typeof import('./COMMAND_INFO').default; -// type COMMAND_LIST = typeof import('./COMMAND_LIST').default; -// type COMMAND = typeof import('./COMMAND').default; -type CONFIG_GET = typeof import('./CONFIG_GET').default; -type CONFIG_RESETASTAT = typeof import('./CONFIG_RESETSTAT').default; -type CONFIG_REWRITE = typeof import('./CONFIG_REWRITE').default; -type CONFIG_SET = typeof import('./CONFIG_SET').default; -type COPY = typeof import('./COPY').default; -type DBSIZE = typeof DBSIZE; -type DECR = typeof import('./DECR').default; -type DECRBY = typeof import('./DECRBY').default; -type DEL = typeof import('./DEL').default; -type DUMP = typeof import('./DUMP').default; -type ECHO = typeof import('./ECHO').default; -type EVAL_RO = typeof import('./EVAL_RO').default; -type EVAL = typeof import('./EVAL').default; -type EVALSHA_RO = typeof import('./EVALSHA_RO').default; -type EVALSHA = typeof import('./EVALSHA').default; -type GEOADD = typeof import('./GEOADD').default; -type GEODIST = typeof import('./GEODIST').default; -type GEOHASH = typeof import('./GEOHASH').default; -type GEOPOS = typeof import('./GEOPOS').default; -type GEORADIUS_RO_WITH = typeof import('./GEORADIUS_RO_WITH').default; -type GEORADIUS_RO = typeof import('./GEORADIUS_RO').default; -type GEORADIUS_STORE = typeof import('./GEORADIUS_STORE').default; -type GEORADIUS_WITH = typeof import('./GEORADIUS_WITH').default; -type GEORADIUS = typeof import('./GEORADIUS').default; -type GEORADIUSBYMEMBER_RO_WITH = typeof import('./GEORADIUSBYMEMBER_RO_WITH').default; -type GEORADIUSBYMEMBER_RO = typeof import('./GEORADIUSBYMEMBER_RO').default; -type GEORADIUSBYMEMBER_STORE = typeof import('./GEORADIUSBYMEMBER_STORE').default; -type GEORADIUSBYMEMBER_WITH = typeof import('./GEORADIUSBYMEMBER_WITH').default; -type GEORADIUSBYMEMBER = typeof import('./GEORADIUSBYMEMBER').default; -type GEOSEARCH_WITH = typeof import('./GEOSEARCH_WITH').default; -type GEOSEARCH = typeof import('./GEOSEARCH').default; -type GEOSEARCHSTORE = typeof import('./GEOSEARCHSTORE').default; -type GET = typeof import('./GET').default; -type GETBIT = typeof import('./GETBIT').default; -type GETDEL = typeof import('./GETDEL').default; -type GETEX = typeof import('./GETEX').default; -type GETRANGE = typeof import('./GETRANGE').default; -type GETSET = typeof import('./GETSET').default; -type EXISTS = typeof import('./EXISTS').default; -type EXPIRE = typeof import('./EXPIRE').default; -type EXPIREAT = typeof import('./EXPIREAT').default; -type EXPIRETIME = typeof import('./EXPIRETIME').default; -type FLUSHALL = typeof import('./FLUSHALL').default; -type FLUSHDB = typeof import('./FLUSHDB').default; -type FCALL = typeof import('./FCALL').default; -type FCALL_RO = typeof import('./FCALL_RO').default; -type FUNCTION_DELETE = typeof import('./FUNCTION_DELETE').default; -type FUNCTION_DUMP = typeof import('./FUNCTION_DUMP').default; -type FUNCTION_FLUSH = typeof import('./FUNCTION_FLUSH').default; -type FUNCTION_KILL = typeof import('./FUNCTION_KILL').default; -type FUNCTION_LIST_WITHCODE = typeof import('./FUNCTION_LIST_WITHCODE').default; -type FUNCTION_LIST = typeof import('./FUNCTION_LIST').default; -type FUNCTION_LOAD = typeof import('./FUNCTION_LOAD').default; -type FUNCTION_RESTORE = typeof import('./FUNCTION_RESTORE').default; -// type FUNCTION_STATS = typeof import('./FUNCTION_STATS').default; -type HDEL = typeof import('./HDEL').default; -type HELLO = typeof import('./HELLO').default; -type HEXISTS = typeof import('./HEXISTS').default; -type HGET = typeof import('./HGET').default; -type HGETALL = typeof import('./HGETALL').default; -type HINCRBY = typeof import('./HINCRBY').default; -type HINCRBYFLOAT = typeof import('./HINCRBYFLOAT').default; -type HKEYS = typeof import('./HKEYS').default; -type HLEN = typeof import('./HLEN').default; -type HMGET = typeof import('./HMGET').default; -type HRANDFIELD_COUNT_WITHVALUES = typeof import('./HRANDFIELD_COUNT_WITHVALUES').default; -type HRANDFIELD_COUNT = typeof import('./HRANDFIELD_COUNT').default; -type HRANDFIELD = typeof import('./HRANDFIELD').default; -type HSCAN = typeof import('./HSCAN').default; -type HSET = typeof import('./HSET').default; -type HSETNX = typeof import('./HSETNX').default; -type HSTRLEN = typeof import('./HSTRLEN').default; -type HVALS = typeof import('./HVALS').default; -type INCR = typeof import('./INCR').default; -type INCRBY = typeof import('./INCRBY').default; -type INCRBYFLOAT = typeof import('./INCRBYFLOAT').default; -type INFO = typeof import('./INFO').default; -type KEYS = typeof import('./KEYS').default; -type LASTSAVE = typeof import('./LASTSAVE').default; -type LATENCY_DOCTOR = typeof import('./LATENCY_DOCTOR').default; -type LATENCY_GRAPH = typeof import('./LATENCY_GRAPH').default; -type LATENCY_LATEST = typeof import('./LATENCY_LATEST').default; -type LCS_IDX_WITHMATCHLEN = typeof import('./LCS_IDX_WITHMATCHLEN').default; -type LCS_IDX = typeof import('./LCS_IDX').default; -type LCS_LEN = typeof import('./LCS_LEN').default; -type LCS = typeof import('./LCS').default; -type LINDEX = typeof import('./LINDEX').default; -type LINSERT = typeof import('./LINSERT').default; -type LLEN = typeof import('./LLEN').default; -type LMOVE = typeof import('./LMOVE').default; -type LMPOP = typeof import('./LMPOP').default; -type LOLWUT = typeof import('./LOLWUT').default; -type LPOP_COUNT = typeof import('./LPOP_COUNT').default; -type LPOP = typeof import('./LPOP').default; -type LPOS_COUNT = typeof import('./LPOS_COUNT').default; -type LPOS = typeof import('./LPOS').default; -type LPUSH = typeof import('./LPUSH').default; -type LPUSHX = typeof import('./LPUSHX').default; -type LRANGE = typeof import('./LRANGE').default; -type LREM = typeof import('./LREM').default; -type LSET = typeof import('./LSET').default; -type LTRIM = typeof import('./LTRIM').default; -type MEMORY_DOCTOR = typeof import('./MEMORY_DOCTOR').default; -type MEMORY_MALLOC_STATS = typeof import('./MEMORY_MALLOC-STATS').default; -type MEMORY_PURGE = typeof import('./MEMORY_PURGE').default; -type MEMORY_STATS = typeof import('./MEMORY_STATS').default; -type MEMORY_USAGE = typeof import('./MEMORY_USAGE').default; -type MGET = typeof import('./MGET').default; -type MODULE_LIST = typeof import('./MODULE_LIST').default; -type MODULE_LOAD = typeof import('./MODULE_LOAD').default; -type MODULE_UNLOAD = typeof import('./MODULE_UNLOAD').default; -type MOVE = typeof import('./MOVE').default; -type MSET = typeof import('./MSET').default; -type MSETNX = typeof import('./MSETNX').default; -type OBJECT_ENCODING = typeof import('./OBJECT_ENCODING').default; -type OBJECT_FREQ = typeof import('./OBJECT_FREQ').default; -type OBJECT_IDLETIME = typeof import('./OBJECT_IDLETIME').default; -type OBJECT_REFCOUNT = typeof import('./OBJECT_REFCOUNT').default; -type PERSIST = typeof import('./PERSIST').default; -type PEXPIRE = typeof import('./PEXPIRE').default; -type PEXPIREAT = typeof import('./PEXPIREAT').default; -type PEXPIRETIME = typeof import('./PEXPIRETIME').default; -type PFADD = typeof import('./PFADD').default; -type PFCOUNT = typeof import('./PFCOUNT').default; -type PFMERGE = typeof import('./PFMERGE').default; -type PING = typeof import('./PING').default; -type PSETEX = typeof import('./PSETEX').default; -type PTTL = typeof import('./PTTL').default; -type PUBLISH = typeof import('./PUBLISH').default; -type PUBSUB_CHANNELS = typeof import('./PUBSUB_CHANNELS').default; -type PUBSUB_NUMPAT = typeof import('./PUBSUB_NUMPAT').default; -type PUBSUB_NUMSUB = typeof import('./PUBSUB_NUMSUB').default; -type PUBSUB_SHARDCHANNELS = typeof import('./PUBSUB_SHARDCHANNELS').default; -type RANDOMKEY = typeof import('./RANDOMKEY').default; -type READONLY = typeof import('./READONLY').default; -type RENAME = typeof import('./RENAME').default; -type RENAMENX = typeof import('./RENAMENX').default; -type RPOP_COUNT = typeof import('./RPOP_COUNT').default; -type ROLE = typeof import('./ROLE').default; -type RPOP = typeof import('./RPOP').default; -type RPOPLPUSH = typeof import('./RPOPLPUSH').default; -type RPUSH = typeof import('./RPUSH').default; -type RPUSHX = typeof import('./RPUSHX').default; -type SADD = typeof import('./SADD').default; -type SCAN = typeof import('./SCAN').default; -type SCARD = typeof import('./SCARD').default; -type SCRIPT_DEBUG = typeof import('./SCRIPT_DEBUG').default; -type SCRIPT_EXISTS = typeof import('./SCRIPT_EXISTS').default; -type SCRIPT_FLUSH = typeof import('./SCRIPT_FLUSH').default; -type SCRIPT_KILL = typeof import('./SCRIPT_KILL').default; -type SCRIPT_LOAD = typeof import('./SCRIPT_LOAD').default; -type SDIFF = typeof import('./SDIFF').default; -type SDIFFSTORE = typeof import('./SDIFFSTORE').default; -type SET = typeof import('./SET').default; -type SETBIT = typeof import('./SETBIT').default; -type SETEX = typeof import('./SETEX').default; -type SETNX = typeof import('./SETNX').default; -type SETRANGE = typeof import('./SETRANGE').default; -type SINTER = typeof import('./SINTER').default; -type SINTERCARD = typeof import('./SINTERCARD').default; -type SINTERSTORE = typeof import('./SINTERSTORE').default; -type SISMEMBER = typeof import('./SISMEMBER').default; -type SMEMBERS = typeof import('./SMEMBERS').default; -type SMISMEMBER = typeof import('./SMISMEMBER').default; -type SMOVE = typeof import('./SMOVE').default; -type SORT_RO = typeof import('./SORT_RO').default; -type SORT_STORE = typeof import('./SORT_STORE').default; -type SORT = typeof import('./SORT').default; -type SPOP_COUNT = typeof import('./SPOP_COUNT').default; -type SPOP = typeof import('./SPOP').default; -type SPUBLISH = typeof import('./SPUBLISH').default; -type SRANDMEMBER_COUNT = typeof import('./SRANDMEMBER_COUNT').default; -type SRANDMEMBER = typeof import('./SRANDMEMBER').default; -type SREM = typeof import('./SREM').default; -type SSCAN = typeof import('./SSCAN').default; -type STRLEN = typeof import('./STRLEN').default; -type SUNION = typeof import('./SUNION').default; -type SUNIONSTORE = typeof import('./SUNIONSTORE').default; -type SWAPDB = typeof import('./SWAPDB').default; -type TIME = typeof import('./TIME').default; -type TOUCH = typeof import('./TOUCH').default; -type TTL = typeof import('./TTL').default; -type TYPE = typeof import('./TYPE').default; -type UNLINK = typeof import('./UNLINK').default; -type UNWATCH = typeof import('./UNWATCH').default; -type WAIT = typeof import('./WAIT').default; -type WATCH = typeof import('./WATCH').default; -type XACK = typeof import('./XACK').default; -type XADD_NOMKSTREAM = typeof import('./XADD_NOMKSTREAM').default; -type XADD = typeof import('./XADD').default; -type XAUTOCLAIM_JUSTID = typeof import('./XAUTOCLAIM_JUSTID').default; -type XAUTOCLAIM = typeof import('./XAUTOCLAIM').default; -type XCLAIM_JUSTID = typeof import('./XCLAIM_JUSTID').default; -type XCLAIM = typeof import('./XCLAIM').default; -type XDEL = typeof import('./XDEL').default; -type XGROUP_CREATE = typeof import('./XGROUP_CREATE').default; -type XGROUP_CREATECONSUMER = typeof import('./XGROUP_CREATECONSUMER').default; -type XGROUP_DELCONSUMER = typeof import('./XGROUP_DELCONSUMER').default; -type XGROUP_DESTROY = typeof import('./XGROUP_DESTROY').default; -type XGROUP_SETID = typeof import('./XGROUP_SETID').default; -type XINFO_CONSUMERS = typeof import('./XINFO_CONSUMERS').default; -type XINFO_GROUPS = typeof import('./XINFO_GROUPS').default; -type XINFO_STREAM = typeof import('./XINFO_STREAM').default; -type XLEN = typeof import('./XLEN').default; -type XPENDING_RANGE = typeof import('./XPENDING_RANGE').default; -type XPENDING = typeof import('./XPENDING').default; -type XRANGE = typeof import('./XRANGE').default; -type XREAD = typeof import('./XREAD').default; -type XREADGROUP = typeof import('./XREADGROUP').default; -type XREVRANGE = typeof import('./XREVRANGE').default; -type XSETID = typeof import('./XSETID').default; -type XTRIM = typeof import('./XTRIM').default; -type ZADD_INCR = typeof import('./ZADD_INCR').default; -type ZADD = typeof import('./ZADD').default; -type ZCARD = typeof import('./ZCARD').default; -type ZCOUNT = typeof import('./ZCOUNT').default; -type ZDIFF_WITHSCORES = typeof import('./ZDIFF_WITHSCORES').default; -type ZDIFF = typeof import('./ZDIFF').default; -type ZDIFFSTORE = typeof import('./ZDIFFSTORE').default; -type ZINCRBY = typeof import('./ZINCRBY').default; -type ZINTER_WITHSCORES = typeof import('./ZINTER_WITHSCORES').default; -type ZINTER = typeof import('./ZINTER').default; -type ZINTERCARD = typeof import('./ZINTERCARD').default; -type ZINTERSTORE = typeof import('./ZINTERSTORE').default; -type ZLEXCOUNT = typeof import('./ZLEXCOUNT').default; -type ZMPOP = typeof import('./ZMPOP').default; -type ZMSCORE = typeof import('./ZMSCORE').default; -type ZPOPMAX_COUNT = typeof import('./ZPOPMAX_COUNT').default; -type ZPOPMAX = typeof import('./ZPOPMAX').default; -type ZPOPMIN_COUNT = typeof import('./ZPOPMIN_COUNT').default; -type ZPOPMIN = typeof import('./ZPOPMIN').default; -type ZRANDMEMBER_COUNT_WITHSCORES = typeof import('./ZRANDMEMBER_COUNT_WITHSCORES').default; -type ZRANDMEMBER_COUNT = typeof import('./ZRANDMEMBER_COUNT').default; -type ZRANDMEMBER = typeof import('./ZRANDMEMBER').default; -type ZRANGE_WITHSCORES = typeof import('./ZRANGE_WITHSCORES').default; -type ZRANGE = typeof import('./ZRANGE').default; -type ZRANGEBYLEX = typeof import('./ZRANGEBYLEX').default; -type ZRANGEBYSCORE_WITHSCORES = typeof import('./ZRANGEBYSCORE_WITHSCORES').default; -type ZRANGEBYSCORE = typeof import('./ZRANGEBYSCORE').default; -type ZRANGESTORE = typeof import('./ZRANGESTORE').default; -type ZREMRANGEBYSCORE = typeof import('./ZREMRANGEBYSCORE').default; -type ZRANK_WITHSCORE = typeof import('./ZRANK_WITHSCORE').default; -type ZRANK = typeof import('./ZRANK').default; -type ZREM = typeof import('./ZREM').default; -type ZREMRANGEBYLEX = typeof import('./ZREMRANGEBYLEX').default; -type ZREMRANGEBYRANK = typeof import('./ZREMRANGEBYRANK').default; -type ZREVRANK = typeof import('./ZREVRANK').default; -type ZSCAN = typeof import('./ZSCAN').default; -type ZSCORE = typeof import('./ZSCORE').default; -type ZUNION_WITHSCORES = typeof import('./ZUNION_WITHSCORES').default; -type ZUNION = typeof import('./ZUNION').default; -type ZUNIONSTORE = typeof import('./ZUNIONSTORE').default; - export default { - ACL_CAT: ACL_CAT as ACL_CAT, - aclCat: ACL_CAT as ACL_CAT, - ACL_DELUSER: ACL_DELUSER as ACL_DELUSER, - aclDelUser: ACL_DELUSER as ACL_DELUSER, - ACL_DRYRUN: ACL_DRYRUN as ACL_DRYRUN, - aclDryRun: ACL_DRYRUN as ACL_DRYRUN, - ACL_GENPASS: ACL_GENPASS as ACL_GENPASS, - aclGenPass: ACL_GENPASS as ACL_GENPASS, - ACL_GETUSER: ACL_GETUSER as ACL_GETUSER, - aclGetUser: ACL_GETUSER as ACL_GETUSER, - ACL_LIST: ACL_LIST as ACL_LIST, - aclList: ACL_LIST as ACL_LIST, - ACL_LOAD: ACL_LOAD as ACL_LOAD, - aclLoad: ACL_LOAD as ACL_LOAD, - ACL_LOG_RESET: ACL_LOG_RESET as ACL_LOG_RESET, - aclLogReset: ACL_LOG_RESET as ACL_LOG_RESET, - ACL_LOG: ACL_LOG as ACL_LOG, - aclLog: ACL_LOG as ACL_LOG, - ACL_SAVE: ACL_SAVE as ACL_SAVE, - aclSave: ACL_SAVE as ACL_SAVE, - ACL_SETUSER: ACL_SETUSER as ACL_SETUSER, - aclSetUser: ACL_SETUSER as ACL_SETUSER, - ACL_USERS: ACL_USERS as ACL_USERS, - aclUsers: ACL_USERS as ACL_USERS, - ACL_WHOAMI: ACL_WHOAMI as ACL_WHOAMI, - aclWhoAmI: ACL_WHOAMI as ACL_WHOAMI, - APPEND: APPEND as APPEND, - append: APPEND as APPEND, - ASKING: ASKING as ASKING, - asking: ASKING as ASKING, - AUTH: AUTH as AUTH, - auth: AUTH as AUTH, - BGREWRITEAOF: BGREWRITEAOF as BGREWRITEAOF, - bgRewriteAof: BGREWRITEAOF as BGREWRITEAOF, - BGSAVE: BGSAVE as BGSAVE, - bgSave: BGSAVE as BGSAVE, - BITCOUNT: BITCOUNT as BITCOUNT, - bitCount: BITCOUNT as BITCOUNT, - BITFIELD_RO: BITFIELD_RO as BITFIELD_RO, - bitFieldRo: BITFIELD_RO as BITFIELD_RO, - BITFIELD: BITFIELD as BITFIELD, - bitField: BITFIELD as BITFIELD, - BITOP: BITOP as BITOP, - bitOp: BITOP as BITOP, - BITPOS: BITPOS as BITPOS, - bitPos: BITPOS as BITPOS, - BLMOVE: BLMOVE as BLMOVE, - blMove: BLMOVE as BLMOVE, - BLMPOP: BLMPOP as BLMPOP, - blmPop: BLMPOP as BLMPOP, - BLPOP: BLPOP as BLPOP, - blPop: BLPOP as BLPOP, - BRPOP: BRPOP as BRPOP, - brPop: BRPOP as BRPOP, - BRPOPLPUSH: BRPOPLPUSH as BRPOPLPUSH, - brPopLPush: BRPOPLPUSH as BRPOPLPUSH, - BZMPOP: BZMPOP as BZMPOP, - bzmPop: BZMPOP as BZMPOP, - BZPOPMAX: BZPOPMAX as BZPOPMAX, - bzPopMax: BZPOPMAX as BZPOPMAX, - BZPOPMIN: BZPOPMIN as BZPOPMIN, - bzPopMin: BZPOPMIN as BZPOPMIN, - CLIENT_CACHING: CLIENT_CACHING as CLIENT_CACHING, - clientCaching: CLIENT_CACHING as CLIENT_CACHING, - CLIENT_GETNAME: CLIENT_GETNAME as CLIENT_GETNAME, - clientGetName: CLIENT_GETNAME as CLIENT_GETNAME, - CLIENT_GETREDIR: CLIENT_GETREDIR as CLIENT_GETREDIR, - clientGetRedir: CLIENT_GETREDIR as CLIENT_GETREDIR, - CLIENT_ID: CLIENT_ID as CLIENT_ID, - clientId: CLIENT_ID as CLIENT_ID, - CLIENT_INFO: CLIENT_INFO as CLIENT_INFO, - clientInfo: CLIENT_INFO as CLIENT_INFO, - CLIENT_KILL: CLIENT_KILL as CLIENT_KILL, - clientKill: CLIENT_KILL as CLIENT_KILL, - CLIENT_LIST: CLIENT_LIST as CLIENT_LIST, - clientList: CLIENT_LIST as CLIENT_LIST, - 'CLIENT_NO-EVICT': CLIENT_NO_EVICT as CLIENT_NO_EVICT, - clientNoEvict: CLIENT_NO_EVICT as CLIENT_NO_EVICT, - CLIENT_PAUSE: CLIENT_PAUSE as CLIENT_PAUSE, - clientPause: CLIENT_PAUSE as CLIENT_PAUSE, - CLIENT_SETNAME: CLIENT_SETNAME as CLIENT_SETNAME, - clientSetName: CLIENT_SETNAME as CLIENT_SETNAME, - CLIENT_TRACKING: CLIENT_TRACKING as CLIENT_TRACKING, - clientTracking: CLIENT_TRACKING as CLIENT_TRACKING, - CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO as CLIENT_TRACKINGINFO, - clientTrackingInfo: CLIENT_TRACKINGINFO as CLIENT_TRACKINGINFO, - CLIENT_UNPAUSE: CLIENT_UNPAUSE as CLIENT_UNPAUSE, - clientUnpause: CLIENT_UNPAUSE as CLIENT_UNPAUSE, - CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS as CLUSTER_ADDSLOTS, - clusterAddSlots: CLUSTER_ADDSLOTS as CLUSTER_ADDSLOTS, - CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE as CLUSTER_ADDSLOTSRANGE, - clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE as CLUSTER_ADDSLOTSRANGE, - CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH as CLUSTER_BUMPEPOCH, - clusterBumpEpoch: CLUSTER_BUMPEPOCH as CLUSTER_BUMPEPOCH, - 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS as CLUSTER_COUNT_FAILURE_REPORTS, - clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS as CLUSTER_COUNT_FAILURE_REPORTS, - CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT as CLUSTER_COUNTKEYSINSLOT, - clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT as CLUSTER_COUNTKEYSINSLOT, - CLUSTER_DELSLOTS: CLUSTER_DELSLOTS as CLUSTER_DELSLOTS, - clusterDelSlots: CLUSTER_DELSLOTS as CLUSTER_DELSLOTS, - CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE as CLUSTER_DELSLOTSRANGE, - clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE as CLUSTER_DELSLOTSRANGE, - CLUSTER_FAILOVER: CLUSTER_FAILOVER as CLUSTER_FAILOVER, - clusterFailover: CLUSTER_FAILOVER as CLUSTER_FAILOVER, - CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS as CLUSTER_FLUSHSLOTS, - clusterFlushSlots: CLUSTER_FLUSHSLOTS as CLUSTER_FLUSHSLOTS, - CLUSTER_FORGET: CLUSTER_FORGET as CLUSTER_FORGET, - clusterForget: CLUSTER_FORGET as CLUSTER_FORGET, - CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT as CLUSTER_GETKEYSINSLOT, - clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT as CLUSTER_GETKEYSINSLOT, + ACL_CAT, + aclCat: ACL_CAT, + ACL_DELUSER, + aclDelUser: ACL_DELUSER, + ACL_DRYRUN, + aclDryRun: ACL_DRYRUN, + ACL_GENPASS, + aclGenPass: ACL_GENPASS, + ACL_GETUSER, + aclGetUser: ACL_GETUSER, + ACL_LIST, + aclList: ACL_LIST, + ACL_LOAD, + aclLoad: ACL_LOAD, + ACL_LOG_RESET, + aclLogReset: ACL_LOG_RESET, + ACL_LOG, + aclLog: ACL_LOG, + ACL_SAVE, + aclSave: ACL_SAVE, + ACL_SETUSER, + aclSetUser: ACL_SETUSER, + ACL_USERS, + aclUsers: ACL_USERS, + ACL_WHOAMI, + aclWhoAmI: ACL_WHOAMI, + APPEND, + append: APPEND, + ASKING, + asking: ASKING, + AUTH, + auth: AUTH, + BGREWRITEAOF, + bgRewriteAof: BGREWRITEAOF, + BGSAVE, + bgSave: BGSAVE, + BITCOUNT, + bitCount: BITCOUNT, + BITFIELD_RO, + bitFieldRo: BITFIELD_RO, + BITFIELD, + bitField: BITFIELD, + BITOP, + bitOp: BITOP, + BITPOS, + bitPos: BITPOS, + BLMOVE, + blMove: BLMOVE, + BLMPOP, + blmPop: BLMPOP, + BLPOP, + blPop: BLPOP, + BRPOP, + brPop: BRPOP, + BRPOPLPUSH, + brPopLPush: BRPOPLPUSH, + BZMPOP, + bzmPop: BZMPOP, + BZPOPMAX, + bzPopMax: BZPOPMAX, + BZPOPMIN, + bzPopMin: BZPOPMIN, + CLIENT_CACHING, + clientCaching: CLIENT_CACHING, + CLIENT_GETNAME, + clientGetName: CLIENT_GETNAME, + CLIENT_GETREDIR, + clientGetRedir: CLIENT_GETREDIR, + CLIENT_ID, + clientId: CLIENT_ID, + CLIENT_INFO, + clientInfo: CLIENT_INFO, + CLIENT_KILL, + clientKill: CLIENT_KILL, + CLIENT_LIST, + clientList: CLIENT_LIST, + 'CLIENT_NO-EVICT': CLIENT_NO_EVICT, + clientNoEvict: CLIENT_NO_EVICT, + CLIENT_PAUSE, + clientPause: CLIENT_PAUSE, + CLIENT_SETNAME, + clientSetName: CLIENT_SETNAME, + CLIENT_TRACKING, + clientTracking: CLIENT_TRACKING, + CLIENT_TRACKINGINFO, + clientTrackingInfo: CLIENT_TRACKINGINFO, + CLIENT_UNPAUSE, + clientUnpause: CLIENT_UNPAUSE, + CLUSTER_ADDSLOTS, + clusterAddSlots: CLUSTER_ADDSLOTS, + CLUSTER_ADDSLOTSRANGE, + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE, + CLUSTER_BUMPEPOCH, + clusterBumpEpoch: CLUSTER_BUMPEPOCH, + 'CLUSTER_COUNT-FAILURE-REPORTS': CLUSTER_COUNT_FAILURE_REPORTS, + clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS, + CLUSTER_COUNTKEYSINSLOT, + clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT, + CLUSTER_DELSLOTS, + clusterDelSlots: CLUSTER_DELSLOTS, + CLUSTER_DELSLOTSRANGE, + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE, + CLUSTER_FAILOVER, + clusterFailover: CLUSTER_FAILOVER, + CLUSTER_FLUSHSLOTS, + clusterFlushSlots: CLUSTER_FLUSHSLOTS, + CLUSTER_FORGET, + clusterForget: CLUSTER_FORGET, + CLUSTER_GETKEYSINSLOT, + clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT, // CLUSTER_INFO, - // clusterInfo: CLUSTER_INFO as CLUSTER_INFO, - CLUSTER_KEYSLOT: CLUSTER_KEYSLOT as CLUSTER_KEYSLOT, - clusterKeySlot: CLUSTER_KEYSLOT as CLUSTER_KEYSLOT, - CLUSTER_LINKS: CLUSTER_LINKS as CLUSTER_LINKS, - clusterLinks: CLUSTER_LINKS as CLUSTER_LINKS, - CLUSTER_MEET: CLUSTER_MEET as CLUSTER_MEET, - clusterMeet: CLUSTER_MEET as CLUSTER_MEET, - CLUSTER_MYID: CLUSTER_MYID as CLUSTER_MYID, - clusterMyId: CLUSTER_MYID as CLUSTER_MYID, + // clusterInfo: CLUSTER_INFO, + CLUSTER_KEYSLOT, + clusterKeySlot: CLUSTER_KEYSLOT, + CLUSTER_LINKS, + clusterLinks: CLUSTER_LINKS, + CLUSTER_MEET, + clusterMeet: CLUSTER_MEET, + CLUSTER_MYID, + clusterMyId: CLUSTER_MYID, // CLUSTER_NODES, - // clusterNodes: CLUSTER_NODES as CLUSTER_NODES, + // clusterNodes: CLUSTER_NODES, // CLUSTER_REPLICAS, - // clusterReplicas: CLUSTER_REPLICAS as CLUSTER_REPLICAS, - CLUSTER_REPLICATE: CLUSTER_REPLICATE as CLUSTER_REPLICATE, - clusterReplicate: CLUSTER_REPLICATE as CLUSTER_REPLICATE, - CLUSTER_RESET: CLUSTER_RESET as CLUSTER_RESET, - clusterReset: CLUSTER_RESET as CLUSTER_RESET, - CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG as CLUSTER_SAVECONFIG, - clusterSaveConfig: CLUSTER_SAVECONFIG as CLUSTER_SAVECONFIG, - 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH as CLUSTER_SET_CONFIG_EPOCH, - clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH as CLUSTER_SET_CONFIG_EPOCH, - CLUSTER_SETSLOT: CLUSTER_SETSLOT as CLUSTER_SETSLOT, - clusterSetSlot: CLUSTER_SETSLOT as CLUSTER_SETSLOT, - CLUSTER_SLOTS: CLUSTER_SLOTS as CLUSTER_SLOTS, - clusterSlots: CLUSTER_SLOTS as CLUSTER_SLOTS, - COMMAND_COUNT: COMMAND_COUNT as COMMAND_COUNT, - commandCount: COMMAND_COUNT as COMMAND_COUNT, - COMMAND_GETKEYS: COMMAND_GETKEYS as COMMAND_GETKEYS, - commandGetKeys: COMMAND_GETKEYS as COMMAND_GETKEYS, - COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS as COMMAND_GETKEYSANDFLAGS, - commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS as COMMAND_GETKEYSANDFLAGS, + // clusterReplicas: CLUSTER_REPLICAS, + CLUSTER_REPLICATE, + clusterReplicate: CLUSTER_REPLICATE, + CLUSTER_RESET, + clusterReset: CLUSTER_RESET, + CLUSTER_SAVECONFIG, + clusterSaveConfig: CLUSTER_SAVECONFIG, + 'CLUSTER_SET-CONFIG-EPOCH': CLUSTER_SET_CONFIG_EPOCH, + clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH, + CLUSTER_SETSLOT, + clusterSetSlot: CLUSTER_SETSLOT, + CLUSTER_SLOTS, + clusterSlots: CLUSTER_SLOTS, + COMMAND_COUNT, + commandCount: COMMAND_COUNT, + COMMAND_GETKEYS, + commandGetKeys: COMMAND_GETKEYS, + COMMAND_GETKEYSANDFLAGS, + commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS, // COMMAND_INFO, - // commandInfo: COMMAND_INFO as COMMAND_INFO, + // commandInfo: COMMAND_INFO, // COMMAND_LIST, - // commandList: COMMAND_LIST as COMMAND_LIST, + // commandList: COMMAND_LIST, // COMMAND, - // command: COMMAND as COMMAND, - CONFIG_GET: CONFIG_GET as CONFIG_GET, - configGet: CONFIG_GET as CONFIG_GET, - CONFIG_RESETASTAT: CONFIG_RESETASTAT as CONFIG_RESETASTAT, - configResetStat: CONFIG_RESETASTAT as CONFIG_RESETASTAT, - CONFIG_REWRITE: CONFIG_REWRITE as CONFIG_REWRITE, - configRewrite: CONFIG_REWRITE as CONFIG_REWRITE, - CONFIG_SET: CONFIG_SET as CONFIG_SET, - configSet: CONFIG_SET as CONFIG_SET, - COPY: COPY as COPY, - copy: COPY as COPY, - DBSIZE: DBSIZE as DBSIZE, - dbSize: DBSIZE as DBSIZE, - DECR: DECR as DECR, - decr: DECR as DECR, - DECRBY: DECRBY as DECRBY, - decrBy: DECRBY as DECRBY, - DEL: DEL as DEL, - del: DEL as DEL, - DUMP: DUMP as DUMP, - dump: DUMP as DUMP, - ECHO: ECHO as ECHO, - echo: ECHO as ECHO, - EVAL_RO: EVAL_RO as EVAL_RO, - evalRo: EVAL_RO as EVAL_RO, - EVAL: EVAL as EVAL, - eval: EVAL as EVAL, - EVALSHA_RO: EVALSHA_RO as EVALSHA_RO, - evalShaRo: EVALSHA_RO as EVALSHA_RO, - EVALSHA: EVALSHA as EVALSHA, - evalSha: EVALSHA as EVALSHA, - EXISTS: EXISTS as EXISTS, - exists: EXISTS as EXISTS, - EXPIRE: EXPIRE as EXPIRE, - expire: EXPIRE as EXPIRE, - EXPIREAT: EXPIREAT as EXPIREAT, - expireAt: EXPIREAT as EXPIREAT, - EXPIRETIME: EXPIRETIME as EXPIRETIME, - expireTime: EXPIRETIME as EXPIRETIME, - FLUSHALL: FLUSHALL as FLUSHALL, - flushAll: FLUSHALL as FLUSHALL, - FLUSHDB: FLUSHDB as FLUSHDB, - flushDb: FLUSHDB as FLUSHDB, - FCALL: FCALL as FCALL, - fCall: FCALL as FCALL, - FCALL_RO: FCALL_RO as FCALL_RO, - fCallRo: FCALL_RO as FCALL_RO, - FUNCTION_DELETE: FUNCTION_DELETE as FUNCTION_DELETE, - functionDelete: FUNCTION_DELETE as FUNCTION_DELETE, - FUNCTION_DUMP: FUNCTION_DUMP as FUNCTION_DUMP, - functionDump: FUNCTION_DUMP as FUNCTION_DUMP, - FUNCTION_FLUSH: FUNCTION_FLUSH as FUNCTION_FLUSH, - functionFlush: FUNCTION_FLUSH as FUNCTION_FLUSH, - FUNCTION_KILL: FUNCTION_KILL as FUNCTION_KILL, - functionKill: FUNCTION_KILL as FUNCTION_KILL, - FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE as FUNCTION_LIST_WITHCODE, - functionListWithCode: FUNCTION_LIST_WITHCODE as FUNCTION_LIST_WITHCODE, - FUNCTION_LIST: FUNCTION_LIST as FUNCTION_LIST, - functionList: FUNCTION_LIST as FUNCTION_LIST, - FUNCTION_LOAD: FUNCTION_LOAD as FUNCTION_LOAD, - functionLoad: FUNCTION_LOAD as FUNCTION_LOAD, - FUNCTION_RESTORE: FUNCTION_RESTORE as FUNCTION_RESTORE, - functionRestore: FUNCTION_RESTORE as FUNCTION_RESTORE, + // command: COMMAND, + CONFIG_GET, + configGet: CONFIG_GET, + CONFIG_RESETASTAT, + configResetStat: CONFIG_RESETASTAT, + CONFIG_REWRITE, + configRewrite: CONFIG_REWRITE, + CONFIG_SET, + configSet: CONFIG_SET, + COPY, + copy: COPY, + DBSIZE, + dbSize: DBSIZE, + DECR, + decr: DECR, + DECRBY, + decrBy: DECRBY, + DEL, + del: DEL, + DUMP, + dump: DUMP, + ECHO, + echo: ECHO, + EVAL_RO, + evalRo: EVAL_RO, + EVAL, + eval: EVAL, + EVALSHA_RO, + evalShaRo: EVALSHA_RO, + EVALSHA, + evalSha: EVALSHA, + EXISTS, + exists: EXISTS, + EXPIRE, + expire: EXPIRE, + EXPIREAT, + expireAt: EXPIREAT, + EXPIRETIME, + expireTime: EXPIRETIME, + FLUSHALL, + flushAll: FLUSHALL, + FLUSHDB, + flushDb: FLUSHDB, + FCALL, + fCall: FCALL, + FCALL_RO, + fCallRo: FCALL_RO, + FUNCTION_DELETE, + functionDelete: FUNCTION_DELETE, + FUNCTION_DUMP, + functionDump: FUNCTION_DUMP, + FUNCTION_FLUSH, + functionFlush: FUNCTION_FLUSH, + FUNCTION_KILL, + functionKill: FUNCTION_KILL, + FUNCTION_LIST_WITHCODE, + functionListWithCode: FUNCTION_LIST_WITHCODE, + FUNCTION_LIST, + functionList: FUNCTION_LIST, + FUNCTION_LOAD, + functionLoad: FUNCTION_LOAD, + FUNCTION_RESTORE, + functionRestore: FUNCTION_RESTORE, // FUNCTION_STATS, - // functionStats: FUNCTION_STATS as FUNCTION_STATS, - GEOADD: GEOADD as GEOADD, - geoAdd: GEOADD as GEOADD, - GEODIST: GEODIST as GEODIST, - geoDist: GEODIST as GEODIST, - GEOHASH: GEOHASH as GEOHASH, - geoHash: GEOHASH as GEOHASH, - GEOPOS: GEOPOS as GEOPOS, - geoPos: GEOPOS as GEOPOS, - GEORADIUS_RO_WITH: GEORADIUS_RO_WITH as GEORADIUS_RO_WITH, - geoRadiusRoWith: GEORADIUS_RO_WITH as GEORADIUS_RO_WITH, - GEORADIUS_RO: GEORADIUS_RO as GEORADIUS_RO, - geoRadiusRo: GEORADIUS_RO as GEORADIUS_RO, - GEORADIUS_STORE: GEORADIUS_STORE as GEORADIUS_STORE, - geoRadiusStore: GEORADIUS_STORE as GEORADIUS_STORE, - GEORADIUS_WITH: GEORADIUS_WITH as GEORADIUS_WITH, - geoRadiusWith: GEORADIUS_WITH as GEORADIUS_WITH, - GEORADIUS: GEORADIUS as GEORADIUS, - geoRadius: GEORADIUS as GEORADIUS, - GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH as GEORADIUSBYMEMBER_RO_WITH, - geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH as GEORADIUSBYMEMBER_RO_WITH, - GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO as GEORADIUSBYMEMBER_RO, - geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO as GEORADIUSBYMEMBER_RO, - GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE as GEORADIUSBYMEMBER_STORE, - geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE as GEORADIUSBYMEMBER_STORE, - GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH as GEORADIUSBYMEMBER_WITH, - geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH as GEORADIUSBYMEMBER_WITH, - GEORADIUSBYMEMBER: GEORADIUSBYMEMBER as GEORADIUSBYMEMBER, - geoRadiusByMember: GEORADIUSBYMEMBER as GEORADIUSBYMEMBER, - GEOSEARCH_WITH: GEOSEARCH_WITH as GEOSEARCH_WITH, - geoSearchWith: GEOSEARCH_WITH as GEOSEARCH_WITH, - GEOSEARCH: GEOSEARCH as GEOSEARCH, - geoSearch: GEOSEARCH as GEOSEARCH, - GEOSEARCHSTORE: GEOSEARCHSTORE as GEOSEARCHSTORE, - geoSearchStore: GEOSEARCHSTORE as GEOSEARCHSTORE, - GET: GET as GET, - get: GET as GET, - GETBIT: GETBIT as GETBIT, - getBit: GETBIT as GETBIT, - GETDEL: GETDEL as GETDEL, - getDel: GETDEL as GETDEL, - GETEX: GETEX as GETEX, - getEx: GETEX as GETEX, - GETRANGE: GETRANGE as GETRANGE, - getRange: GETRANGE as GETRANGE, - GETSET: GETSET as GETSET, - getSet: GETSET as GETSET, - HDEL: HDEL as HDEL, - hDel: HDEL as HDEL, - HELLO: HELLO as HELLO, - hello: HELLO as HELLO, - HEXISTS: HEXISTS as HEXISTS, - hExists: HEXISTS as HEXISTS, - HGET: HGET as HGET, - hGet: HGET as HGET, - HGETALL: HGETALL as HGETALL, - hGetAll: HGETALL as HGETALL, - HINCRBY: HINCRBY as HINCRBY, - hIncrBy: HINCRBY as HINCRBY, - HINCRBYFLOAT: HINCRBYFLOAT as HINCRBYFLOAT, - hIncrByFloat: HINCRBYFLOAT as HINCRBYFLOAT, - HKEYS: HKEYS as HKEYS, - hKeys: HKEYS as HKEYS, - HLEN: HLEN as HLEN, - hLen: HLEN as HLEN, - HMGET: HMGET as HMGET, - hmGet: HMGET as HMGET, - HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES as HRANDFIELD_COUNT_WITHVALUES, - hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES as HRANDFIELD_COUNT_WITHVALUES, - HRANDFIELD_COUNT: HRANDFIELD_COUNT as HRANDFIELD_COUNT, - hRandFieldCount: HRANDFIELD_COUNT as HRANDFIELD_COUNT, - HRANDFIELD: HRANDFIELD as HRANDFIELD, - hRandField: HRANDFIELD as HRANDFIELD, - HSCAN: HSCAN as HSCAN, - hScan: HSCAN as HSCAN, - HSET: HSET as HSET, - hSet: HSET as HSET, - HSETNX: HSETNX as HSETNX, - hSetNX: HSETNX as HSETNX, - HSTRLEN: HSTRLEN as HSTRLEN, - hStrLen: HSTRLEN as HSTRLEN, - HVALS: HVALS as HVALS, - hVals: HVALS as HVALS, - INCR: INCR as INCR, - incr: INCR as INCR, - INCRBY: INCRBY as INCRBY, - incrBy: INCRBY as INCRBY, - INCRBYFLOAT: INCRBYFLOAT as INCRBYFLOAT, - incrByFloat: INCRBYFLOAT as INCRBYFLOAT, - INFO: INFO as INFO, - info: INFO as INFO, - KEYS: KEYS as KEYS, - keys: KEYS as KEYS, - LASTSAVE: LASTSAVE as LASTSAVE, - lastSave: LASTSAVE as LASTSAVE, - LATENCY_DOCTOR: LATENCY_DOCTOR as LATENCY_DOCTOR, - latencyDoctor: LATENCY_DOCTOR as LATENCY_DOCTOR, - LATENCY_GRAPH: LATENCY_GRAPH as LATENCY_GRAPH, - latencyGraph: LATENCY_GRAPH as LATENCY_GRAPH, - LATENCY_LATEST: LATENCY_LATEST as LATENCY_LATEST, - latencyLatest: LATENCY_LATEST as LATENCY_LATEST, - LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN as LCS_IDX_WITHMATCHLEN, - lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN as LCS_IDX_WITHMATCHLEN, - LCS_IDX: LCS_IDX as LCS_IDX, - lcsIdx: LCS_IDX as LCS_IDX, - LCS_LEN: LCS_LEN as LCS_LEN, - lcsLen: LCS_LEN as LCS_LEN, - LCS: LCS as LCS, - lcs: LCS as LCS, - LINDEX: LINDEX as LINDEX, - lIndex: LINDEX as LINDEX, - LINSERT: LINSERT as LINSERT, - lInsert: LINSERT as LINSERT, - LLEN: LLEN as LLEN, - lLen: LLEN as LLEN, - LMOVE: LMOVE as LMOVE, - lMove: LMOVE as LMOVE, - LMPOP: LMPOP as LMPOP, - lmPop: LMPOP as LMPOP, - LOLWUT: LOLWUT as LOLWUT, - LPOP_COUNT: LPOP_COUNT as LPOP_COUNT, - lPopCount: LPOP_COUNT as LPOP_COUNT, - LPOP: LPOP as LPOP, - lPop: LPOP as LPOP, - LPOS_COUNT: LPOS_COUNT as LPOS_COUNT, - lPosCount: LPOS_COUNT as LPOS_COUNT, - LPOS: LPOS as LPOS, - lPos: LPOS as LPOS, - LPUSH: LPUSH as LPUSH, - lPush: LPUSH as LPUSH, - LPUSHX: LPUSHX as LPUSHX, - lPushX: LPUSHX as LPUSHX, - LRANGE: LRANGE as LRANGE, - lRange: LRANGE as LRANGE, - LREM: LREM as LREM, - lRem: LREM as LREM, - LSET: LSET as LSET, - lSet: LSET as LSET, - LTRIM: LTRIM as LTRIM, - lTrim: LTRIM as LTRIM, - MEMORY_DOCTOR: MEMORY_DOCTOR as MEMORY_DOCTOR, - memoryDoctor: MEMORY_DOCTOR as MEMORY_DOCTOR, - 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS as MEMORY_MALLOC_STATS, - memoryMallocStats: MEMORY_MALLOC_STATS as MEMORY_MALLOC_STATS, - MEMORY_PURGE: MEMORY_PURGE as MEMORY_PURGE, - memoryPurge: MEMORY_PURGE as MEMORY_PURGE, - MEMORY_STATS: MEMORY_STATS as MEMORY_STATS, - memoryStats: MEMORY_STATS as MEMORY_STATS, - MEMORY_USAGE: MEMORY_USAGE as MEMORY_USAGE, - memoryUsage: MEMORY_USAGE as MEMORY_USAGE, - MGET: MGET as MGET, - mGet: MGET as MGET, - MODULE_LIST: MODULE_LIST as MODULE_LIST, - moduleList: MODULE_LIST as MODULE_LIST, - MODULE_LOAD: MODULE_LOAD as MODULE_LOAD, - moduleLoad: MODULE_LOAD as MODULE_LOAD, - MODULE_UNLOAD: MODULE_UNLOAD as MODULE_UNLOAD, - moduleUnload: MODULE_UNLOAD as MODULE_UNLOAD, - MOVE: MOVE as MOVE, - move: MOVE as MOVE, - MSET: MSET as MSET, - mSet: MSET as MSET, - MSETNX: MSETNX as MSETNX, - mSetNX: MSETNX as MSETNX, - OBJECT_ENCODING: OBJECT_ENCODING as OBJECT_ENCODING, - objectEncoding: OBJECT_ENCODING as OBJECT_ENCODING, - OBJECT_FREQ: OBJECT_FREQ as OBJECT_FREQ, - objectFreq: OBJECT_FREQ as OBJECT_FREQ, - OBJECT_IDLETIME: OBJECT_IDLETIME as OBJECT_IDLETIME, - objectIdleTime: OBJECT_IDLETIME as OBJECT_IDLETIME, - OBJECT_REFCOUNT: OBJECT_REFCOUNT as OBJECT_REFCOUNT, - objectRefCount: OBJECT_REFCOUNT as OBJECT_REFCOUNT, - PERSIST: PERSIST as PERSIST, - persist: PERSIST as PERSIST, - PEXPIRE: PEXPIRE as PEXPIRE, - pExpire: PEXPIRE as PEXPIRE, - PEXPIREAT: PEXPIREAT as PEXPIREAT, - pExpireAt: PEXPIREAT as PEXPIREAT, - PEXPIRETIME: PEXPIRETIME as PEXPIRETIME, - pExpireTime: PEXPIRETIME as PEXPIRETIME, - PFADD: PFADD as PFADD, - pfAdd: PFADD as PFADD, - PFCOUNT: PFCOUNT as PFCOUNT, - pfCount: PFCOUNT as PFCOUNT, - PFMERGE: PFMERGE as PFMERGE, - pfMerge: PFMERGE as PFMERGE, - PING: PING as PING, + // functionStats: FUNCTION_STATS, + GEOADD, + geoAdd: GEOADD, + GEODIST, + geoDist: GEODIST, + GEOHASH, + geoHash: GEOHASH, + GEOPOS, + geoPos: GEOPOS, + GEORADIUS_RO_WITH, + geoRadiusRoWith: GEORADIUS_RO_WITH, + GEORADIUS_RO, + geoRadiusRo: GEORADIUS_RO, + GEORADIUS_STORE, + geoRadiusStore: GEORADIUS_STORE, + GEORADIUS_WITH, + geoRadiusWith: GEORADIUS_WITH, + GEORADIUS, + geoRadius: GEORADIUS, + GEORADIUSBYMEMBER_RO_WITH, + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH, + GEORADIUSBYMEMBER_RO, + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO, + GEORADIUSBYMEMBER_STORE, + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE, + GEORADIUSBYMEMBER_WITH, + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH, + GEORADIUSBYMEMBER, + geoRadiusByMember: GEORADIUSBYMEMBER, + GEOSEARCH_WITH, + geoSearchWith: GEOSEARCH_WITH, + GEOSEARCH, + geoSearch: GEOSEARCH, + GEOSEARCHSTORE, + geoSearchStore: GEOSEARCHSTORE, + GET, + get: GET, + GETBIT, + getBit: GETBIT, + GETDEL, + getDel: GETDEL, + GETEX, + getEx: GETEX, + GETRANGE, + getRange: GETRANGE, + GETSET, + getSet: GETSET, + HDEL, + hDel: HDEL, + HELLO, + hello: HELLO, + HEXISTS, + hExists: HEXISTS, + HGET, + hGet: HGET, + HGETALL, + hGetAll: HGETALL, + HINCRBY, + hIncrBy: HINCRBY, + HINCRBYFLOAT, + hIncrByFloat: HINCRBYFLOAT, + HKEYS, + hKeys: HKEYS, + HLEN, + hLen: HLEN, + HMGET, + hmGet: HMGET, + HRANDFIELD_COUNT_WITHVALUES, + hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, + HRANDFIELD_COUNT, + hRandFieldCount: HRANDFIELD_COUNT, + HRANDFIELD, + hRandField: HRANDFIELD, + HSCAN, + hScan: HSCAN, + HSET, + hSet: HSET, + HSETNX, + hSetNX: HSETNX, + HSTRLEN, + hStrLen: HSTRLEN, + HVALS, + hVals: HVALS, + INCR, + incr: INCR, + INCRBY, + incrBy: INCRBY, + INCRBYFLOAT, + incrByFloat: INCRBYFLOAT, + INFO, + info: INFO, + KEYS, + keys: KEYS, + LASTSAVE, + lastSave: LASTSAVE, + LATENCY_DOCTOR, + latencyDoctor: LATENCY_DOCTOR, + LATENCY_GRAPH, + latencyGraph: LATENCY_GRAPH, + LATENCY_LATEST, + latencyLatest: LATENCY_LATEST, + LCS_IDX_WITHMATCHLEN, + lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN, + LCS_IDX, + lcsIdx: LCS_IDX, + LCS_LEN, + lcsLen: LCS_LEN, + LCS, + lcs: LCS, + LINDEX, + lIndex: LINDEX, + LINSERT, + lInsert: LINSERT, + LLEN, + lLen: LLEN, + LMOVE, + lMove: LMOVE, + LMPOP, + lmPop: LMPOP, + LOLWUT, + LPOP_COUNT, + lPopCount: LPOP_COUNT, + LPOP, + lPop: LPOP, + LPOS_COUNT, + lPosCount: LPOS_COUNT, + LPOS, + lPos: LPOS, + LPUSH, + lPush: LPUSH, + LPUSHX, + lPushX: LPUSHX, + LRANGE, + lRange: LRANGE, + LREM, + lRem: LREM, + LSET, + lSet: LSET, + LTRIM, + lTrim: LTRIM, + MEMORY_DOCTOR, + memoryDoctor: MEMORY_DOCTOR, + 'MEMORY_MALLOC-STATS': MEMORY_MALLOC_STATS, + memoryMallocStats: MEMORY_MALLOC_STATS, + MEMORY_PURGE, + memoryPurge: MEMORY_PURGE, + MEMORY_STATS, + memoryStats: MEMORY_STATS, + MEMORY_USAGE, + memoryUsage: MEMORY_USAGE, + MGET, + mGet: MGET, + MODULE_LIST, + moduleList: MODULE_LIST, + MODULE_LOAD, + moduleLoad: MODULE_LOAD, + MODULE_UNLOAD, + moduleUnload: MODULE_UNLOAD, + MOVE, + move: MOVE, + MSET, + mSet: MSET, + MSETNX, + mSetNX: MSETNX, + OBJECT_ENCODING, + objectEncoding: OBJECT_ENCODING, + OBJECT_FREQ, + objectFreq: OBJECT_FREQ, + OBJECT_IDLETIME, + objectIdleTime: OBJECT_IDLETIME, + OBJECT_REFCOUNT, + objectRefCount: OBJECT_REFCOUNT, + PERSIST, + persist: PERSIST, + PEXPIRE, + pExpire: PEXPIRE, + PEXPIREAT, + pExpireAt: PEXPIREAT, + PEXPIRETIME, + pExpireTime: PEXPIRETIME, + PFADD, + pfAdd: PFADD, + PFCOUNT, + pfCount: PFCOUNT, + PFMERGE, + pfMerge: PFMERGE, + PING, /** * ping jsdoc */ - ping: PING as PING, - PSETEX: PSETEX as PSETEX, - pSetEx: PSETEX as PSETEX, - PTTL: PTTL as PTTL, - pTTL: PTTL as PTTL, - PUBLISH: PUBLISH as PUBLISH, - publish: PUBLISH as PUBLISH, - PUBSUB_CHANNELS: PUBSUB_CHANNELS as PUBSUB_CHANNELS, - pubSubChannels: PUBSUB_CHANNELS as PUBSUB_CHANNELS, - PUBSUB_NUMPAT: PUBSUB_NUMPAT as PUBSUB_NUMPAT, - pubSubNumPat: PUBSUB_NUMPAT as PUBSUB_NUMPAT, - PUBSUB_NUMSUB: PUBSUB_NUMSUB as PUBSUB_NUMSUB, - pubSubNumSub: PUBSUB_NUMSUB as PUBSUB_NUMSUB, - PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS as PUBSUB_SHARDCHANNELS, - pubSubShardChannels: PUBSUB_SHARDCHANNELS as PUBSUB_SHARDCHANNELS, - RANDOMKEY: RANDOMKEY as RANDOMKEY, - randomKey: RANDOMKEY as RANDOMKEY, - READONLY: READONLY as READONLY, - readonly: READONLY as READONLY, - RENAME: RENAME as RENAME, - rename: RENAME as RENAME, - RENAMENX: RENAMENX as RENAMENX, - renameNX: RENAMENX as RENAMENX, - RPOP_COUNT: RPOP_COUNT as RPOP_COUNT, - rPopCount: RPOP_COUNT as RPOP_COUNT, - ROLE: ROLE as ROLE, - role: ROLE as ROLE, - RPOP: RPOP as RPOP, - rPop: RPOP as RPOP, - RPOPLPUSH: RPOPLPUSH as RPOPLPUSH, - rPopLPush: RPOPLPUSH as RPOPLPUSH, - RPUSH: RPUSH as RPUSH, - rPush: RPUSH as RPUSH, - RPUSHX: RPUSHX as RPUSHX, - rPushX: RPUSHX as RPUSHX, - SADD: SADD as SADD, - sAdd: SADD as SADD, - SCAN: SCAN as SCAN, - scan: SCAN as SCAN, - SCARD: SCARD as SCARD, - sCard: SCARD as SCARD, - SCRIPT_DEBUG: SCRIPT_DEBUG as SCRIPT_DEBUG, - scriptDebug: SCRIPT_DEBUG as SCRIPT_DEBUG, - SCRIPT_EXISTS: SCRIPT_EXISTS as SCRIPT_EXISTS, - scriptExists: SCRIPT_EXISTS as SCRIPT_EXISTS, - SCRIPT_FLUSH: SCRIPT_FLUSH as SCRIPT_FLUSH, - scriptFlush: SCRIPT_FLUSH as SCRIPT_FLUSH, - SCRIPT_KILL: SCRIPT_KILL as SCRIPT_KILL, - scriptKill: SCRIPT_KILL as SCRIPT_KILL, - SCRIPT_LOAD: SCRIPT_LOAD as SCRIPT_LOAD, - scriptLoad: SCRIPT_LOAD as SCRIPT_LOAD, - SDIFF: SDIFF as SDIFF, - sDiff: SDIFF as SDIFF, - SDIFFSTORE: SDIFFSTORE as SDIFFSTORE, - sDiffStore: SDIFFSTORE as SDIFFSTORE, - SET: SET as SET, - set: SET as SET, - SETBIT: SETBIT as SETBIT, - setBit: SETBIT as SETBIT, - SETEX: SETEX as SETEX, - setEx: SETEX as SETEX, - SETNX: SETNX as SETNX, - setNX: SETNX as SETNX, - SETRANGE: SETRANGE as SETRANGE, - setRange: SETRANGE as SETRANGE, - SINTER: SINTER as SINTER, - sInter: SINTER as SINTER, - SINTERCARD: SINTERCARD as SINTERCARD, - sInterCard: SINTERCARD as SINTERCARD, - SINTERSTORE: SINTERSTORE as SINTERSTORE, - sInterStore: SINTERSTORE as SINTERSTORE, - SISMEMBER: SISMEMBER as SISMEMBER, - sIsMember: SISMEMBER as SISMEMBER, - SMEMBERS: SMEMBERS as SMEMBERS, - sMembers: SMEMBERS as SMEMBERS, - SMISMEMBER: SMISMEMBER as SMISMEMBER, - smIsMember: SMISMEMBER as SMISMEMBER, - SMOVE: SMOVE as SMOVE, - sMove: SMOVE as SMOVE, - SORT_RO: SORT_RO as SORT_RO, - sortRo: SORT_RO as SORT_RO, - SORT_STORE: SORT_STORE as SORT_STORE, - sortStore: SORT_STORE as SORT_STORE, - SORT: SORT as SORT, - sort: SORT as SORT, - SPOP_COUNT: SPOP_COUNT as SPOP_COUNT, - sPopCount: SPOP_COUNT as SPOP_COUNT, - SPOP: SPOP as SPOP, - sPop: SPOP as SPOP, - SPUBLISH: SPUBLISH as SPUBLISH, - sPublish: SPUBLISH as SPUBLISH, - SRANDMEMBER_COUNT: SRANDMEMBER_COUNT as SRANDMEMBER_COUNT, - sRandMemberCount: SRANDMEMBER_COUNT as SRANDMEMBER_COUNT, - SRANDMEMBER: SRANDMEMBER as SRANDMEMBER, - sRandMember: SRANDMEMBER as SRANDMEMBER, - SREM: SREM as SREM, - sRem: SREM as SREM, - SSCAN: SSCAN as SSCAN, - sScan: SSCAN as SSCAN, - STRLEN: STRLEN as STRLEN, - strLen: STRLEN as STRLEN, - SUNION: SUNION as SUNION, - sUnion: SUNION as SUNION, - SUNIONSTORE: SUNIONSTORE as SUNIONSTORE, - sUnionStore: SUNIONSTORE as SUNIONSTORE, - SWAPDB: SWAPDB as SWAPDB, - swapDb: SWAPDB as SWAPDB, - TIME: TIME as TIME, - time: TIME as TIME, - TOUCH: TOUCH as TOUCH, - touch: TOUCH as TOUCH, - TTL: TTL as TTL, - ttl: TTL as TTL, - TYPE: TYPE as TYPE, - type: TYPE as TYPE, - UNLINK: UNLINK as UNLINK, - unlink: UNLINK as UNLINK, - UNWATCH: UNWATCH as UNWATCH, - unwatch: UNWATCH as UNWATCH, - WAIT: WAIT as WAIT, - wait: WAIT as WAIT, - WATCH: WATCH as WATCH, - watch: WATCH as WATCH, - XACK: XACK as XACK, - xAck: XACK as XACK, - XADD_NOMKSTREAM: XADD_NOMKSTREAM as XADD_NOMKSTREAM, - xAddNoMkStream: XADD_NOMKSTREAM as XADD_NOMKSTREAM, - XADD: XADD as XADD, - xAdd: XADD as XADD, - XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID as XAUTOCLAIM_JUSTID, - xAutoClaimJustId: XAUTOCLAIM_JUSTID as XAUTOCLAIM_JUSTID, - XAUTOCLAIM: XAUTOCLAIM as XAUTOCLAIM, - xAutoClaim: XAUTOCLAIM as XAUTOCLAIM, - XCLAIM_JUSTID: XCLAIM_JUSTID as XCLAIM_JUSTID, - xClaimJustId: XCLAIM_JUSTID as XCLAIM_JUSTID, - XCLAIM: XCLAIM as XCLAIM, - xClaim: XCLAIM as XCLAIM, - XDEL: XDEL as XDEL, - xDel: XDEL as XDEL, - XGROUP_CREATE: XGROUP_CREATE as XGROUP_CREATE, - xGroupCreate: XGROUP_CREATE as XGROUP_CREATE, - XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER as XGROUP_CREATECONSUMER, - xGroupCreateConsumer: XGROUP_CREATECONSUMER as XGROUP_CREATECONSUMER, - XGROUP_DELCONSUMER: XGROUP_DELCONSUMER as XGROUP_DELCONSUMER, - xGroupDelConsumer: XGROUP_DELCONSUMER as XGROUP_DELCONSUMER, - XGROUP_DESTROY: XGROUP_DESTROY as XGROUP_DESTROY, - xGroupDestroy: XGROUP_DESTROY as XGROUP_DESTROY, - XGROUP_SETID: XGROUP_SETID as XGROUP_SETID, - xGroupSetId: XGROUP_SETID as XGROUP_SETID, - XINFO_CONSUMERS: XINFO_CONSUMERS as XINFO_CONSUMERS, - xInfoConsumers: XINFO_CONSUMERS as XINFO_CONSUMERS, - XINFO_GROUPS: XINFO_GROUPS as XINFO_GROUPS, - xInfoGroups: XINFO_GROUPS as XINFO_GROUPS, - XINFO_STREAM: XINFO_STREAM as XINFO_STREAM, - xInfoStream: XINFO_STREAM as XINFO_STREAM, - XLEN: XLEN as XLEN, - xLen: XLEN as XLEN, - XPENDING_RANGE: XPENDING_RANGE as XPENDING_RANGE, - xPendingRange: XPENDING_RANGE as XPENDING_RANGE, - XPENDING: XPENDING as XPENDING, - xPending: XPENDING as XPENDING, - XRANGE: XRANGE as XRANGE, - xRange: XRANGE as XRANGE, - XREAD: XREAD as XREAD, - xRead: XREAD as XREAD, - XREADGROUP: XREADGROUP as XREADGROUP, - xReadGroup: XREADGROUP as XREADGROUP, - XREVRANGE: XREVRANGE as XREVRANGE, - xRevRange: XREVRANGE as XREVRANGE, - XSETID: XSETID as XSETID, - xSetId: XSETID as XSETID, - XTRIM: XTRIM as XTRIM, - xTrim: XTRIM as XTRIM, - ZADD_INCR: ZADD_INCR as ZADD_INCR, - zAddIncr: ZADD_INCR as ZADD_INCR, - ZADD: ZADD as ZADD, - zAdd: ZADD as ZADD, - ZCARD: ZCARD as ZCARD, - zCard: ZCARD as ZCARD, - ZCOUNT: ZCOUNT as ZCOUNT, - zCount: ZCOUNT as ZCOUNT, - ZDIFF_WITHSCORES: ZDIFF_WITHSCORES as ZDIFF_WITHSCORES, - zDiffWithScores: ZDIFF_WITHSCORES as ZDIFF_WITHSCORES, - ZDIFF: ZDIFF as ZDIFF, - zDiff: ZDIFF as ZDIFF, - ZDIFFSTORE: ZDIFFSTORE as ZDIFFSTORE, - zDiffStore: ZDIFFSTORE as ZDIFFSTORE, - ZINCRBY: ZINCRBY as ZINCRBY, - zIncrBy: ZINCRBY as ZINCRBY, - ZINTER_WITHSCORES: ZINTER_WITHSCORES as ZINTER_WITHSCORES, - zInterWithScores: ZINTER_WITHSCORES as ZINTER_WITHSCORES, - ZINTER: ZINTER as ZINTER, - zInter: ZINTER as ZINTER, - ZINTERCARD: ZINTERCARD as ZINTERCARD, - zInterCard: ZINTERCARD as ZINTERCARD, - ZINTERSTORE: ZINTERSTORE as ZINTERSTORE, - zInterStore: ZINTERSTORE as ZINTERSTORE, - ZLEXCOUNT: ZLEXCOUNT as ZLEXCOUNT, - zLexCount: ZLEXCOUNT as ZLEXCOUNT, - ZMPOP: ZMPOP as ZMPOP, - zmPop: ZMPOP as ZMPOP, - ZMSCORE: ZMSCORE as ZMSCORE, - zmScore: ZMSCORE as ZMSCORE, - ZPOPMAX_COUNT: ZPOPMAX_COUNT as ZPOPMAX_COUNT, - zPopMaxCount: ZPOPMAX_COUNT as ZPOPMAX_COUNT, - ZPOPMAX: ZPOPMAX as ZPOPMAX, - zPopMax: ZPOPMAX as ZPOPMAX, - ZPOPMIN_COUNT: ZPOPMIN_COUNT as ZPOPMIN_COUNT, - zPopMinCount: ZPOPMIN_COUNT as ZPOPMIN_COUNT, - ZPOPMIN: ZPOPMIN as ZPOPMIN, - zPopMin: ZPOPMIN as ZPOPMIN, - ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES as ZRANDMEMBER_COUNT_WITHSCORES, - zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES as ZRANDMEMBER_COUNT_WITHSCORES, - ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT as ZRANDMEMBER_COUNT, - zRandMemberCount: ZRANDMEMBER_COUNT as ZRANDMEMBER_COUNT, - ZRANDMEMBER: ZRANDMEMBER as ZRANDMEMBER, - zRandMember: ZRANDMEMBER as ZRANDMEMBER, - ZRANGE_WITHSCORES: ZRANGE_WITHSCORES as ZRANGE_WITHSCORES, - zRangeWithScores: ZRANGE_WITHSCORES as ZRANGE_WITHSCORES, - ZRANGE: ZRANGE as ZRANGE, - zRange: ZRANGE as ZRANGE, - ZRANGEBYLEX: ZRANGEBYLEX as ZRANGEBYLEX, - zRangeByLex: ZRANGEBYLEX as ZRANGEBYLEX, - ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES as ZRANGEBYSCORE_WITHSCORES, - zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES as ZRANGEBYSCORE_WITHSCORES, - ZRANGEBYSCORE: ZRANGEBYSCORE as ZRANGEBYSCORE, - zRangeByScore: ZRANGEBYSCORE as ZRANGEBYSCORE, - ZRANGESTORE: ZRANGESTORE as ZRANGESTORE, - zRangeStore: ZRANGESTORE as ZRANGESTORE, - ZRANK_WITHSCORE: ZRANK_WITHSCORE as ZRANK_WITHSCORE, - zRankWithScore: ZRANK_WITHSCORE as ZRANK_WITHSCORE, - ZRANK: ZRANK as ZRANK, - zRank: ZRANK as ZRANK, - ZREM: ZREM as ZREM, - zRem: ZREM as ZREM, - ZREMRANGEBYLEX: ZREMRANGEBYLEX as ZREMRANGEBYLEX, - zRemRangeByLex: ZREMRANGEBYLEX as ZREMRANGEBYLEX, - ZREMRANGEBYRANK: ZREMRANGEBYRANK as ZREMRANGEBYRANK, - zRemRangeByRank: ZREMRANGEBYRANK as ZREMRANGEBYRANK, - ZREMRANGEBYSCORE: ZREMRANGEBYSCORE as ZREMRANGEBYSCORE, - zRemRangeByScore: ZREMRANGEBYSCORE as ZREMRANGEBYSCORE, - ZREVRANK: ZREVRANK as ZREVRANK, - zRevRank: ZREVRANK as ZREVRANK, - ZSCAN: ZSCAN as ZSCAN, - zScan: ZSCAN as ZSCAN, - ZSCORE: ZSCORE as ZSCORE, - zScore: ZSCORE as ZSCORE, - ZUNION_WITHSCORES: ZUNION_WITHSCORES as ZUNION_WITHSCORES, - zUnionWithScores: ZUNION_WITHSCORES as ZUNION_WITHSCORES, - ZUNION: ZUNION as ZUNION, - zUnion: ZUNION as ZUNION, - ZUNIONSTORE: ZUNIONSTORE as ZUNIONSTORE, + ping: PING, + PSETEX, + pSetEx: PSETEX, + PTTL, + pTTL: PTTL, + PUBLISH, + publish: PUBLISH, + PUBSUB_CHANNELS, + pubSubChannels: PUBSUB_CHANNELS, + PUBSUB_NUMPAT, + pubSubNumPat: PUBSUB_NUMPAT, + PUBSUB_NUMSUB, + pubSubNumSub: PUBSUB_NUMSUB, + PUBSUB_SHARDCHANNELS, + pubSubShardChannels: PUBSUB_SHARDCHANNELS, + RANDOMKEY, + randomKey: RANDOMKEY, + READONLY, + readonly: READONLY, + RENAME, + rename: RENAME, + RENAMENX, + renameNX: RENAMENX, + RPOP_COUNT, + rPopCount: RPOP_COUNT, + ROLE, + role: ROLE, + RPOP, + rPop: RPOP, + RPOPLPUSH, + rPopLPush: RPOPLPUSH, + RPUSH, + rPush: RPUSH, + RPUSHX, + rPushX: RPUSHX, + SADD, + sAdd: SADD, + SCAN, + scan: SCAN, + SCARD, + sCard: SCARD, + SCRIPT_DEBUG, + scriptDebug: SCRIPT_DEBUG, + SCRIPT_EXISTS, + scriptExists: SCRIPT_EXISTS, + SCRIPT_FLUSH, + scriptFlush: SCRIPT_FLUSH, + SCRIPT_KILL, + scriptKill: SCRIPT_KILL, + SCRIPT_LOAD, + scriptLoad: SCRIPT_LOAD, + SDIFF, + sDiff: SDIFF, + SDIFFSTORE, + sDiffStore: SDIFFSTORE, + SET, + set: SET, + SETBIT, + setBit: SETBIT, + SETEX, + setEx: SETEX, + SETNX, + setNX: SETNX, + SETRANGE, + setRange: SETRANGE, + SINTER, + sInter: SINTER, + SINTERCARD, + sInterCard: SINTERCARD, + SINTERSTORE, + sInterStore: SINTERSTORE, + SISMEMBER, + sIsMember: SISMEMBER, + SMEMBERS, + sMembers: SMEMBERS, + SMISMEMBER, + smIsMember: SMISMEMBER, + SMOVE, + sMove: SMOVE, + SORT_RO, + sortRo: SORT_RO, + SORT_STORE, + sortStore: SORT_STORE, + SORT, + sort: SORT, + SPOP_COUNT, + sPopCount: SPOP_COUNT, + SPOP, + sPop: SPOP, + SPUBLISH, + sPublish: SPUBLISH, + SRANDMEMBER_COUNT, + sRandMemberCount: SRANDMEMBER_COUNT, + SRANDMEMBER, + sRandMember: SRANDMEMBER, + SREM, + sRem: SREM, + SSCAN, + sScan: SSCAN, + STRLEN, + strLen: STRLEN, + SUNION, + sUnion: SUNION, + SUNIONSTORE, + sUnionStore: SUNIONSTORE, + SWAPDB, + swapDb: SWAPDB, + TIME, + time: TIME, + TOUCH, + touch: TOUCH, + TTL, + ttl: TTL, + TYPE, + type: TYPE, + UNLINK, + unlink: UNLINK, + UNWATCH, + unwatch: UNWATCH, + WAIT, + wait: WAIT, + WATCH, + watch: WATCH, + XACK, + xAck: XACK, + XADD_NOMKSTREAM, + xAddNoMkStream: XADD_NOMKSTREAM, + XADD, + xAdd: XADD, + XAUTOCLAIM_JUSTID, + xAutoClaimJustId: XAUTOCLAIM_JUSTID, + XAUTOCLAIM, + xAutoClaim: XAUTOCLAIM, + XCLAIM_JUSTID, + xClaimJustId: XCLAIM_JUSTID, + XCLAIM, + xClaim: XCLAIM, + XDEL, + xDel: XDEL, + XGROUP_CREATE, + xGroupCreate: XGROUP_CREATE, + XGROUP_CREATECONSUMER, + xGroupCreateConsumer: XGROUP_CREATECONSUMER, + XGROUP_DELCONSUMER, + xGroupDelConsumer: XGROUP_DELCONSUMER, + XGROUP_DESTROY, + xGroupDestroy: XGROUP_DESTROY, + XGROUP_SETID, + xGroupSetId: XGROUP_SETID, + XINFO_CONSUMERS, + xInfoConsumers: XINFO_CONSUMERS, + XINFO_GROUPS, + xInfoGroups: XINFO_GROUPS, + XINFO_STREAM, + xInfoStream: XINFO_STREAM, + XLEN, + xLen: XLEN, + XPENDING_RANGE, + xPendingRange: XPENDING_RANGE, + XPENDING, + xPending: XPENDING, + XRANGE, + xRange: XRANGE, + XREAD, + xRead: XREAD, + XREADGROUP, + xReadGroup: XREADGROUP, + XREVRANGE, + xRevRange: XREVRANGE, + XSETID, + xSetId: XSETID, + XTRIM, + xTrim: XTRIM, + ZADD_INCR, + zAddIncr: ZADD_INCR, + ZADD, + zAdd: ZADD, + ZCARD, + zCard: ZCARD, + ZCOUNT, + zCount: ZCOUNT, + ZDIFF_WITHSCORES, + zDiffWithScores: ZDIFF_WITHSCORES, + ZDIFF, + zDiff: ZDIFF, + ZDIFFSTORE, + zDiffStore: ZDIFFSTORE, + ZINCRBY, + zIncrBy: ZINCRBY, + ZINTER_WITHSCORES, + zInterWithScores: ZINTER_WITHSCORES, + ZINTER, + zInter: ZINTER, + ZINTERCARD, + zInterCard: ZINTERCARD, + ZINTERSTORE, + zInterStore: ZINTERSTORE, + ZLEXCOUNT, + zLexCount: ZLEXCOUNT, + ZMPOP, + zmPop: ZMPOP, + ZMSCORE, + zmScore: ZMSCORE, + ZPOPMAX_COUNT, + zPopMaxCount: ZPOPMAX_COUNT, + ZPOPMAX, + zPopMax: ZPOPMAX, + ZPOPMIN_COUNT, + zPopMinCount: ZPOPMIN_COUNT, + ZPOPMIN, + zPopMin: ZPOPMIN, + ZRANDMEMBER_COUNT_WITHSCORES, + zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES, + ZRANDMEMBER_COUNT, + zRandMemberCount: ZRANDMEMBER_COUNT, + ZRANDMEMBER, + zRandMember: ZRANDMEMBER, + ZRANGE_WITHSCORES, + zRangeWithScores: ZRANGE_WITHSCORES, + ZRANGE, + zRange: ZRANGE, + ZRANGEBYLEX, + zRangeByLex: ZRANGEBYLEX, + ZRANGEBYSCORE_WITHSCORES, + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, + ZRANGEBYSCORE, + zRangeByScore: ZRANGEBYSCORE, + ZRANGESTORE, + zRangeStore: ZRANGESTORE, + ZRANK_WITHSCORE, + zRankWithScore: ZRANK_WITHSCORE, + ZRANK, + zRank: ZRANK, + ZREM, + zRem: ZREM, + ZREMRANGEBYLEX, + zRemRangeByLex: ZREMRANGEBYLEX, + ZREMRANGEBYRANK, + zRemRangeByRank: ZREMRANGEBYRANK, + ZREMRANGEBYSCORE, + zRemRangeByScore: ZREMRANGEBYSCORE, + ZREVRANK, + zRevRank: ZREVRANK, + ZSCAN, + zScan: ZSCAN, + ZSCORE, + zScore: ZSCORE, + ZUNION_WITHSCORES, + zUnionWithScores: ZUNION_WITHSCORES, + ZUNION, + zUnion: ZUNION, + ZUNIONSTORE, zUnionStore: ZUNIONSTORE } as const satisfies RedisCommands; From 492c451b2d6b7e8c054ff1700934ea83d861107d Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 6 Jul 2023 15:44:24 -0400 Subject: [PATCH 178/325] fix MEMORY STATS --- packages/client/lib/commands/MEMORY_STATS.spec.ts | 9 +++++---- packages/client/lib/commands/MEMORY_STATS.ts | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/client/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts index d210514d7fa..29af2b95d90 100644 --- a/packages/client/lib/commands/MEMORY_STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_STATS.spec.ts @@ -18,12 +18,8 @@ describe('MEMORY STATS', () => { assert.equal(typeof memoryStats['replication.backlog'], 'number'); assert.equal(typeof memoryStats['clients.slaves'], 'number'); assert.equal(typeof memoryStats['clients.normal'], 'number'); - if (testUtils.isVersionGreaterThan([7])) { - assert.equal(typeof memoryStats['cluster.links'], 'number'); - } assert.equal(typeof memoryStats['aof.buffer'], 'number'); assert.equal(typeof memoryStats['lua.caches'], 'number'); - assert.equal(typeof memoryStats['functions.caches'], 'number'); assert.equal(typeof memoryStats['overhead.total'], 'number'); assert.equal(typeof memoryStats['keys.count'], 'number'); assert.equal(typeof memoryStats['keys.bytes-per-key'], 'number'); @@ -41,5 +37,10 @@ describe('MEMORY STATS', () => { assert.equal(typeof memoryStats['rss-overhead.bytes'], 'number'); assert.equal(typeof memoryStats['fragmentation'], 'string'); assert.equal(typeof memoryStats['fragmentation.bytes'], 'number'); + + if (testUtils.isVersionGreaterThan([7])) { + assert.equal(typeof memoryStats['cluster.links'], 'number'); + assert.equal(typeof memoryStats['functions.caches'], 'number'); + } }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index b15db7fb8fa..4e6997ff99c 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -11,6 +11,7 @@ export type MemoryStatsReply = TuplesToMapReply<[ [BlobStringReply<'cluster.links'>, NumberReply], [BlobStringReply<'aof.buffer'>, NumberReply], [BlobStringReply<'lua.caches'>, NumberReply], + /** added in 7.0 */ [BlobStringReply<'functions.caches'>, NumberReply], [BlobStringReply<'overhead.total'>, NumberReply], [BlobStringReply<'keys.count'>, NumberReply], From d986ff52b6c80959ddf5f46cbf316148d83db230 Mon Sep 17 00:00:00 2001 From: dovi Date: Thu, 6 Jul 2023 15:50:21 -0400 Subject: [PATCH 179/325] FT.SUGDEL docs --- docs/v4-to-v5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 91d88c066e7..e4c1b122b5f 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -174,6 +174,7 @@ Some command arguments/replies have changed to align more closely to data types - `XINFO GROUPS`: `lastDeliveredId` -> `last-delivered-id` [^map-keys] - `XINFO STREAM`: `radixTreeKeys` -> `radix-tree-keys`, `radixTreeNodes` -> `radix-tree-nodes`, `lastGeneratedId` -> `last-generated-id`, `maxDeletedEntryId` -> `max-deleted-entry-id`, `entriesAdded` -> `entries-added`, `recordedFirstEntryId` -> `recorded-first-entry-id`, `firstEntry` -> `first-entry`, `lastEntry` -> `last-entry` - `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record }>; }>` -> `Record }>>` +- `FT.SUGDEL`: [^boolean-to-number] [^enum-to-constants]: TODO From e64946566a9a1c017f7611c0bfa706f0c3da7da0 Mon Sep 17 00:00:00 2001 From: dovi Date: Thu, 6 Jul 2023 15:51:12 -0400 Subject: [PATCH 180/325] more commands --- .../json/lib/commands/DEBUG_MEMORY.spec.ts | 40 +++++++------- packages/json/lib/commands/DEBUG_MEMORY.ts | 15 +++--- packages/json/lib/commands/DEL.spec.ts | 41 ++++++++------- packages/json/lib/commands/DEL.ts | 15 +++--- packages/json/lib/commands/FORGET.spec.ts | 40 +++++++------- packages/json/lib/commands/FORGET.ts | 15 +++--- packages/search/lib/commands/DICTADD.spec.ts | 40 +++++++------- packages/search/lib/commands/DICTADD.ts | 15 +++--- packages/search/lib/commands/DICTDEL.spec.ts | 40 +++++++------- packages/search/lib/commands/DICTDEL.ts | 15 +++--- packages/search/lib/commands/EXPLAIN.spec.ts | 52 +++++++++---------- packages/search/lib/commands/EXPLAIN.ts | 30 ++++++----- .../search/lib/commands/EXPLAINCLI.spec.ts | 14 ++--- packages/search/lib/commands/EXPLAINCLI.ts | 13 +++-- packages/search/lib/commands/SUGADD.spec.ts | 52 +++++++++---------- packages/search/lib/commands/SUGADD.ts | 23 ++++---- packages/search/lib/commands/SUGDEL.spec.ts | 26 +++++----- packages/search/lib/commands/SUGDEL.ts | 13 +++-- packages/search/lib/commands/SUGLEN.spec.ts | 26 +++++----- packages/search/lib/commands/SUGLEN.ts | 13 +++-- 20 files changed, 286 insertions(+), 252 deletions(-) diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts index 468c994f2f5..51b6f7e2da8 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DEBUG_MEMORY'; +import DEBUG_MEMORY from './DEBUG_MEMORY'; describe('DEBUG MEMORY', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.DEBUG', 'MEMORY', 'key'] - ); - }); + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + DEBUG_MEMORY.transformArguments('key'), + ['JSON.DEBUG', 'MEMORY', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.DEBUG', 'MEMORY', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + DEBUG_MEMORY.transformArguments('key', '$'), + ['JSON.DEBUG', 'MEMORY', 'key', '$'] + ); }); + }); - testUtils.testWithClient('client.json.arrTrim', async client => { - assert.deepEqual( - await client.json.debugMemory('key', '$'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index da60b1d9529..3b1c4460373 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -1,13 +1,16 @@ -export const FIRST_KEY_INDEX = 2; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 2, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.DEBUG', 'MEMORY', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/DEL.spec.ts b/packages/json/lib/commands/DEL.spec.ts index a957b9584ac..4d67d7cb3e0 100644 --- a/packages/json/lib/commands/DEL.spec.ts +++ b/packages/json/lib/commands/DEL.spec.ts @@ -1,28 +1,29 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DEL'; +import DEL from './DEL'; describe('DEL', () => { - describe('transformArguments', () => { - it('key', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.DEL', 'key'] - ); - }); + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + DEL.transformArguments('key'), + ['JSON.DEL', 'key'] + ); + }); - it('key, path', () => { - assert.deepEqual( - transformArguments('key', '$.path'), - ['JSON.DEL', 'key', '$.path'] - ); - }); + it('key, path', () => { + assert.deepEqual( + DEL.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); + 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 index 090d4dbe853..922fc7a7832 100644 --- a/packages/json/lib/commands/DEL.ts +++ b/packages/json/lib/commands/DEL.ts @@ -1,13 +1,16 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.DEL', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/FORGET.spec.ts b/packages/json/lib/commands/FORGET.spec.ts index 923bb997fc8..b0e19615064 100644 --- a/packages/json/lib/commands/FORGET.spec.ts +++ b/packages/json/lib/commands/FORGET.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './FORGET'; +import FORGET from './FORGET'; describe('FORGET', () => { - describe('transformArguments', () => { - it('key', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.FORGET', 'key'] - ); - }); + describe('transformArguments', () => { + it('key', () => { + assert.deepEqual( + FORGET.transformArguments('key'), + ['JSON.FORGET', 'key'] + ); + }); - it('key, path', () => { - assert.deepEqual( - transformArguments('key', '$.path'), - ['JSON.FORGET', 'key', '$.path'] - ); - }); + it('key, path', () => { + assert.deepEqual( + FORGET.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); + 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 index cb2df3d605d..b55015e9488 100644 --- a/packages/json/lib/commands/FORGET.ts +++ b/packages/json/lib/commands/FORGET.ts @@ -1,13 +1,16 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.FORGET', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/DICTADD.spec.ts b/packages/search/lib/commands/DICTADD.spec.ts index b5f29dd4083..6aa3c862f2f 100644 --- a/packages/search/lib/commands/DICTADD.spec.ts +++ b/packages/search/lib/commands/DICTADD.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DICTADD'; +import DICTADD from './DICTADD'; describe('DICTADD', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('dictionary', 'term'), - ['FT.DICTADD', 'dictionary', 'term'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + DICTADD.transformArguments('dictionary', 'term'), + ['FT.DICTADD', 'dictionary', 'term'] + ); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('dictionary', ['1', '2']), - ['FT.DICTADD', 'dictionary', '1', '2'] - ); - }); + it('Array', () => { + assert.deepEqual( + DICTADD.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); + 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 index 2a8d9c522bc..a90e87dcf70 100644 --- a/packages/search/lib/commands/DICTADD.ts +++ b/packages/search/lib/commands/DICTADD.ts @@ -1,8 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTADD', dictionary], term); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/DICTDEL.spec.ts b/packages/search/lib/commands/DICTDEL.spec.ts index 5ffa6b6b84f..9d42944d62b 100644 --- a/packages/search/lib/commands/DICTDEL.spec.ts +++ b/packages/search/lib/commands/DICTDEL.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DICTDEL'; +import DICTDEL from './DICTDEL'; describe('DICTDEL', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - transformArguments('dictionary', 'term'), - ['FT.DICTDEL', 'dictionary', 'term'] - ); - }); + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + DICTDEL.transformArguments('dictionary', 'term'), + ['FT.DICTDEL', 'dictionary', 'term'] + ); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('dictionary', ['1', '2']), - ['FT.DICTDEL', 'dictionary', '1', '2'] - ); - }); + it('Array', () => { + assert.deepEqual( + DICTDEL.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); + 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 index 8a8513f5595..e639d3427b0 100644 --- a/packages/search/lib/commands/DICTDEL.ts +++ b/packages/search/lib/commands/DICTDEL.ts @@ -1,8 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(dictionary: string, term: string | Array): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTDEL', dictionary], term); -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/EXPLAIN.spec.ts b/packages/search/lib/commands/EXPLAIN.spec.ts index d24f5fe4ac5..6b3c72507df 100644 --- a/packages/search/lib/commands/EXPLAIN.spec.ts +++ b/packages/search/lib/commands/EXPLAIN.spec.ts @@ -1,33 +1,33 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './EXPLAIN'; +import EXPLAIN from './EXPLAIN'; describe('EXPLAIN', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('index', '*'), - ['FT.EXPLAIN', 'index', '*'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + EXPLAIN.transformArguments('index', '*'), + ['FT.EXPLAIN', 'index', '*'] + ); + }); - it('with PARAMS', () => { - assert.deepEqual( - transformArguments('index', '*', { - PARAMS: { - param: 'value' - } - }), - ['FT.EXPLAIN', 'index', '*', 'PARAMS', '2', 'param', 'value'] - ); - }); + it('with PARAMS', () => { + assert.deepEqual( + EXPLAIN.transformArguments('index', '*', { + PARAMS: { + param: 'value' + } + }), + ['FT.EXPLAIN', 'index', '*', 'PARAMS', '2', 'param', 'value'] + ); + }); - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', '*', { - DIALECT: 1 - }), - ['FT.EXPLAIN', 'index', '*', 'DIALECT', '1'] - ); - }); + it('with DIALECT', () => { + assert.deepEqual( + EXPLAIN.transformArguments('index', '*', { + DIALECT: 1 + }), + ['FT.EXPLAIN', 'index', '*', 'DIALECT', '1'] + ); }); + }); }); diff --git a/packages/search/lib/commands/EXPLAIN.ts b/packages/search/lib/commands/EXPLAIN.ts index ab3935ff979..538299e9c0f 100644 --- a/packages/search/lib/commands/EXPLAIN.ts +++ b/packages/search/lib/commands/EXPLAIN.ts @@ -1,26 +1,28 @@ +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { Params, pushParamsArgs } from "."; -export const IS_READ_ONLY = true; - -interface ExplainOptions { - PARAMS?: Params; - DIALECT?: number; +export interface FtExplainOptions { + PARAMS?: Params; + DIALECT?: number; } -export function transformArguments( - index: string, - query: string, - options?: ExplainOptions -): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments( + index: RedisArgument, + query: RedisArgument, + options?: FtExplainOptions + ) { const args = ['FT.EXPLAIN', index, query]; pushParamsArgs(args, options?.PARAMS); if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); + args.push('DIALECT', options.DIALECT.toString()); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/EXPLAINCLI.spec.ts b/packages/search/lib/commands/EXPLAINCLI.spec.ts index 238ef44eaaa..720f91a8499 100644 --- a/packages/search/lib/commands/EXPLAINCLI.spec.ts +++ b/packages/search/lib/commands/EXPLAINCLI.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './EXPLAINCLI'; +import EXPLAINCLI from './EXPLAINCLI'; describe('EXPLAINCLI', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index', '*'), - ['FT.EXPLAINCLI', 'index', '*'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + EXPLAINCLI.transformArguments('index', '*'), + ['FT.EXPLAINCLI', 'index', '*'] + ); + }); }); diff --git a/packages/search/lib/commands/EXPLAINCLI.ts b/packages/search/lib/commands/EXPLAINCLI.ts index db97fb9c8da..e16866991b9 100644 --- a/packages/search/lib/commands/EXPLAINCLI.ts +++ b/packages/search/lib/commands/EXPLAINCLI.ts @@ -1,7 +1,10 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(index: string, query: string): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, query: RedisArgument) { return ['FT.EXPLAINCLI', index, query]; -} - -export declare function transformReply(): Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGADD.spec.ts b/packages/search/lib/commands/SUGADD.spec.ts index 23294eb4abd..391fa51d615 100644 --- a/packages/search/lib/commands/SUGADD.spec.ts +++ b/packages/search/lib/commands/SUGADD.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGADD'; +import SUGADD from './SUGADD'; describe('SUGADD', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', 'string', 1), - ['FT.SUGADD', 'key', 'string', '1'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SUGADD.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 INCR', () => { + assert.deepEqual( + SUGADD.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'] - ); - }); + it('with PAYLOAD', () => { + assert.deepEqual( + SUGADD.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); + 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 index d68f0d98841..490dd6d1b35 100644 --- a/packages/search/lib/commands/SUGADD.ts +++ b/packages/search/lib/commands/SUGADD.ts @@ -1,20 +1,25 @@ -interface SugAddOptions { - INCR?: true; - PAYLOAD?: string; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export interface FtSugAddOptions { + INCR?: boolean; + PAYLOAD?: RedisArgument; } -export function transformArguments(key: string, string: string, score: number, options?: SugAddOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) { const args = ['FT.SUGADD', key, string, score.toString()]; if (options?.INCR) { - args.push('INCR'); + args.push('INCR'); } if (options?.PAYLOAD) { - args.push('PAYLOAD', options.PAYLOAD); + args.push('PAYLOAD', options.PAYLOAD); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGDEL.spec.ts b/packages/search/lib/commands/SUGDEL.spec.ts index 3d89e3b9a72..4d0b72b6d9c 100644 --- a/packages/search/lib/commands/SUGDEL.spec.ts +++ b/packages/search/lib/commands/SUGDEL.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGDEL'; +import SUGDEL from './SUGDEL'; describe('SUGDEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'string'), - ['FT.SUGDEL', 'key', 'string'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SUGDEL.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); + 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 index b522acdfd47..9311e14c026 100644 --- a/packages/search/lib/commands/SUGDEL.ts +++ b/packages/search/lib/commands/SUGDEL.ts @@ -1,5 +1,10 @@ -export function transformArguments(key: string, string: string): Array { - return ['FT.SUGDEL', key, string]; -} +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export { transformBooleanReply as transformReply } from '@redis/client/dist/lib/commands/generic-transformers'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, string: RedisArgument) { + return ['FT.SUGDEL', key, string]; + }, + transformReply: undefined as unknown as () => NumberReply<0 | 1> +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGLEN.spec.ts b/packages/search/lib/commands/SUGLEN.spec.ts index 2ea680df953..88a140b770c 100644 --- a/packages/search/lib/commands/SUGLEN.spec.ts +++ b/packages/search/lib/commands/SUGLEN.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGLEN'; +import SUGLEN from './SUGLEN'; describe('SUGLEN', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key'), - ['FT.SUGLEN', 'key'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + SUGLEN.transformArguments('key'), + ['FT.SUGLEN', 'key'] + ); + }); - testUtils.testWithClient('client.ft.sugLen', async client => { - assert.equal( - await client.ft.sugLen('key'), - 0 - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 15b3da61261..a5418843d44 100644 --- a/packages/search/lib/commands/SUGLEN.ts +++ b/packages/search/lib/commands/SUGLEN.ts @@ -1,7 +1,10 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['FT.SUGLEN', key]; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; From a4aa9039878fd58b9a8aa7f0ff5c88c611677ae6 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 10 Jul 2023 10:32:23 -0400 Subject: [PATCH 181/325] fix SMEMBERS --- packages/client/lib/commands/SMEMBERS.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/SMEMBERS.ts b/packages/client/lib/commands/SMEMBERS.ts index fdab118e86e..391c83af6c6 100644 --- a/packages/client/lib/commands/SMEMBERS.ts +++ b/packages/client/lib/commands/SMEMBERS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SetReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, SetReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,5 +6,8 @@ export default { transformArguments(key: RedisArgument) { return ['SMEMBERS', key]; }, - transformReply: undefined as unknown as () => SetReply + transformReply: { + 2: undefined as unknown as () => ArrayReply, + 3: undefined as unknown as () => SetReply + } } as const satisfies Command; From 3fa7717a7d23aaaf10e284cc3c42f5fe736c0aad Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 10 Jul 2023 12:20:40 -0400 Subject: [PATCH 182/325] graph --- .../graph/lib/commands/CONFIG_GET.spec.ts | 2 +- .../graph/lib/commands/CONFIG_SET.spec.ts | 2 +- packages/graph/lib/commands/CONFIG_SET.ts | 2 +- packages/graph/lib/commands/DELETE.spec.ts | 12 +- packages/graph/lib/commands/DELETE.ts | 2 +- packages/graph/lib/commands/EXPLAIN.spec.ts | 6 +- packages/graph/lib/commands/LIST.spec.ts | 2 +- packages/graph/lib/commands/PROFILE.spec.ts | 6 +- packages/graph/lib/commands/QUERY.spec.ts | 60 +- packages/graph/lib/commands/QUERY.ts | 134 +++-- packages/graph/lib/commands/RO_QUERY.spec.ts | 30 +- packages/graph/lib/commands/RO_QUERY.ts | 32 +- packages/graph/lib/commands/SLOWLOG.spec.ts | 10 +- packages/graph/lib/commands/SLOWLOG.ts | 46 +- packages/graph/lib/commands/index.spec.ts | 62 -- packages/graph/lib/commands/index.ts | 141 +---- packages/graph/lib/graph.spec.ts | 284 ++++----- packages/graph/lib/graph.ts | 566 +++++++++--------- packages/graph/lib/test-utils.ts | 20 +- packages/graph/package.json | 6 +- 20 files changed, 681 insertions(+), 744 deletions(-) delete mode 100644 packages/graph/lib/commands/index.spec.ts diff --git a/packages/graph/lib/commands/CONFIG_GET.spec.ts b/packages/graph/lib/commands/CONFIG_GET.spec.ts index c002bbdf0e0..c9bf44503ba 100644 --- a/packages/graph/lib/commands/CONFIG_GET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_GET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_GET from './CONFIG_GET'; -describe('CONFIG GET', () => { +describe('GRAPH.CONFIG GET', () => { it('transformArguments', () => { assert.deepEqual( CONFIG_GET.transformArguments('TIMEOUT'), diff --git a/packages/graph/lib/commands/CONFIG_SET.spec.ts b/packages/graph/lib/commands/CONFIG_SET.spec.ts index 02eed85cd95..aa44be8717b 100644 --- a/packages/graph/lib/commands/CONFIG_SET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_SET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_SET from './CONFIG_SET'; -describe('CONFIG SET', () => { +describe('GRAPH.CONFIG SET', () => { it('transformArguments', () => { assert.deepEqual( CONFIG_SET.transformArguments('TIMEOUT', 0), diff --git a/packages/graph/lib/commands/CONFIG_SET.ts b/packages/graph/lib/commands/CONFIG_SET.ts index 715f754ce38..ba23ac2f1a7 100644 --- a/packages/graph/lib/commands/CONFIG_SET.ts +++ b/packages/graph/lib/commands/CONFIG_SET.ts @@ -11,5 +11,5 @@ export default { value.toString() ]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/graph/lib/commands/DELETE.spec.ts b/packages/graph/lib/commands/DELETE.spec.ts index 5b9fd2ceb61..86cec5c8d28 100644 --- a/packages/graph/lib/commands/DELETE.spec.ts +++ b/packages/graph/lib/commands/DELETE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DELETE from './DELETE'; -describe('', () => { +describe('GRAPH.DELETE', () => { it('transformArguments', () => { assert.deepEqual( DELETE.transformArguments('key'), @@ -11,11 +11,11 @@ describe('', () => { }); testUtils.testWithClient('client.graph.delete', async client => { - await client.graph.query('key', 'RETURN 1'); + const [, reply] = await Promise.all([ + client.graph.query('key', 'RETURN 1'), + client.graph.delete('key') + ]); - assert.equal( - typeof await client.graph.delete('key'), - 'string' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/DELETE.ts b/packages/graph/lib/commands/DELETE.ts index 16c2566af01..f5772a5f6e6 100644 --- a/packages/graph/lib/commands/DELETE.ts +++ b/packages/graph/lib/commands/DELETE.ts @@ -6,5 +6,5 @@ export default { transformArguments(key: RedisArgument) { return ['GRAPH.DELETE', key]; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/graph/lib/commands/EXPLAIN.spec.ts b/packages/graph/lib/commands/EXPLAIN.spec.ts index 9e532307a92..1fc824ad364 100644 --- a/packages/graph/lib/commands/EXPLAIN.spec.ts +++ b/packages/graph/lib/commands/EXPLAIN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXPLAIN from './EXPLAIN'; -describe('EXPLAIN', () => { +describe('GRAPH.EXPLAIN', () => { it('transformArguments', () => { assert.deepEqual( EXPLAIN.transformArguments('key', 'RETURN 0'), @@ -16,6 +16,8 @@ describe('EXPLAIN', () => { client.graph.explain('key', 'RETURN 0') ]); assert.ok(Array.isArray(reply)); - assert.ok(!reply.find(x => typeof x !== 'string')); + for (const item of reply) { + assert.equal(typeof item, 'string'); + } }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/LIST.spec.ts b/packages/graph/lib/commands/LIST.spec.ts index 3621adf1244..697b9906123 100644 --- a/packages/graph/lib/commands/LIST.spec.ts +++ b/packages/graph/lib/commands/LIST.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import LIST from './LIST'; -describe('LIST', () => { +describe('GRAPH.LIST', () => { it('transformArguments', () => { assert.deepEqual( LIST.transformArguments(), diff --git a/packages/graph/lib/commands/PROFILE.spec.ts b/packages/graph/lib/commands/PROFILE.spec.ts index 8d967a1344e..ec950d505e7 100644 --- a/packages/graph/lib/commands/PROFILE.spec.ts +++ b/packages/graph/lib/commands/PROFILE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import PROFILE from './PROFILE'; -describe('PROFILE', () => { +describe('GRAPH.PROFILE', () => { it('transformArguments', () => { assert.deepEqual( PROFILE.transformArguments('key', 'RETURN 0'), @@ -13,6 +13,8 @@ describe('PROFILE', () => { testUtils.testWithClient('client.graph.profile', async client => { const reply = await client.graph.profile('key', 'RETURN 0'); assert.ok(Array.isArray(reply)); - assert.ok(!reply.find(x => typeof x !== 'string')); + for (const item of reply) { + assert.equal(typeof item, 'string'); + } }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/QUERY.spec.ts b/packages/graph/lib/commands/QUERY.spec.ts index accbc5cc4cf..389374b5d30 100644 --- a/packages/graph/lib/commands/QUERY.spec.ts +++ b/packages/graph/lib/commands/QUERY.spec.ts @@ -2,14 +2,60 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import QUERY from './QUERY'; -describe('QUERY', () => { - it('transformArguments', () => { - assert.deepEqual( - QUERY.transformArguments('key', 'query'), - ['GRAPH.QUERY', 'key', 'query'] - ); +describe('GRAPH.QUERY', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'query'), + ['GRAPH.QUERY', 'key', 'query'] + ); + }); + + describe('params', () => { + it('all types', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'query', { + params: { + null: null, + string: '"\\', + number: 0, + boolean: false, + array: [0], + object: {a: 0} + } + }), + ['GRAPH.QUERY', 'key', 'CYPHER null=null string="\\"\\\\" number=0 boolean=false array=[0] object={a:0} query'] + ); + }); + + it('TypeError', () => { + assert.throws(() => { + QUERY.transformArguments('key', 'query', { + params: { + a: Buffer.from('a') + } + }) + }, TypeError); + }); + }); + + it('TIMEOUT', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'query', { + TIMEOUT: 1 + }), + ['GRAPH.QUERY', 'key', 'query', 'TIMEOUT', '1'] + ); + }); + + it('compact', () => { + assert.deepEqual( + QUERY.transformArguments('key', 'query', undefined, true), + ['GRAPH.QUERY', 'key', 'query', '--compact'] + ); + }); }); - + testUtils.testWithClient('client.graph.query', async client => { const { data } = await client.graph.query('key', 'RETURN 0'); assert.deepEqual(data, [[0]]); diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index 1d6a4229fa7..b86382a49d6 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -1,55 +1,103 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands/index'; -import { pushQueryArguments, QueryOptionsBackwardCompatible } from '.'; +import { RedisArgument, Command, ArrayReply, BlobStringReply, NumberReply, NullReply, TuplesReply } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; +type Headers = ArrayReply; -export function transformArguments( - graph: RedisCommandArgument, - query: RedisCommandArgument, - options?: QueryOptionsBackwardCompatible, - compact?: boolean -): RedisCommandArguments { - return pushQueryArguments( - ['GRAPH.QUERY'], - graph, - query, - options, - compact - ); -} +// TODO: cannot use `ArrayReply` due to circular reference +type Data = Array; -type Headers = Array; +type Metadata = ArrayReply; -type Data = Array; - -type Metadata = Array; - -type QueryRawReply = [ +type QueryRawReply = TuplesReply<[ headers: Headers, data: Data, metadata: Metadata ] | [ metadata: Metadata -]; - -export type QueryReply = { - headers: undefined; - data: undefined; - metadata: Metadata; -} | { - headers: Headers; - data: Data; - metadata: Metadata; +]>; + +type QueryParam = null | string | number | boolean | QueryParams | Array; + +type QueryParams = { + [key: string]: QueryParam; }; -export function transformReply(reply: QueryRawReply): QueryReply { - return reply.length === 1 ? { - headers: undefined, - data: undefined, - metadata: reply[0] - } : { - headers: reply[0], - data: reply[1], - metadata: reply[2] - }; +export interface QueryOptions { + params?: QueryParams; + TIMEOUT?: number; +} + +export function transformQueryArguments( + command: RedisArgument, + graph: RedisArgument, + query: RedisArgument, + options?: QueryOptions, + compact?: boolean +) { + const args = [ + command, + graph, + options?.params ? + `CYPHER ${queryParamsToString(options.params)} ${query}` : + query + ]; + + if (options?.TIMEOUT !== undefined) { + args.push('TIMEOUT', options.TIMEOUT.toString()); + } + + if (compact) { + args.push('--compact'); + } + + return args; } + +function queryParamsToString(params: QueryParams) { + return Object.entries(params) + .map(([key, value]) => `${key}=${queryParamToString(value)}`) + .join(' '); +} + +function queryParamToString(param: QueryParam): string { + if (param === null) { + return 'null'; + } + + switch (typeof param) { + case 'string': + return `"${param.replace(/["\\]/g, '\\$&')}"`; + + case 'number': + case 'boolean': + return param.toString(); + } + + if (Array.isArray(param)) { + return `[${param.map(queryParamToString).join(',')}]`; + } else if (typeof param === 'object') { + const body = []; + for (const [key, value] of Object.entries(param)) { + body.push(`${key}:${queryParamToString(value)}`); + } + return `{${body.join(',')}}`; + } else { + throw new TypeError(`Unexpected param type ${typeof param} ${param}`) + } +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transformQueryArguments.bind(undefined, 'GRAPH.QUERY'), + transformReply(reply: QueryRawReply) { + return reply.length === 1 ? { + headers: undefined, + data: undefined, + metadata: reply[0] + } : { + headers: reply[0], + data: reply[1], + metadata: reply[2] + }; + } +} as const satisfies Command; diff --git a/packages/graph/lib/commands/RO_QUERY.spec.ts b/packages/graph/lib/commands/RO_QUERY.spec.ts index 1d76b1bd652..b85c33be63b 100644 --- a/packages/graph/lib/commands/RO_QUERY.spec.ts +++ b/packages/graph/lib/commands/RO_QUERY.spec.ts @@ -1,20 +1,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RO_QUERY'; +import RO_QUERY from './RO_QUERY'; -describe('RO_QUERY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'query'), - ['GRAPH.RO_QUERY', 'key', 'query'] - ); - }); +describe('GRAPH.RO_QUERY', () => { + it('transformArguments', () => { + assert.deepEqual( + RO_QUERY.transformArguments('key', 'query'), + ['GRAPH.RO_QUERY', 'key', 'query'] + ); + }); - testUtils.testWithClient('client.graph.roQuery', async client => { - const [, { data }] = await Promise.all([ - client.graph.query('key', 'RETURN 0'), // make sure to create a graph first - client.graph.roQuery('key', 'RETURN 0') - ]); - assert.deepEqual(data, [[0]]); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.graph.roQuery', async client => { + const [, { data }] = await Promise.all([ + client.graph.query('key', 'RETURN 0'), // make sure to create a graph first + client.graph.roQuery('key', 'RETURN 0') + ]); + assert.deepEqual(data, [[0]]); + }, GLOBAL.SERVERS.OPEN); }); \ No newline at end of file diff --git a/packages/graph/lib/commands/RO_QUERY.ts b/packages/graph/lib/commands/RO_QUERY.ts index d4dda9dee27..5987f511b7d 100644 --- a/packages/graph/lib/commands/RO_QUERY.ts +++ b/packages/graph/lib/commands/RO_QUERY.ts @@ -1,23 +1,9 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushQueryArguments, QueryOptionsBackwardCompatible } from '.'; - -export { FIRST_KEY_INDEX } from './QUERY'; - -export const IS_READ_ONLY = true; - -export function transformArguments( - graph: RedisCommandArgument, - query: RedisCommandArgument, - options?: QueryOptionsBackwardCompatible, - compact?: boolean -): RedisCommandArguments { - return pushQueryArguments( - ['GRAPH.RO_QUERY'], - graph, - query, - options, - compact - ); -} - -export { transformReply } from './QUERY'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import QUERY, { transformQueryArguments } from './QUERY'; + +export default { + FIRST_KEY_INDEX: QUERY.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformQueryArguments.bind(undefined, 'GRAPH.RO_QUERY'), + transformReply: QUERY.transformReply +} as const satisfies Command; diff --git a/packages/graph/lib/commands/SLOWLOG.spec.ts b/packages/graph/lib/commands/SLOWLOG.spec.ts index 00ec90e9450..5f8d1107527 100644 --- a/packages/graph/lib/commands/SLOWLOG.spec.ts +++ b/packages/graph/lib/commands/SLOWLOG.spec.ts @@ -1,8 +1,8 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SLOWLOG'; +import SLOWLOG from './SLOWLOG'; -describe('SLOWLOG', () => { +describe('GRAPH.SLOWLOG', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('key'), @@ -11,8 +11,10 @@ describe('SLOWLOG', () => { }); testUtils.testWithClient('client.graph.slowLog', async client => { - await client.graph.query('key', 'RETURN 1'); - const reply = await client.graph.slowLog('key'); + const [, reply] = await Promise.all([ + client.graph.query('key', 'RETURN 1'), + client.graph.slowLog('key') + ]); assert.equal(reply.length, 1); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/SLOWLOG.ts b/packages/graph/lib/commands/SLOWLOG.ts index 6ae87af89bf..b0271ccae68 100644 --- a/packages/graph/lib/commands/SLOWLOG.ts +++ b/packages/graph/lib/commands/SLOWLOG.ts @@ -1,30 +1,24 @@ -export const IS_READ_ONLY = true; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; +type SlowLogRawReply = ArrayReply>; -export function transformArguments(key: string) { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { return ['GRAPH.SLOWLOG', key]; -} - -type SlowLogRawReply = Array<[ - timestamp: string, - command: string, - query: string, - took: string -]>; - -type SlowLogReply = Array<{ - timestamp: Date; - command: string; - query: string; - took: number; -}>; - -export function transformReply(logs: SlowLogRawReply): SlowLogReply { - return logs.map(([timestamp, command, query, took]) => ({ - timestamp: new Date(Number(timestamp) * 1000), - command, - query, - took: Number(took) + }, + transformReply(reply: SlowLogRawReply) { + return reply.map(([timestamp, command, query, took]) => ({ + timestamp: Number(timestamp), + command, + query, + took: Number(took) })); -} + } +} as const satisfies Command; diff --git a/packages/graph/lib/commands/index.spec.ts b/packages/graph/lib/commands/index.spec.ts deleted file mode 100644 index a688c49dd39..00000000000 --- a/packages/graph/lib/commands/index.spec.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { strict as assert } from 'assert'; -import { pushQueryArguments } from '.'; - -describe('pushQueryArguments', () => { - it('simple', () => { - assert.deepEqual( - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query'), - ['GRAPH.QUERY', 'graph', 'query'] - ); - }); - - describe('params', () => { - it('all types', () => { - assert.deepEqual( - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query', { - params: { - null: null, - string: '"\\', - number: 0, - boolean: false, - array: [0], - object: {a: 0} - } - }), - ['GRAPH.QUERY', 'graph', 'CYPHER null=null string="\\"\\\\" number=0 boolean=false array=[0] object={a:0} query'] - ); - }); - - it('TypeError', () => { - assert.throws(() => { - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query', { - params: { - a: undefined as any - } - }) - }, TypeError); - }); - }); - - it('TIMEOUT backward compatible', () => { - assert.deepEqual( - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query', 1), - ['GRAPH.QUERY', 'graph', 'query', 'TIMEOUT', '1'] - ); - }); - - it('TIMEOUT', () => { - assert.deepEqual( - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query', { - TIMEOUT: 1 - }), - ['GRAPH.QUERY', 'graph', 'query', 'TIMEOUT', '1'] - ); - }); - - it('compact', () => { - assert.deepEqual( - pushQueryArguments(['GRAPH.QUERY'], 'graph', 'query', undefined, true), - ['GRAPH.QUERY', 'graph', 'query', '--compact'] - ); - }); -}); diff --git a/packages/graph/lib/commands/index.ts b/packages/graph/lib/commands/index.ts index 2acf9089ee6..cba3305a3f1 100644 --- a/packages/graph/lib/commands/index.ts +++ b/packages/graph/lib/commands/index.ts @@ -1,114 +1,31 @@ -import * as CONFIG_GET from './CONFIG_GET'; -import * as CONFIG_SET from './CONFIG_SET';; -import * as DELETE from './DELETE'; -import * as EXPLAIN from './EXPLAIN'; -import * as LIST from './LIST'; -import * as PROFILE from './PROFILE'; -import * as QUERY from './QUERY'; -import * as RO_QUERY from './RO_QUERY'; -import * as SLOWLOG from './SLOWLOG'; -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; +import CONFIG_GET from './CONFIG_GET'; +import CONFIG_SET from './CONFIG_SET';; +import DELETE from './DELETE'; +import EXPLAIN from './EXPLAIN'; +import LIST from './LIST'; +import PROFILE from './PROFILE'; +import QUERY from './QUERY'; +import RO_QUERY from './RO_QUERY'; +// import SLOWLOG from './SLOWLOG'; export default { - CONFIG_GET, - configGet: CONFIG_GET, - CONFIG_SET, - configSet: CONFIG_SET, - DELETE, - delete: DELETE, - EXPLAIN, - explain: EXPLAIN, - LIST, - list: LIST, - PROFILE, - profile: PROFILE, - QUERY, - query: QUERY, - RO_QUERY, - roQuery: RO_QUERY, - SLOWLOG, - slowLog: SLOWLOG -}; - -type QueryParam = null | string | number | boolean | QueryParams | Array; - -type QueryParams = { - [key: string]: QueryParam; -}; - -export interface QueryOptions { - params?: QueryParams; - TIMEOUT?: number; -} - -export type QueryOptionsBackwardCompatible = QueryOptions | number; - -export function pushQueryArguments( - args: RedisCommandArguments, - graph: RedisCommandArgument, - query: RedisCommandArgument, - options?: QueryOptionsBackwardCompatible, - compact?: boolean -): RedisCommandArguments { - args.push(graph); - - if (typeof options === 'number') { - args.push(query); - pushTimeout(args, options); - } else { - args.push( - options?.params ? - `CYPHER ${queryParamsToString(options.params)} ${query}` : - query - ); - - if (options?.TIMEOUT !== undefined) { - pushTimeout(args, options.TIMEOUT); - } - } - - if (compact) { - args.push('--compact'); - } - - return args; -} - -function pushTimeout(args: RedisCommandArguments, timeout: number): void { - args.push('TIMEOUT', timeout.toString()); -} - -function queryParamsToString(params: QueryParams): string { - const parts = []; - for (const [key, value] of Object.entries(params)) { - parts.push(`${key}=${queryParamToString(value)}`); - } - return parts.join(' '); -} - -function queryParamToString(param: QueryParam): string { - if (param === null) { - return 'null'; - } - - switch (typeof param) { - case 'string': - return `"${param.replace(/["\\]/g, '\\$&')}"`; - - case 'number': - case 'boolean': - return param.toString(); - } - - if (Array.isArray(param)) { - return `[${param.map(queryParamToString).join(',')}]`; - } else if (typeof param === 'object') { - const body = []; - for (const [key, value] of Object.entries(param)) { - body.push(`${key}:${queryParamToString(value)}`); - } - return `{${body.join(',')}}`; - } else { - throw new TypeError(`Unexpected param type ${typeof param} ${param}`) - } -} + CONFIG_GET, + configGet: CONFIG_GET, + CONFIG_SET, + configSet: CONFIG_SET, + DELETE, + delete: DELETE, + EXPLAIN, + explain: EXPLAIN, + LIST, + list: LIST, + PROFILE, + profile: PROFILE, + QUERY, + query: QUERY, + RO_QUERY, + roQuery: RO_QUERY, + // SLOWLOG, + // slowLog: SLOWLOG +} as const satisfies RedisCommands; diff --git a/packages/graph/lib/graph.spec.ts b/packages/graph/lib/graph.spec.ts index 495c6d17a8a..13b8e6145bb 100644 --- a/packages/graph/lib/graph.spec.ts +++ b/packages/graph/lib/graph.spec.ts @@ -3,146 +3,146 @@ import testUtils, { GLOBAL } from './test-utils'; import Graph from './graph'; describe('Graph', () => { - testUtils.testWithClient('null', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN null AS key'); - - assert.deepEqual( - data, - [{ key: null }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('string', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN "string" AS key'); - - assert.deepEqual( - data, - [{ key: 'string' }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('integer', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN 0 AS key'); - - assert.deepEqual( - data, - [{ key: 0 }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('boolean', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN false AS key'); - - assert.deepEqual( - data, - [{ key: false }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('double', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN 0.1 AS key'); - - assert.deepEqual( - data, - [{ key: 0.1 }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('array', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN [null] AS key'); - - assert.deepEqual( - data, - [{ key: [null] }] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('edge', async client => { - const graph = new Graph(client as any, 'graph'); - - // check with and without metadata cache - for (let i = 0; i < 2; i++) { - const { data } = await graph.query('CREATE ()-[edge :edge]->() RETURN edge'); - assert.ok(Array.isArray(data)); - assert.equal(data.length, 1); - assert.equal(typeof data[0].edge.id, 'number'); - assert.equal(data[0].edge.relationshipType, 'edge'); - assert.equal(typeof data[0].edge.sourceId, 'number'); - assert.equal(typeof data[0].edge.destinationId, 'number'); - assert.deepEqual(data[0].edge.properties, {}); - } - - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('node', async client => { - const graph = new Graph(client as any, 'graph'); - - // check with and without metadata cache - for (let i = 0; i < 2; i++) { - const { data } = await graph.query('CREATE (node :node { p: 0 }) RETURN node'); - assert.ok(Array.isArray(data)); - assert.equal(data.length, 1); - assert.equal(typeof data[0].node.id, 'number'); - assert.deepEqual(data[0].node.labels, ['node']); - assert.deepEqual(data[0].node.properties, { p: 0 }); - } - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('path', async client => { - const graph = new Graph(client as any, 'graph'), - [, { data }] = await Promise.all([ - await graph.query('CREATE ()-[:edge]->()'), - await graph.roQuery('MATCH path = ()-[:edge]->() RETURN path') - ]); - - assert.ok(Array.isArray(data)); - assert.equal(data.length, 1); - - assert.ok(Array.isArray(data[0].path.nodes)); - assert.equal(data[0].path.nodes.length, 2); - for (const node of data[0].path.nodes) { - assert.equal(typeof node.id, 'number'); - assert.deepEqual(node.labels, []); - assert.deepEqual(node.properties, {}); - } - - assert.ok(Array.isArray(data[0].path.edges)); - assert.equal(data[0].path.edges.length, 1); - for (const edge of data[0].path.edges) { - assert.equal(typeof edge.id, 'number'); - assert.equal(edge.relationshipType, 'edge'); - assert.equal(typeof edge.sourceId, 'number'); - assert.equal(typeof edge.destinationId, 'number'); - assert.deepEqual(edge.properties, {}); - } - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('map', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN { key: "value" } AS map'); - - assert.deepEqual(data, [{ - map: { - key: 'value' - } - }]); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('point', async client => { - const graph = new Graph(client as any, 'graph'), - { data } = await graph.query('RETURN point({ latitude: 1, longitude: 2 }) AS point'); - - assert.deepEqual(data, [{ - point: { - latitude: 1, - longitude: 2 - } - }]); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('null', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN null AS key'); + + assert.deepEqual( + data, + [{ key: null }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('string', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN "string" AS key'); + + assert.deepEqual( + data, + [{ key: 'string' }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('integer', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN 0 AS key'); + + assert.deepEqual( + data, + [{ key: 0 }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('boolean', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN false AS key'); + + assert.deepEqual( + data, + [{ key: false }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('double', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN 0.1 AS key'); + + assert.deepEqual( + data, + [{ key: 0.1 }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('array', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN [null] AS key'); + + assert.deepEqual( + data, + [{ key: [null] }] + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('edge', async client => { + const graph = new Graph(client as any, 'graph'); + + // check with and without metadata cache + for (let i = 0; i < 2; i++) { + const { data } = await graph.query('CREATE ()-[edge :edge]->() RETURN edge'); + assert.ok(Array.isArray(data)); + assert.equal(data.length, 1); + assert.equal(typeof data[0].edge.id, 'number'); + assert.equal(data[0].edge.relationshipType, 'edge'); + assert.equal(typeof data[0].edge.sourceId, 'number'); + assert.equal(typeof data[0].edge.destinationId, 'number'); + assert.deepEqual(data[0].edge.properties, {}); + } + + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('node', async client => { + const graph = new Graph(client as any, 'graph'); + + // check with and without metadata cache + for (let i = 0; i < 2; i++) { + const { data } = await graph.query('CREATE (node :node { p: 0 }) RETURN node'); + assert.ok(Array.isArray(data)); + assert.equal(data.length, 1); + assert.equal(typeof data[0].node.id, 'number'); + assert.deepEqual(data[0].node.labels, ['node']); + assert.deepEqual(data[0].node.properties, { p: 0 }); + } + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('path', async client => { + const graph = new Graph(client as any, 'graph'), + [, { data }] = await Promise.all([ + await graph.query('CREATE ()-[:edge]->()'), + await graph.roQuery('MATCH path = ()-[:edge]->() RETURN path') + ]); + + assert.ok(Array.isArray(data)); + assert.equal(data.length, 1); + + assert.ok(Array.isArray(data[0].path.nodes)); + assert.equal(data[0].path.nodes.length, 2); + for (const node of data[0].path.nodes) { + assert.equal(typeof node.id, 'number'); + assert.deepEqual(node.labels, []); + assert.deepEqual(node.properties, {}); + } + + assert.ok(Array.isArray(data[0].path.edges)); + assert.equal(data[0].path.edges.length, 1); + for (const edge of data[0].path.edges) { + assert.equal(typeof edge.id, 'number'); + assert.equal(edge.relationshipType, 'edge'); + assert.equal(typeof edge.sourceId, 'number'); + assert.equal(typeof edge.destinationId, 'number'); + assert.deepEqual(edge.properties, {}); + } + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('map', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN { key: "value" } AS map'); + + assert.deepEqual(data, [{ + map: { + key: 'value' + } + }]); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('point', async client => { + const graph = new Graph(client as any, 'graph'), + { data } = await graph.query('RETURN point({ latitude: 1, longitude: 2 }) AS point'); + + assert.deepEqual(data, [{ + point: { + latitude: 1, + longitude: 2 + } + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/graph.ts b/packages/graph/lib/graph.ts index 5baff1dae29..8866052bdad 100644 --- a/packages/graph/lib/graph.ts +++ b/packages/graph/lib/graph.ts @@ -1,359 +1,359 @@ import { RedisClientType } from '@redis/client/dist/lib/client/index'; -import { RedisCommandArgument, RedisFunctions, RedisScripts } from '@redis/client/dist/lib/commands'; -import { QueryOptions } from './commands'; -import { QueryReply } from './commands/QUERY'; +import { RedisArgument, RedisFunctions, RedisScripts } from '@redis/client/dist/lib/RESP/types'; +import QUERY, { QueryOptions } from './commands/QUERY'; interface GraphMetadata { - labels: Array; - relationshipTypes: Array; - propertyKeys: Array; + labels: Array; + relationshipTypes: Array; + propertyKeys: Array; } // https://github.com/RedisGraph/RedisGraph/blob/master/src/resultset/formatters/resultset_formatter.h#L20 enum GraphValueTypes { - UNKNOWN = 0, - NULL = 1, - STRING = 2, - INTEGER = 3, - BOOLEAN = 4, - DOUBLE = 5, - ARRAY = 6, - EDGE = 7, - NODE = 8, - PATH = 9, - MAP = 10, - POINT = 11 + UNKNOWN = 0, + NULL = 1, + STRING = 2, + INTEGER = 3, + BOOLEAN = 4, + DOUBLE = 5, + ARRAY = 6, + EDGE = 7, + NODE = 8, + PATH = 9, + MAP = 10, + POINT = 11 } type GraphEntityRawProperties = Array<[ - id: number, - ...value: GraphRawValue + id: number, + ...value: GraphRawValue ]>; type GraphEdgeRawValue = [ - GraphValueTypes.EDGE, - [ - id: number, - relationshipTypeId: number, - sourceId: number, - destinationId: number, - properties: GraphEntityRawProperties - ] + GraphValueTypes.EDGE, + [ + id: number, + relationshipTypeId: number, + sourceId: number, + destinationId: number, + properties: GraphEntityRawProperties + ] ]; type GraphNodeRawValue = [ - GraphValueTypes.NODE, - [ - id: number, - labelIds: Array, - properties: GraphEntityRawProperties - ] + GraphValueTypes.NODE, + [ + id: number, + labelIds: Array, + properties: GraphEntityRawProperties + ] ]; type GraphPathRawValue = [ - GraphValueTypes.PATH, - [ - nodes: [ - GraphValueTypes.ARRAY, - Array - ], - edges: [ - GraphValueTypes.ARRAY, - Array - ] + GraphValueTypes.PATH, + [ + nodes: [ + GraphValueTypes.ARRAY, + Array + ], + edges: [ + GraphValueTypes.ARRAY, + Array ] + ] ]; type GraphMapRawValue = [ - GraphValueTypes.MAP, - Array + GraphValueTypes.MAP, + Array ]; type GraphRawValue = [ - GraphValueTypes.NULL, - null + GraphValueTypes.NULL, + null ] | [ - GraphValueTypes.STRING, - string + GraphValueTypes.STRING, + string ] | [ - GraphValueTypes.INTEGER, - number + GraphValueTypes.INTEGER, + number ] | [ - GraphValueTypes.BOOLEAN, - string + GraphValueTypes.BOOLEAN, + string ] | [ - GraphValueTypes.DOUBLE, - string + GraphValueTypes.DOUBLE, + string ] | [ - GraphValueTypes.ARRAY, - Array + GraphValueTypes.ARRAY, + Array ] | GraphEdgeRawValue | GraphNodeRawValue | GraphPathRawValue | GraphMapRawValue | [ - GraphValueTypes.POINT, - [ - latitude: string, - longitude: string - ] + GraphValueTypes.POINT, + [ + latitude: string, + longitude: string + ] ]; type GraphEntityProperties = Record; interface GraphEdge { - id: number; - relationshipType: string; - sourceId: number; - destinationId: number; - properties: GraphEntityProperties; + id: number; + relationshipType: string; + sourceId: number; + destinationId: number; + properties: GraphEntityProperties; } interface GraphNode { - id: number; - labels: Array; - properties: GraphEntityProperties; + id: number; + labels: Array; + properties: GraphEntityProperties; } interface GraphPath { - nodes: Array; - edges: Array; + nodes: Array; + edges: Array; } type GraphMap = { - [key: string]: GraphValue; + [key: string]: GraphValue; }; type GraphValue = null | string | number | boolean | Array | { } | GraphEdge | GraphNode | GraphPath | GraphMap | { - latitude: string; - longitude: string; + latitude: string; + longitude: string; }; -type GraphReply = Omit & { - data?: Array; +type GraphReply = { + data?: Array; }; type GraphClientType = RedisClientType<{ - graph: { - query: typeof import('./commands/QUERY'), - roQuery: typeof import('./commands/RO_QUERY') - } + graph: { + query: typeof QUERY, + roQuery: typeof import('./commands/RO_QUERY').default + } }, RedisFunctions, RedisScripts>; export default class Graph { - #client: GraphClientType; - #name: string; - #metadata?: GraphMetadata; - - constructor( - client: GraphClientType, - name: string - ) { - this.#client = client; - this.#name = name; - } - - async query( - query: RedisCommandArgument, - options?: QueryOptions - ) { - return this.#parseReply( - await this.#client.graph.query( - this.#name, - query, - options, - true - ) - ); - } - - async roQuery( - query: RedisCommandArgument, - options?: QueryOptions - ) { - return this.#parseReply( - await this.#client.graph.roQuery( - this.#name, - query, - options, - true - ) - ); - } - - #setMetadataPromise?: Promise; - - #updateMetadata(): Promise { - this.#setMetadataPromise ??= this.#setMetadata() - .finally(() => this.#setMetadataPromise = undefined); - return this.#setMetadataPromise; - } - - // DO NOT use directly, use #updateMetadata instead - async #setMetadata(): Promise { - const [labels, relationshipTypes, propertyKeys] = await Promise.all([ - this.#client.graph.roQuery(this.#name, 'CALL db.labels()'), - this.#client.graph.roQuery(this.#name, 'CALL db.relationshipTypes()'), - this.#client.graph.roQuery(this.#name, 'CALL db.propertyKeys()') - ]); - - this.#metadata = { - labels: this.#cleanMetadataArray(labels.data as Array<[string]>), - relationshipTypes: this.#cleanMetadataArray(relationshipTypes.data as Array<[string]>), - propertyKeys: this.#cleanMetadataArray(propertyKeys.data as Array<[string]>) - }; - - return this.#metadata; - } - - #cleanMetadataArray(arr: Array<[string]>): Array { - return arr.map(([value]) => value); - } - - #getMetadata( - key: T, - id: number - ): GraphMetadata[T][number] | Promise { - return this.#metadata?.[key][id] ?? this.#getMetadataAsync(key, id); - } - - // DO NOT use directly, use #getMetadata instead - async #getMetadataAsync( - key: T, - id: number - ): Promise { - const value = (await this.#updateMetadata())[key][id]; - if (value === undefined) throw new Error(`Cannot find value from ${key}[${id}]`); + #client: GraphClientType; + #name: string; + #metadata?: GraphMetadata; + + constructor( + client: GraphClientType, + name: string + ) { + this.#client = client; + this.#name = name; + } + + async query( + query: RedisArgument, + options?: QueryOptions + ) { + return this.#parseReply( + await this.#client.graph.query( + this.#name, + query, + options, + true + ) + ); + } + + async roQuery( + query: RedisArgument, + options?: QueryOptions + ) { + return this.#parseReply( + await this.#client.graph.roQuery( + this.#name, + query, + options, + true + ) + ); + } + + #setMetadataPromise?: Promise; + + #updateMetadata(): Promise { + this.#setMetadataPromise ??= this.#setMetadata() + .finally(() => this.#setMetadataPromise = undefined); + return this.#setMetadataPromise; + } + + // DO NOT use directly, use #updateMetadata instead + async #setMetadata(): Promise { + const [labels, relationshipTypes, propertyKeys] = await Promise.all([ + this.#client.graph.roQuery(this.#name, 'CALL db.labels()'), + this.#client.graph.roQuery(this.#name, 'CALL db.relationshipTypes()'), + this.#client.graph.roQuery(this.#name, 'CALL db.propertyKeys()') + ]); + + this.#metadata = { + labels: this.#cleanMetadataArray(labels.data as Array<[string]>), + relationshipTypes: this.#cleanMetadataArray(relationshipTypes.data as Array<[string]>), + propertyKeys: this.#cleanMetadataArray(propertyKeys.data as Array<[string]>) + }; + + return this.#metadata; + } + + #cleanMetadataArray(arr: Array<[string]>): Array { + return arr.map(([value]) => value); + } + + #getMetadata( + key: T, + id: number + ): GraphMetadata[T][number] | Promise { + return this.#metadata?.[key][id] ?? this.#getMetadataAsync(key, id); + } + + // DO NOT use directly, use #getMetadata instead + async #getMetadataAsync( + key: T, + id: number + ): Promise { + const value = (await this.#updateMetadata())[key][id]; + if (value === undefined) throw new Error(`Cannot find value from ${key}[${id}]`); + return value; + } + + // TODO: reply type + async #parseReply(reply: any): Promise> { + if (!reply.data) return reply; + + const promises: Array> = [], + parsed = { + metadata: reply.metadata, + data: reply.data!.map((row: any) => { + const data: Record = {}; + for (let i = 0; i < row.length; i++) { + data[reply.headers[i][1]] = this.#parseValue(row[i], promises); + } + + return data as unknown as T; + }) + }; + + if (promises.length) await Promise.all(promises); + + return parsed; + } + + #parseValue([valueType, value]: GraphRawValue, promises: Array>): GraphValue { + switch (valueType) { + case GraphValueTypes.NULL: + return null; + + case GraphValueTypes.STRING: + case GraphValueTypes.INTEGER: return value; - } - async #parseReply(reply: QueryReply): Promise> { - if (!reply.data) return reply; + case GraphValueTypes.BOOLEAN: + return value === 'true'; - const promises: Array> = [], - parsed = { - metadata: reply.metadata, - data: reply.data!.map((row: any) => { - const data: Record = {}; - for (let i = 0; i < row.length; i++) { - data[reply.headers[i][1]] = this.#parseValue(row[i], promises); - } + case GraphValueTypes.DOUBLE: + return parseFloat(value); - return data as unknown as T; - }) - }; + case GraphValueTypes.ARRAY: + return value.map(x => this.#parseValue(x, promises)); - if (promises.length) await Promise.all(promises); + case GraphValueTypes.EDGE: + return this.#parseEdge(value, promises); - return parsed; - } - - #parseValue([valueType, value]: GraphRawValue, promises: Array>): GraphValue { - switch (valueType) { - case GraphValueTypes.NULL: - return null; - - case GraphValueTypes.STRING: - case GraphValueTypes.INTEGER: - return value; - - case GraphValueTypes.BOOLEAN: - return value === 'true'; - - case GraphValueTypes.DOUBLE: - return parseFloat(value); - - case GraphValueTypes.ARRAY: - return value.map(x => this.#parseValue(x, promises)); - - case GraphValueTypes.EDGE: - return this.#parseEdge(value, promises); - - case GraphValueTypes.NODE: - return this.#parseNode(value, promises); - - case GraphValueTypes.PATH: - return { - nodes: value[0][1].map(([, node]) => this.#parseNode(node, promises)), - edges: value[1][1].map(([, edge]) => this.#parseEdge(edge, promises)) - }; - - case GraphValueTypes.MAP: - const map: GraphMap = {}; - for (let i = 0; i < value.length; i++) { - map[value[i++] as string] = this.#parseValue(value[i] as GraphRawValue, promises); - } - - return map; - - case GraphValueTypes.POINT: - return { - latitude: parseFloat(value[0]), - longitude: parseFloat(value[1]) - }; + case GraphValueTypes.NODE: + return this.#parseNode(value, promises); - default: - throw new Error(`unknown scalar type: ${valueType}`); - } - } + case GraphValueTypes.PATH: + return { + nodes: value[0][1].map(([, node]) => this.#parseNode(node, promises)), + edges: value[1][1].map(([, edge]) => this.#parseEdge(edge, promises)) + }; - #parseEdge([ - id, - relationshipTypeId, - sourceId, - destinationId, - properties - ]: GraphEdgeRawValue[1], promises: Array>): GraphEdge { - const edge = { - id, - sourceId, - destinationId, - properties: this.#parseProperties(properties, promises) - } as GraphEdge; - - const relationshipType = this.#getMetadata('relationshipTypes', relationshipTypeId); - if (relationshipType instanceof Promise) { - promises.push( - relationshipType.then(value => edge.relationshipType = value) - ); - } else { - edge.relationshipType = relationshipType; + case GraphValueTypes.MAP: + const map: GraphMap = {}; + for (let i = 0; i < value.length; i++) { + map[value[i++] as string] = this.#parseValue(value[i] as GraphRawValue, promises); } - return edge; - } - - #parseNode([ - id, - labelIds, - properties - ]: GraphNodeRawValue[1], promises: Array>): GraphNode { - const labels = new Array(labelIds.length); - for (let i = 0; i < labelIds.length; i++) { - const value = this.#getMetadata('labels', labelIds[i]); - if (value instanceof Promise) { - promises.push(value.then(value => labels[i] = value)); - } else { - labels[i] = value; - } - } + return map; + case GraphValueTypes.POINT: return { - id, - labels, - properties: this.#parseProperties(properties, promises) + latitude: parseFloat(value[0]), + longitude: parseFloat(value[1]) }; + + default: + throw new Error(`unknown scalar type: ${valueType}`); + } + } + + #parseEdge([ + id, + relationshipTypeId, + sourceId, + destinationId, + properties + ]: GraphEdgeRawValue[1], promises: Array>): GraphEdge { + const edge = { + id, + sourceId, + destinationId, + properties: this.#parseProperties(properties, promises) + } as GraphEdge; + + const relationshipType = this.#getMetadata('relationshipTypes', relationshipTypeId); + if (relationshipType instanceof Promise) { + promises.push( + relationshipType.then(value => edge.relationshipType = value) + ); + } else { + edge.relationshipType = relationshipType; } - #parseProperties(raw: GraphEntityRawProperties, promises: Array>): GraphEntityProperties { - const parsed: GraphEntityProperties = {}; - for (const [id, type, value] of raw) { - const parsedValue = this.#parseValue([type, value] as GraphRawValue, promises), - key = this.#getMetadata('propertyKeys', id); - if (key instanceof Promise) { - promises.push(key.then(key => parsed[key] = parsedValue)); - } else { - parsed[key] = parsedValue; - } - } + return edge; + } + + #parseNode([ + id, + labelIds, + properties + ]: GraphNodeRawValue[1], promises: Array>): GraphNode { + const labels = new Array(labelIds.length); + for (let i = 0; i < labelIds.length; i++) { + const value = this.#getMetadata('labels', labelIds[i]); + if (value instanceof Promise) { + promises.push(value.then(value => labels[i] = value)); + } else { + labels[i] = value; + } + } - return parsed; + return { + id, + labels, + properties: this.#parseProperties(properties, promises) + }; + } + + #parseProperties(raw: GraphEntityRawProperties, promises: Array>): GraphEntityProperties { + const parsed: GraphEntityProperties = {}; + for (const [id, type, value] of raw) { + const parsedValue = this.#parseValue([type, value] as GraphRawValue, promises), + key = this.#getMetadata('propertyKeys', id); + if (key instanceof Promise) { + promises.push(key.then(key => parsed[key] = parsedValue)); + } else { + parsed[key] = parsedValue; + } } + + return parsed; + } } diff --git a/packages/graph/lib/test-utils.ts b/packages/graph/lib/test-utils.ts index 56c0af56a2e..e00b03fc692 100644 --- a/packages/graph/lib/test-utils.ts +++ b/packages/graph/lib/test-utils.ts @@ -2,19 +2,19 @@ import TestUtils from '@redis/test-utils'; import RedisGraph from '.'; export default new TestUtils({ - dockerImageName: 'redislabs/redisgraph', - dockerImageVersionArgument: 'redisgraph-version' + dockerImageName: 'redislabs/redisgraph', + dockerImageVersionArgument: 'redisgraph-version' }); export const GLOBAL = { - SERVERS: { - OPEN: { - serverArguments: ['--loadmodule /usr/lib/redis/modules/redisgraph.so'], - clientOptions: { - modules: { - graph: RedisGraph - } - } + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/redisgraph.so'], + clientOptions: { + modules: { + graph: RedisGraph } + } } + } }; diff --git a/packages/graph/package.json b/packages/graph/package.json index 17ae40d3b55..9f819a0f79f 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -5,10 +5,12 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" }, + "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + }, "peerDependencies": { "@redis/client": "*" }, From 384f6ca78f019651ad3be238b103a8cbd9b0c1f9 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 10 Jul 2023 12:23:14 -0400 Subject: [PATCH 183/325] graph docs --- docs/v4-to-v5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 725b24d9ce7..9536523ae00 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -176,6 +176,7 @@ Some command arguments/replies have changed to align more closely to data types - `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record }>; }>` -> `Record }>>` - `FT.SUGDEL`: [^boolean-to-number] - `TOPK.QUERY`: `Array` -> `Array` +- `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` [^enum-to-constants]: TODO From d2b0b4e5b0fff17d5e78bb8647840aefd8f74ad1 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 10 Jul 2023 12:29:36 -0400 Subject: [PATCH 184/325] more commands --- packages/json/lib/commands/ARRAPPEND.spec.ts | 42 +++++++-------- packages/json/lib/commands/ARRAPPEND.ts | 16 +++--- packages/json/lib/commands/ARRINDEX.spec.ts | 54 +++++++++---------- packages/json/lib/commands/ARRINDEX.ts | 30 ++++++----- packages/search/lib/commands/DICTDUMP.spec.ts | 28 +++++----- packages/search/lib/commands/DICTDUMP.ts | 16 ++++-- .../search/lib/commands/DROPINDEX.spec.ts | 46 ++++++++-------- packages/search/lib/commands/DROPINDEX.ts | 22 +++++--- packages/search/lib/commands/TAGVALS.spec.ts | 32 +++++------ packages/search/lib/commands/TAGVALS.ts | 16 ++++-- packages/search/lib/commands/_LIST.spec.ts | 26 ++++----- packages/search/lib/commands/_LIST.ts | 16 ++++-- 12 files changed, 192 insertions(+), 152 deletions(-) diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts index ab53837a000..cd2001d5ea5 100644 --- a/packages/json/lib/commands/ARRAPPEND.spec.ts +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ARRAPPEND'; +import ARRAPPEND from './ARRAPPEND'; describe('ARRAPPEND', () => { - describe('transformArguments', () => { - it('single JSON', () => { - assert.deepEqual( - transformArguments('key', '$', 1), - ['JSON.ARRAPPEND', 'key', '$', '1'] - ); - }); + describe('transformArguments', () => { + it('single JSON', () => { + assert.deepEqual( + ARRAPPEND.transformArguments('key', '$', 1), + ['JSON.ARRAPPEND', 'key', '$', '1'] + ); + }); - it('multiple JSONs', () => { - assert.deepEqual( - transformArguments('key', '$', 1, 2), - ['JSON.ARRAPPEND', 'key', '$', '1', '2'] - ); - }); + it('multiple JSONs', () => { + assert.deepEqual( + ARRAPPEND.transformArguments('key', '$', 1, 2), + ['JSON.ARRAPPEND', 'key', '$', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.json.arrAppend', async client => { - await client.json.set('key', '$', []); + testUtils.testWithClient('client.json.arrAppend', async client => { + await client.json.set('key', '$', []); - assert.deepEqual( - await client.json.arrAppend('key', '$', 1), - [1] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 2935d192996..ce809876479 100644 --- a/packages/json/lib/commands/ARRAPPEND.ts +++ b/packages/json/lib/commands/ARRAPPEND.ts @@ -1,15 +1,17 @@ import { RedisJSON, transformRedisJsonArgument } from '.'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string, path: string, ...jsons: Array): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, ...jsons: Array) { const args = ['JSON.ARRAPPEND', key, path]; for (const json of jsons) { - args.push(transformRedisJsonArgument(json)); + args.push(transformRedisJsonArgument(json)); } return args; -} - -export declare function transformReply(): number | Array; + }, + transformReply: undefined as unknown as () => NumberReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/ARRINDEX.spec.ts b/packages/json/lib/commands/ARRINDEX.spec.ts index 7a47d67126a..290d0a237f6 100644 --- a/packages/json/lib/commands/ARRINDEX.spec.ts +++ b/packages/json/lib/commands/ARRINDEX.spec.ts @@ -1,37 +1,37 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ARRINDEX'; +import ARRINDEX from './ARRINDEX'; describe('ARRINDEX', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', '$', 'json'), - ['JSON.ARRINDEX', 'key', '$', '"json"'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ARRINDEX.transformArguments('key', '$', 'json'), + ['JSON.ARRINDEX', 'key', '$', '"json"'] + ); + }); - it('with start', () => { - assert.deepEqual( - transformArguments('key', '$', 'json', 1), - ['JSON.ARRINDEX', 'key', '$', '"json"', '1'] - ); - }); + it('with start', () => { + assert.deepEqual( + ARRINDEX.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'] - ); - }); + it('with start, end', () => { + assert.deepEqual( + ARRINDEX.transformArguments('key', '$', 'json', 1, 2), + ['JSON.ARRINDEX', 'key', '$', '"json"', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.json.arrIndex', async client => { - await client.json.set('key', '$', []); + testUtils.testWithClient('client.json.arrIndex', async client => { + await client.json.set('key', '$', []); - assert.deepEqual( - await client.json.arrIndex('key', '$', 'json'), - [-1] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 5860b59cb3c..8c8c9e5df2a 100644 --- a/packages/json/lib/commands/ARRINDEX.ts +++ b/packages/json/lib/commands/ARRINDEX.ts @@ -1,21 +1,27 @@ +import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; 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 { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + path: RedisArgument, + json: RedisJSON, + start?: number, + stop?: number + ) { const args = ['JSON.ARRINDEX', key, path, transformRedisJsonArgument(json)]; if (start !== undefined && start !== null) { - args.push(start.toString()); + args.push(start.toString()); - if (stop !== undefined && stop !== null) { - args.push(stop.toString()); - } + if (stop !== undefined && stop !== null) { + args.push(stop.toString()); + } } return args; -} - -export declare function transformReply(): number | Array; + }, + transformReply: undefined as unknown as () => NumberReply | ArrayReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/DICTDUMP.spec.ts b/packages/search/lib/commands/DICTDUMP.spec.ts index 9896fb9440d..0e50a4a373f 100644 --- a/packages/search/lib/commands/DICTDUMP.spec.ts +++ b/packages/search/lib/commands/DICTDUMP.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './DICTDUMP'; +import DICTDUMP from './DICTDUMP'; describe('DICTDUMP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('dictionary'), - ['FT.DICTDUMP', 'dictionary'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + DICTDUMP.transformArguments('dictionary'), + ['FT.DICTDUMP', 'dictionary'] + ); + }); - testUtils.testWithClient('client.ft.dictDump', async client => { - await client.ft.dictAdd('dictionary', 'string') + testUtils.testWithClient('client.ft.dictDump', async client => { + await client.ft.dictAdd('dictionary', 'string') - assert.deepEqual( - await client.ft.dictDump('dictionary'), - ['string'] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 1427bb42cb7..f542403cc57 100644 --- a/packages/search/lib/commands/DICTDUMP.ts +++ b/packages/search/lib/commands/DICTDUMP.ts @@ -1,5 +1,13 @@ -export function transformArguments(dictionary: string): Array { - return ['FT.DICTDUMP', dictionary]; -} +import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(dictionary: RedisArgument) { + return ['FT.DICTDUMP', dictionary]; + }, + transformReply: { + 2: undefined as unknown as () => ArrayReply, + 3: undefined as unknown as () => SetReply + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/DROPINDEX.spec.ts b/packages/search/lib/commands/DROPINDEX.spec.ts index 6a60a5d851f..cb6ca192cd4 100644 --- a/packages/search/lib/commands/DROPINDEX.spec.ts +++ b/packages/search/lib/commands/DROPINDEX.spec.ts @@ -1,33 +1,33 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; -import { transformArguments } from './DROPINDEX'; +import DROPINDEX from './DROPINDEX'; describe('DROPINDEX', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index'), - ['FT.DROPINDEX', 'index'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + DROPINDEX.transformArguments('index'), + ['FT.DROPINDEX', 'index'] + ); + }); - it('with DD', () => { - assert.deepEqual( - transformArguments('index', { DD: true }), - ['FT.DROPINDEX', 'index', 'DD'] - ); - }); + it('with DD', () => { + assert.deepEqual( + DROPINDEX.transformArguments('index', { DD: true }), + ['FT.DROPINDEX', 'index', 'DD'] + ); }); + }); - testUtils.testWithClient('client.ft.dropIndex', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + testUtils.testWithClient('client.ft.dropIndex', async client => { + await client.ft.create('index', { + field: SchemaFieldTypes.TEXT + }); - assert.equal( - await client.ft.dropIndex('index'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 7897a9dd82e..fe25a79e97b 100644 --- a/packages/search/lib/commands/DROPINDEX.ts +++ b/packages/search/lib/commands/DROPINDEX.ts @@ -1,15 +1,23 @@ -interface DropIndexOptions { - DD?: true; +import { RedisArgument, SimpleStringReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export interface FtDropIndexOptions { + DD?: true; } -export function transformArguments(index: string, options?: DropIndexOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(index: RedisArgument, options?: FtDropIndexOptions) { const args = ['FT.DROPINDEX', index]; if (options?.DD) { - args.push('DD'); + args.push('DD'); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: { + 2: undefined as unknown as () => SimpleStringReply<'OK'>, + 3: undefined as unknown as () => NumberReply + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/TAGVALS.spec.ts b/packages/search/lib/commands/TAGVALS.spec.ts index d59bfcfe3ea..52bb66c1ce7 100644 --- a/packages/search/lib/commands/TAGVALS.spec.ts +++ b/packages/search/lib/commands/TAGVALS.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; -import { transformArguments } from './TAGVALS'; +import TAGVALS from './TAGVALS'; describe('TAGVALS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index', '@field'), - ['FT.TAGVALS', 'index', '@field'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + TAGVALS.transformArguments('index', '@field'), + ['FT.TAGVALS', 'index', '@field'] + ); + }); - testUtils.testWithClient('client.ft.tagVals', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TAG - }); + 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); + 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 index 54342f0c9e5..7c58a1f9d11 100644 --- a/packages/search/lib/commands/TAGVALS.ts +++ b/packages/search/lib/commands/TAGVALS.ts @@ -1,5 +1,13 @@ -export function transformArguments(index: string, fieldName: string): Array { - return ['FT.TAGVALS', index, fieldName]; -} +import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(index: RedisArgument, fieldName: RedisArgument) { + return ['FT.TAGVALS', index, fieldName]; + }, + transformReply: { + 2: undefined as unknown as () => ArrayReply, + 3: undefined as unknown as () => SetReply + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/_LIST.spec.ts b/packages/search/lib/commands/_LIST.spec.ts index 602c29975f2..1b468db0d7e 100644 --- a/packages/search/lib/commands/_LIST.spec.ts +++ b/packages/search/lib/commands/_LIST.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './_LIST'; +import _LIST from './_LIST'; describe('_LIST', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['FT._LIST'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + _LIST.transformArguments(), + ['FT._LIST'] + ); + }); - testUtils.testWithClient('client.ft._list', async client => { - assert.deepEqual( - await client.ft._list(), - [] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 588ec837c3b..efb6c31acce 100644 --- a/packages/search/lib/commands/_LIST.ts +++ b/packages/search/lib/commands/_LIST.ts @@ -1,5 +1,13 @@ -export function transformArguments(): Array { - return ['FT._LIST']; -} +import { ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['FT._LIST']; + }, + transformReply: { + 2: undefined as unknown as () => ArrayReply, + 3: undefined as unknown as () => SetReply + } +} as const satisfies Command; From 75fc5a92d1cc37c227c713a4cffeffee51f40e1f Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 10 Jul 2023 16:46:57 -0400 Subject: [PATCH 185/325] JSON commands --- packages/json/lib/commands/ARRINSERT.spec.ts | 42 ++++++++-------- packages/json/lib/commands/ARRINSERT.ts | 16 +++--- packages/json/lib/commands/ARRLEN.spec.ts | 42 ++++++++-------- packages/json/lib/commands/ARRLEN.ts | 17 ++++--- packages/json/lib/commands/ARRTRIM.spec.ts | 28 +++++------ packages/json/lib/commands/ARRTRIM.ts | 13 +++-- packages/json/lib/commands/OBJLEN.spec.ts | 40 +++++++-------- packages/json/lib/commands/OBJLEN.ts | 15 +++--- packages/json/lib/commands/STRAPPEND.spec.ts | 52 ++++++++++---------- packages/json/lib/commands/STRAPPEND.ts | 28 +++++------ packages/json/lib/commands/STRLEN.spec.ts | 42 ++++++++-------- packages/json/lib/commands/STRLEN.ts | 17 ++++--- packages/json/lib/commands/TOGGLE.spec.ts | 30 +++++++++++ packages/json/lib/commands/TOGGLE.ts | 14 ++++++ 14 files changed, 225 insertions(+), 171 deletions(-) create mode 100644 packages/json/lib/commands/TOGGLE.spec.ts create mode 100644 packages/json/lib/commands/TOGGLE.ts diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts index 4b9d58b2cac..6adb3cd7676 100644 --- a/packages/json/lib/commands/ARRINSERT.spec.ts +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ARRINSERT'; +import ARRINSERT from './ARRINSERT'; describe('ARRINSERT', () => { - describe('transformArguments', () => { - it('single JSON', () => { - assert.deepEqual( - transformArguments('key', '$', 0, 'json'), - ['JSON.ARRINSERT', 'key', '$', '0', '"json"'] - ); - }); + describe('transformArguments', () => { + it('single JSON', () => { + assert.deepEqual( + ARRINSERT.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"'] - ); - }); + it('multiple JSONs', () => { + assert.deepEqual( + ARRINSERT.transformArguments('key', '$', 0, '1', '2'), + ['JSON.ARRINSERT', 'key', '$', '0', '"1"', '"2"'] + ); }); + }); - testUtils.testWithClient('client.json.arrInsert', async client => { - await client.json.set('key', '$', []); + 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); + 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 index 85857657019..66663c646fa 100644 --- a/packages/json/lib/commands/ARRINSERT.ts +++ b/packages/json/lib/commands/ARRINSERT.ts @@ -1,15 +1,17 @@ +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(key: string, path: string, index: number, ...jsons: Array): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, index: number, ...jsons: Array) { const args = ['JSON.ARRINSERT', key, path, index.toString()]; for (const json of jsons) { - args.push(transformRedisJsonArgument(json)); + args.push(transformRedisJsonArgument(json)); } return args; -} - -export declare function transformReply(): number | Array; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts index f0a3ec40a4c..d14531f0382 100644 --- a/packages/json/lib/commands/ARRLEN.spec.ts +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ARRLEN'; +import ARRLEN from './ARRLEN'; describe('ARRLEN', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.ARRLEN', 'key'] - ); - }); + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + ARRLEN.transformArguments('key'), + ['JSON.ARRLEN', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.ARRLEN', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + ARRLEN.transformArguments('key', '$'), + ['JSON.ARRLEN', 'key', '$'] + ); }); + }); - testUtils.testWithClient('client.json.arrLen', async client => { - await client.json.set('key', '$', []); + testUtils.testWithClient('client.json.arrLen', async client => { + await client.json.set('key', '$', []); - assert.deepEqual( - await client.json.arrLen('key', '$'), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 818397b7f8d..26155a109db 100644 --- a/packages/json/lib/commands/ARRLEN.ts +++ b/packages/json/lib/commands/ARRLEN.ts @@ -1,15 +1,16 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.ARRLEN', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number | Array; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/ARRTRIM.spec.ts b/packages/json/lib/commands/ARRTRIM.spec.ts index c254e1b6a03..0d44c88ccdb 100644 --- a/packages/json/lib/commands/ARRTRIM.spec.ts +++ b/packages/json/lib/commands/ARRTRIM.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ARRTRIM'; +import ARRTRIM from './ARRTRIM'; describe('ARRTRIM', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '$', 0, 1), - ['JSON.ARRTRIM', 'key', '$', '0', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + ARRTRIM.transformArguments('key', '$', 0, 1), + ['JSON.ARRTRIM', 'key', '$', '0', '1'] + ); + }); - testUtils.testWithClient('client.json.arrTrim', async client => { - await client.json.set('key', '$', []); + 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); + 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 index 2de444eeebd..a3de83fff10 100644 --- a/packages/json/lib/commands/ARRTRIM.ts +++ b/packages/json/lib/commands/ARRTRIM.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path: string, start: number, stop: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, start: number, stop: number) { return ['JSON.ARRTRIM', key, path, start.toString(), stop.toString()]; -} - -export declare function transformReply(): number | Array; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts index 35b6589c875..316a3ebf0e1 100644 --- a/packages/json/lib/commands/OBJLEN.spec.ts +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJLEN'; +import OBJLEN from './OBJLEN'; describe('OBJLEN', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.OBJLEN', 'key'] - ); - }); + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + OBJLEN.transformArguments('key'), + ['JSON.OBJLEN', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.OBJLEN', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + OBJLEN.transformArguments('key', '$'), + ['JSON.OBJLEN', 'key', '$'] + ); }); + }); - // testUtils.testWithClient('client.json.objLen', async client => { - // assert.equal( - // await client.json.objLen('key', '$'), - // [null] - // ); - // }, GLOBAL.SERVERS.OPEN); + // 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 index aa800e97f71..4063feea397 100644 --- a/packages/json/lib/commands/OBJLEN.ts +++ b/packages/json/lib/commands/OBJLEN.ts @@ -1,13 +1,16 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.OBJLEN', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number | null | Array; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/STRAPPEND.spec.ts b/packages/json/lib/commands/STRAPPEND.spec.ts index a37eaa1d91c..06e6b60b10c 100644 --- a/packages/json/lib/commands/STRAPPEND.spec.ts +++ b/packages/json/lib/commands/STRAPPEND.spec.ts @@ -1,30 +1,30 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './STRAPPEND'; +// 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"'] - ); - }); +// 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"'] - ); - }); - }); +// it('with path', () => { +// assert.deepEqual( +// transformArguments('key', '$', 'append'), +// ['JSON.STRAPPEND', 'key', '$', '"append"'] +// ); +// }); +// }); - testUtils.testWithClient('client.json.strAppend', async client => { - await client.json.set('key', '$', ''); +// testUtils.testWithClient('client.json.strAppend', async client => { +// await client.json.set('key', '$', ''); - assert.deepEqual( - await client.json.strAppend('key', '$', 'append'), - [6] - ); - }, GLOBAL.SERVERS.OPEN); -}); +// 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 index eea384c93fd..9f3ef316fd0 100644 --- a/packages/json/lib/commands/STRAPPEND.ts +++ b/packages/json/lib/commands/STRAPPEND.ts @@ -1,21 +1,21 @@ -import { transformRedisJsonArgument } from '.'; +// import { transformRedisJsonArgument } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -type AppendArguments = [key: string, append: string]; +// type AppendArguments = [key: string, append: string]; -type AppendWithPathArguments = [key: string, path: 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]; +// 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)); - } +// if (append !== undefined && append !== null) { +// args.push(pathOrAppend, transformRedisJsonArgument(append)); +// } else { +// args.push(transformRedisJsonArgument(pathOrAppend)); +// } - return args; -} +// return args; +// } -export declare function transformReply(): number | Array; +// export declare function transformReply(): number | Array; diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts index cf163d3c19e..97a14542fb1 100644 --- a/packages/json/lib/commands/STRLEN.spec.ts +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './STRLEN'; +import STRLEN from './STRLEN'; describe('STRLEN', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.STRLEN', 'key'] - ); - }); + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + STRLEN.transformArguments('key'), + ['JSON.STRLEN', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.STRLEN', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + STRLEN.transformArguments('key', '$'), + ['JSON.STRLEN', 'key', '$'] + ); }); + }); - testUtils.testWithClient('client.json.strLen', async client => { - await client.json.set('key', '$', ''); + testUtils.testWithClient('client.json.strLen', async client => { + await client.json.set('key', '$', ''); - assert.deepEqual( - await client.json.strLen('key', '$'), - [0] - ); - }, GLOBAL.SERVERS.OPEN); + 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 index 93f5d563baf..a2bab3b1f49 100644 --- a/packages/json/lib/commands/STRLEN.ts +++ b/packages/json/lib/commands/STRLEN.ts @@ -1,15 +1,16 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export const IS_READ_ONLY = true; - -export function transformArguments(key: string, path?: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.STRLEN', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): number; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts new file mode 100644 index 00000000000..0be05e0ccd6 --- /dev/null +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import TOGGLE from './TOGGLE'; + +describe('TOGGLE', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + TOGGLE.transformArguments('key'), + ['JSON.TOGGLE', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + TOGGLE.transformArguments('key', '$'), + ['JSON.TOGGLE', 'key', '$'] + ); + }); + }); + + testUtils.testWithClient('client.json.toggle', async client => { + await client.json.set('key', '$', ''); + + assert.deepEqual( + await client.json.toggle('key', '$'), + [0] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/TOGGLE.ts b/packages/json/lib/commands/TOGGLE.ts new file mode 100644 index 00000000000..45b632952a6 --- /dev/null +++ b/packages/json/lib/commands/TOGGLE.ts @@ -0,0 +1,14 @@ +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command, } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { + const args = ['JSON.TOGGLE', key] + + if (path) args.push(path); + + return args; + }, + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply +} as const satisfies Command; From e176a387b1439a884f1d28e5ab7f5a50500af7c9 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 10 Jul 2023 16:49:17 -0400 Subject: [PATCH 186/325] fix prev commit --- packages/json/lib/commands/ARRAPPEND.ts | 4 ++-- packages/json/lib/commands/ARRINDEX.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/json/lib/commands/ARRAPPEND.ts b/packages/json/lib/commands/ARRAPPEND.ts index ce809876479..934a534cfcd 100644 --- a/packages/json/lib/commands/ARRAPPEND.ts +++ b/packages/json/lib/commands/ARRAPPEND.ts @@ -1,5 +1,5 @@ import { RedisJSON, transformRedisJsonArgument } from '.'; -import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/ARRINDEX.ts b/packages/json/lib/commands/ARRINDEX.ts index 8c8c9e5df2a..f085e1afb93 100644 --- a/packages/json/lib/commands/ARRINDEX.ts +++ b/packages/json/lib/commands/ARRINDEX.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; export default { @@ -23,5 +23,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply } as const satisfies Command; From 513668e545d21fb8eaca83222771d037ee6ff678 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 10 Jul 2023 17:40:37 -0400 Subject: [PATCH 187/325] more commands --- packages/json/lib/commands/NUMINCRBY.spec.ts | 30 +++++------ packages/json/lib/commands/NUMINCRBY.ts | 13 +++-- packages/json/lib/commands/NUMMULTBY.spec.ts | 30 +++++------ packages/json/lib/commands/NUMMULTBY.ts | 13 +++-- packages/json/lib/commands/OBJKEYS.spec.ts | 42 +++++++-------- packages/json/lib/commands/OBJKEYS.ts | 17 +++--- packages/json/lib/commands/SET.spec.ts | 54 ++++++++++---------- packages/json/lib/commands/SET.ts | 26 +++++----- 8 files changed, 119 insertions(+), 106 deletions(-) diff --git a/packages/json/lib/commands/NUMINCRBY.spec.ts b/packages/json/lib/commands/NUMINCRBY.spec.ts index 56dede68bde..ee3675643dc 100644 --- a/packages/json/lib/commands/NUMINCRBY.spec.ts +++ b/packages/json/lib/commands/NUMINCRBY.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './NUMINCRBY'; +import NUMINCRBY from './NUMINCRBY'; -describe('NUMINCRBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '$', 1), - ['JSON.NUMINCRBY', 'key', '$', '1'] - ); - }); +describe('JSON.NUMINCRBY', () => { + it('transformArguments', () => { + assert.deepEqual( + NUMINCRBY.transformArguments('key', '$', 1), + ['JSON.NUMINCRBY', 'key', '$', '1'] + ); + }); - testUtils.testWithClient('client.json.numIncrBy', async client => { - await client.json.set('key', '$', 0); + 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); + 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 index e3d8887ea3d..d025c249dd0 100644 --- a/packages/json/lib/commands/NUMINCRBY.ts +++ b/packages/json/lib/commands/NUMINCRBY.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command, ArrayReply, NumberReply, DoubleReply, NullReply } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path: string, by: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, by: number) { return ['JSON.NUMINCRBY', key, path, by.toString()]; -} - -export { transformNumbersReply as transformReply } from '.'; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/NUMMULTBY.spec.ts b/packages/json/lib/commands/NUMMULTBY.spec.ts index 3e2581a3cd8..471c276f0ba 100644 --- a/packages/json/lib/commands/NUMMULTBY.spec.ts +++ b/packages/json/lib/commands/NUMMULTBY.spec.ts @@ -1,21 +1,21 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './NUMMULTBY'; +import NUMMULTBY from './NUMMULTBY'; -describe('NUMMULTBY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '$', 2), - ['JSON.NUMMULTBY', 'key', '$', '2'] - ); - }); +describe('JSON.NUMMULTBY', () => { + it('transformArguments', () => { + assert.deepEqual( + NUMMULTBY.transformArguments('key', '$', 2), + ['JSON.NUMMULTBY', 'key', '$', '2'] + ); + }); - testUtils.testWithClient('client.json.numMultBy', async client => { - await client.json.set('key', '$', 1); + 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); + 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 index 2082916619a..11a56d0d729 100644 --- a/packages/json/lib/commands/NUMMULTBY.ts +++ b/packages/json/lib/commands/NUMMULTBY.ts @@ -1,7 +1,10 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command, ArrayReply, NumberReply, DoubleReply, NullReply } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path: string, by: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, by: number) { return ['JSON.NUMMULTBY', key, path, by.toString()]; -} - -export { transformNumbersReply as transformReply } from '.'; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/OBJKEYS.spec.ts b/packages/json/lib/commands/OBJKEYS.spec.ts index 6288c112392..17417098eca 100644 --- a/packages/json/lib/commands/OBJKEYS.spec.ts +++ b/packages/json/lib/commands/OBJKEYS.spec.ts @@ -1,28 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './OBJKEYS'; +import OBJKEYS from './OBJKEYS'; -describe('OBJKEYS', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.OBJKEYS', 'key'] - ); - }); +describe('JSON.OBJKEYS', () => { + describe('transformArguments', () => { + it('without path', () => { + assert.deepEqual( + OBJKEYS.transformArguments('key'), + ['JSON.OBJKEYS', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.OBJKEYS', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + OBJKEYS.transformArguments('key', '$'), + ['JSON.OBJKEYS', 'key', '$'] + ); }); + }); - // testUtils.testWithClient('client.json.objKeys', async client => { - // assert.deepEqual( - // await client.json.objKeys('key', '$'), - // [null] - // ); - // }, GLOBAL.SERVERS.OPEN); + 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 index a9465c9160c..e9541bdb524 100644 --- a/packages/json/lib/commands/OBJKEYS.ts +++ b/packages/json/lib/commands/OBJKEYS.ts @@ -1,13 +1,18 @@ -export const FIRST_KEY_INDEX = 1; +import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +type ReplyItem = ArrayReply | NullReply; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.OBJKEYS', key]; if (path) { - args.push(path); + args.push(path); } return args; -} - -export declare function transformReply(): Array | null | Array | null>; + }, + transformReply: undefined as unknown as () => ReplyItem | ArrayReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/SET.spec.ts b/packages/json/lib/commands/SET.spec.ts index 8f8586a2047..d65b562be27 100644 --- a/packages/json/lib/commands/SET.spec.ts +++ b/packages/json/lib/commands/SET.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SET'; +import SET from './SET'; -describe('SET', () => { - describe('transformArguments', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '$', 'json'), - ['JSON.SET', 'key', '$', '"json"'] - ); - }); +describe('JSON.SET', () => { + describe('transformArguments', () => { + it('transformArguments', () => { + assert.deepEqual( + SET.transformArguments('key', '$', 'json'), + ['JSON.SET', 'key', '$', '"json"'] + ); + }); - it('NX', () => { - assert.deepEqual( - transformArguments('key', '$', 'json', { NX: true }), - ['JSON.SET', 'key', '$', '"json"', 'NX'] - ); - }); + it('NX', () => { + assert.deepEqual( + SET.transformArguments('key', '$', 'json', { NX: true }), + ['JSON.SET', 'key', '$', '"json"', 'NX'] + ); + }); - it('XX', () => { - assert.deepEqual( - transformArguments('key', '$', 'json', { XX: true }), - ['JSON.SET', 'key', '$', '"json"', 'XX'] - ); - }); + it('XX', () => { + assert.deepEqual( + SET.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); + testUtils.testWithClient('client.json.set', 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 index f50a42bf5db..9edebaa4308 100644 --- a/packages/json/lib/commands/SET.ts +++ b/packages/json/lib/commands/SET.ts @@ -1,25 +1,27 @@ +import { RedisArgument, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; -export const FIRST_KEY_INDEX = 1; - -interface NX { - NX: true; +export interface NX { + NX: true; } -interface XX { - XX: true; +export interface XX { + XX: true; } -export function transformArguments(key: string, path: string, json: RedisJSON, options?: NX | XX): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, json: RedisJSON, options?: NX | XX) { const args = ['JSON.SET', key, path, transformRedisJsonArgument(json)]; if ((options)?.NX) { - args.push('NX'); + args.push('NX'); } else if ((options)?.XX) { - args.push('XX'); + args.push('XX'); } return args; -} - -export declare function transformReply(): 'OK' | null; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> | NullReply +} as const satisfies Command; From ad8d0a0fe155ba8629dfe3aed9e25f4fe5da1763 Mon Sep 17 00:00:00 2001 From: dovi Date: Mon, 10 Jul 2023 17:41:02 -0400 Subject: [PATCH 188/325] fix test file --- packages/json/lib/commands/ARRINSERT.spec.ts | 2 +- packages/json/lib/commands/ARRLEN.spec.ts | 2 +- packages/json/lib/commands/ARRTRIM.spec.ts | 2 +- packages/json/lib/commands/CLEAR.spec.ts | 2 +- packages/json/lib/commands/OBJLEN.spec.ts | 2 +- packages/json/lib/commands/STRLEN.spec.ts | 2 +- packages/json/lib/commands/TOGGLE.spec.ts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts index 6adb3cd7676..8bf3d0d633e 100644 --- a/packages/json/lib/commands/ARRINSERT.spec.ts +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRINSERT from './ARRINSERT'; -describe('ARRINSERT', () => { +describe('JSON.ARRINSERT', () => { describe('transformArguments', () => { it('single JSON', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts index d14531f0382..803b108ddea 100644 --- a/packages/json/lib/commands/ARRLEN.spec.ts +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRLEN from './ARRLEN'; -describe('ARRLEN', () => { +describe('JSON.ARRLEN', () => { describe('transformArguments', () => { it('without path', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/ARRTRIM.spec.ts b/packages/json/lib/commands/ARRTRIM.spec.ts index 0d44c88ccdb..241c1b509b8 100644 --- a/packages/json/lib/commands/ARRTRIM.spec.ts +++ b/packages/json/lib/commands/ARRTRIM.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRTRIM from './ARRTRIM'; -describe('ARRTRIM', () => { +describe('JSON.ARRTRIM', () => { it('transformArguments', () => { assert.deepEqual( ARRTRIM.transformArguments('key', '$', 0, 1), diff --git a/packages/json/lib/commands/CLEAR.spec.ts b/packages/json/lib/commands/CLEAR.spec.ts index ce8b2898891..5b53b77c3c3 100644 --- a/packages/json/lib/commands/CLEAR.spec.ts +++ b/packages/json/lib/commands/CLEAR.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLEAR from './CLEAR'; -describe('CLEAR', () => { +describe('JSON.CLEAR', () => { describe('transformArguments', () => { it('key', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts index 316a3ebf0e1..b2eed67c525 100644 --- a/packages/json/lib/commands/OBJLEN.spec.ts +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJLEN from './OBJLEN'; -describe('OBJLEN', () => { +describe('JSON.OBJLEN', () => { describe('transformArguments', () => { it('without path', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts index 97a14542fb1..f05a45cf953 100644 --- a/packages/json/lib/commands/STRLEN.spec.ts +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import STRLEN from './STRLEN'; -describe('STRLEN', () => { +describe('JSON.STRLEN', () => { describe('transformArguments', () => { it('without path', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts index 0be05e0ccd6..7ffb5094894 100644 --- a/packages/json/lib/commands/TOGGLE.spec.ts +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import TOGGLE from './TOGGLE'; -describe('TOGGLE', () => { +describe('JSON.TOGGLE', () => { describe('transformArguments', () => { it('without path', () => { assert.deepEqual( From 54c3a66c72abae26aae4e46b491b8100cd568582 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 11 Jul 2023 13:11:13 -0400 Subject: [PATCH 189/325] time-series --- packages/time-series/lib/commands/ADD.spec.ts | 10 +- .../time-series/lib/commands/ALTER.spec.ts | 16 +- packages/time-series/lib/commands/ALTER.ts | 10 +- .../time-series/lib/commands/CREATE.spec.ts | 12 +- packages/time-series/lib/commands/CREATE.ts | 6 +- .../lib/commands/CREATERULE.spec.ts | 19 +- .../time-series/lib/commands/CREATERULE.ts | 21 +- .../time-series/lib/commands/DECRBY.spec.ts | 8 +- packages/time-series/lib/commands/DECRBY.ts | 14 +- packages/time-series/lib/commands/DEL.spec.ts | 12 +- .../lib/commands/DELETERULE.spec.ts | 14 +- packages/time-series/lib/commands/GET.spec.ts | 30 +- packages/time-series/lib/commands/GET.ts | 9 +- .../time-series/lib/commands/INCRBY.spec.ts | 8 +- packages/time-series/lib/commands/INCRBY.ts | 43 +- .../time-series/lib/commands/INFO.spec.ts | 2 +- .../lib/commands/INFO_DEBUG.spec.ts | 2 +- .../time-series/lib/commands/MADD.spec.ts | 26 +- packages/time-series/lib/commands/MADD.ts | 4 +- .../time-series/lib/commands/MGET.spec.ts | 2 +- .../lib/commands/MGET_WITHLABELS.spec.ts | 2 +- .../time-series/lib/commands/MRANGE.spec.ts | 2 +- .../lib/commands/MRANGE_WITHLABELS.spec.ts | 2 +- .../lib/commands/MREVRANGE.spec.ts | 2 +- .../lib/commands/MREVRANGE_WITHLABELS.spec.ts | 2 +- .../lib/commands/QUERYINDEX.spec.ts | 2 +- .../time-series/lib/commands/RANGE.spec.ts | 2 +- .../time-series/lib/commands/REVRANGE.spec.ts | 2 +- .../time-series/lib/commands/index.spec.ts | 878 +++++++++--------- packages/time-series/lib/commands/index.ts | 804 +++++++--------- packages/time-series/lib/index.ts | 10 +- packages/time-series/lib/test-utils.ts | 20 +- 32 files changed, 971 insertions(+), 1025 deletions(-) diff --git a/packages/time-series/lib/commands/ADD.spec.ts b/packages/time-series/lib/commands/ADD.spec.ts index 898f42ee772..0c0e588aa7c 100644 --- a/packages/time-series/lib/commands/ADD.spec.ts +++ b/packages/time-series/lib/commands/ADD.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ADD from './ADD'; -import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.'; +import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.'; describe('TS.ADD', () => { describe('transformArguments', () => { @@ -24,7 +24,7 @@ describe('TS.ADD', () => { it('with ENCODING', () => { assert.deepEqual( ADD.transformArguments('key', '*', 1, { - ENCODING: TimeSeriesEncoding.UNCOMPRESSED + ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED }), ['TS.ADD', 'key', '*', '1', 'ENCODING', 'UNCOMPRESSED'] ); @@ -42,7 +42,7 @@ describe('TS.ADD', () => { it('with ON_DUPLICATE', () => { assert.deepEqual( ADD.transformArguments('key', '*', 1, { - ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK + ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK }), ['TS.ADD', 'key', '*', '1', 'ON_DUPLICATE', 'BLOCK'] ); @@ -61,9 +61,9 @@ describe('TS.ADD', () => { assert.deepEqual( ADD.transformArguments('key', '*', 1, { RETENTION: 1, - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, + ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED, CHUNK_SIZE: 1, - ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK, + ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, LABELS: { label: 'value' } }), ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value'] diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index 0a7d7cb2caa..6889cd2b2c4 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'assert'; -import { TimeSeriesDuplicatePolicies } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import ALTER from './ALTER'; +import { TIME_SERIES_DUPLICATE_POLICIES } from '.'; describe('TS.ALTER', () => { describe('transformArguments', () => { @@ -33,7 +33,7 @@ describe('TS.ALTER', () => { it('with DUPLICATE_POLICY', () => { assert.deepEqual( ALTER.transformArguments('key', { - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK + DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK }), ['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK'] ); @@ -53,7 +53,7 @@ describe('TS.ALTER', () => { ALTER.transformArguments('key', { RETENTION: 1, CHUNK_SIZE: 1, - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, + DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, LABELS: { label: 'value' } }), ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] @@ -62,11 +62,11 @@ describe('TS.ALTER', () => { }); testUtils.testWithClient('client.ts.alter', async client => { - await client.ts.create('key'); + const [, reply] = await Promise.all([ + client.ts.create('key'), + client.ts.alter('key', { RETENTION: 1 }) + ]); - assert.equal( - await client.ts.alter('key', { RETENTION: 1 }), - 'OK' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/ALTER.ts b/packages/time-series/lib/commands/ALTER.ts index bf4e4d528c3..ae30799b2eb 100644 --- a/packages/time-series/lib/commands/ALTER.ts +++ b/packages/time-series/lib/commands/ALTER.ts @@ -1,12 +1,8 @@ -import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy } from '.'; import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { TsCreateOptions } from './CREATE'; +import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument } from '.'; -export interface TsAlterOptions { - RETENTION?: number; - CHUNK_SIZE?: number; - DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; - LABELS?: Labels; -} +export type TsAlterOptions = Pick; export default { FIRST_KEY_INDEX: 1, diff --git a/packages/time-series/lib/commands/CREATE.spec.ts b/packages/time-series/lib/commands/CREATE.spec.ts index 33717b607c8..d77c4117ebb 100644 --- a/packages/time-series/lib/commands/CREATE.spec.ts +++ b/packages/time-series/lib/commands/CREATE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import CREATE from './CREATE'; +import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.'; -describe('CREATE', () => { +describe('TS.CREATE', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -24,7 +24,7 @@ describe('CREATE', () => { it('with ENCODING', () => { assert.deepEqual( CREATE.transformArguments('key', { - ENCODING: TimeSeriesEncoding.UNCOMPRESSED + ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED }), ['TS.CREATE', 'key', 'ENCODING', 'UNCOMPRESSED'] ); @@ -42,7 +42,7 @@ describe('CREATE', () => { it('with DUPLICATE_POLICY', () => { assert.deepEqual( CREATE.transformArguments('key', { - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK + DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK }), ['TS.CREATE', 'key', 'DUPLICATE_POLICY', 'BLOCK'] ); @@ -61,9 +61,9 @@ describe('CREATE', () => { assert.deepEqual( CREATE.transformArguments('key', { RETENTION: 1, - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, + ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED, CHUNK_SIZE: 1, - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, + DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, LABELS: { label: 'value' } }), ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] diff --git a/packages/time-series/lib/commands/CREATE.ts b/packages/time-series/lib/commands/CREATE.ts index da28112d284..b028a470277 100644 --- a/packages/time-series/lib/commands/CREATE.ts +++ b/packages/time-series/lib/commands/CREATE.ts @@ -1,14 +1,14 @@ +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { pushRetentionArgument, TimeSeriesEncoding, pushEncodingArgument, pushChunkSizeArgument, TimeSeriesDuplicatePolicies, + pushDuplicatePolicy, Labels, - pushLabelsArgument, - pushDuplicatePolicy + pushLabelsArgument } from '.'; -import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; export interface TsCreateOptions { RETENTION?: number; diff --git a/packages/time-series/lib/commands/CREATERULE.spec.ts b/packages/time-series/lib/commands/CREATERULE.spec.ts index bd336b78df5..c06d27671a9 100644 --- a/packages/time-series/lib/commands/CREATERULE.spec.ts +++ b/packages/time-series/lib/commands/CREATERULE.spec.ts @@ -1,34 +1,31 @@ import { strict as assert } from 'assert'; -import { TimeSeriesAggregationType } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import CREATERULE from './CREATERULE'; +import CREATERULE, { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; -describe('CREATERULE', () => { +describe('TS.CREATERULE', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( - CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), + CREATERULE.transformArguments('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1), ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1'] ); }); it('with alignTimestamp', () => { assert.deepEqual( - CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1, 1), + CREATERULE.transformArguments('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1, 1), ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1'] ); }); }); testUtils.testWithClient('client.ts.createRule', async client => { - await Promise.all([ + const [, , reply] = await Promise.all([ client.ts.create('source'), - client.ts.create('destination') + client.ts.create('destination'), + client.ts.createRule('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1) ]); - assert.equal( - await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), - 'OK' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/CREATERULE.ts b/packages/time-series/lib/commands/CREATERULE.ts index 8c4536f0393..bd074d7107c 100644 --- a/packages/time-series/lib/commands/CREATERULE.ts +++ b/packages/time-series/lib/commands/CREATERULE.ts @@ -1,6 +1,23 @@ -import { TimeSeriesAggregationType } from '.'; import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +export const TIME_SERIES_AGGREGATION_TYPE = { + AVG: 'AVG', + FIRST: 'FIRST', + LAST: 'LAST', + MIN: 'MIN', + MAX: 'MAX', + SUM: 'SUM', + RANGE: 'RANGE', + COUNT: 'COUNT', + STD_P: 'STD.P', + STD_S: 'STD.S', + VAR_P: 'VAR.P', + VAR_S: 'VAR.S', + TWA: 'TWA' +} as const; + +export type TimeSeriesAggregationType = typeof TIME_SERIES_AGGREGATION_TYPE[keyof typeof TIME_SERIES_AGGREGATION_TYPE]; + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, @@ -20,7 +37,7 @@ export default { bucketDuration.toString() ]; - if (alignTimestamp) { + if (alignTimestamp !== undefined) { args.push(alignTimestamp.toString()); } diff --git a/packages/time-series/lib/commands/DECRBY.spec.ts b/packages/time-series/lib/commands/DECRBY.spec.ts index 8efa09ce42a..0f7679b794c 100644 --- a/packages/time-series/lib/commands/DECRBY.spec.ts +++ b/packages/time-series/lib/commands/DECRBY.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DECRBY from './DECRBY'; -describe('DECRBY', () => { +describe('TS.DECRBY', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -72,10 +72,8 @@ describe('DECRBY', () => { testUtils.testWithClient('client.ts.decrBy', async client => { assert.equal( - await client.ts.decrBy('key', 1, { - TIMESTAMP: 0 - }), - 0 + typeof await client.ts.decrBy('key', 1), + 'number' ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/DECRBY.ts b/packages/time-series/lib/commands/DECRBY.ts index 181568d1a85..a5ee01efb06 100644 --- a/packages/time-series/lib/commands/DECRBY.ts +++ b/packages/time-series/lib/commands/DECRBY.ts @@ -1,11 +1,9 @@ -import { IncrDecrOptions, transformIncrDecrArguments } from '.'; -import { RedisArgument, Command, NumberReply } from '@redis/client/dist/lib/RESP/types'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import INCRBY, { transformIncrByArguments } from './INCRBY'; export default { - FIRST_KEY_INDEX: 1, - IS_READ_ONLY: false, - transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { - return transformIncrDecrArguments('TS.DECRBY', key, value, options); - }, - transformReply: undefined as unknown as () => NumberReply + FIRST_KEY_INDEX: INCRBY.FIRST_KEY_INDEX, + IS_READ_ONLY: INCRBY.IS_READ_ONLY, + transformArguments: transformIncrByArguments.bind(undefined, 'TS.DECRBY'), + transformReply: INCRBY.transformReply } as const satisfies Command; diff --git a/packages/time-series/lib/commands/DEL.spec.ts b/packages/time-series/lib/commands/DEL.spec.ts index a0fdabedd65..d6f90d2e2ac 100644 --- a/packages/time-series/lib/commands/DEL.spec.ts +++ b/packages/time-series/lib/commands/DEL.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEL from './DEL'; -describe('DEL', () => { +describe('TS.DEL', () => { it('transformArguments', () => { assert.deepEqual( DEL.transformArguments('key', '-', '+'), @@ -11,11 +11,11 @@ describe('DEL', () => { }); testUtils.testWithClient('client.ts.del', async client => { - await client.ts.create('key'); + const [, reply] = await Promise.all([ + client.ts.create('key'), + client.ts.del('key', '-', '+') + ]); - assert.equal( - await client.ts.del('key', '-', '+'), - 0 - ); + assert.equal(reply, 0); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/DELETERULE.spec.ts b/packages/time-series/lib/commands/DELETERULE.spec.ts index c131dbcef17..1ee0de3993b 100644 --- a/packages/time-series/lib/commands/DELETERULE.spec.ts +++ b/packages/time-series/lib/commands/DELETERULE.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; -import { TimeSeriesAggregationType } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import DELETERULE from './DELETERULE'; +import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; -describe('DELETERULE', () => { +describe('TS.DELETERULE', () => { it('transformArguments', () => { assert.deepEqual( DELETERULE.transformArguments('source', 'destination'), @@ -12,15 +12,13 @@ describe('DELETERULE', () => { }); testUtils.testWithClient('client.ts.deleteRule', async client => { - await Promise.all([ + const [, , , reply] = await Promise.all([ client.ts.create('source'), client.ts.create('destination'), - client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1) + client.ts.createRule('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1), + client.ts.deleteRule('source', 'destination') ]); - assert.equal( - await client.ts.deleteRule('source', 'destination'), - 'OK' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/GET.spec.ts b/packages/time-series/lib/commands/GET.spec.ts index 3af57f75102..4c0925e014c 100644 --- a/packages/time-series/lib/commands/GET.spec.ts +++ b/packages/time-series/lib/commands/GET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import GET from './GET'; -describe('GET', () => { +describe('TS.GET', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -23,24 +23,24 @@ describe('GET', () => { describe('client.ts.get', () => { testUtils.testWithClient('null', async client => { - await client.ts.create('key'); + const [, reply] = await Promise.all([ + client.ts.create('key'), + client.ts.get('key') + ]); - assert.equal( - await client.ts.get('key'), - null - ); + assert.equal(reply, null); }, GLOBAL.SERVERS.OPEN); - testUtils.testWithClient('with samples', async client => { - await client.ts.add('key', 0, 1); + testUtils.testWithClient('with sample', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 1), + client.ts.get('key') + ]); - assert.deepEqual( - await client.ts.get('key'), - { - timestamp: 0, - value: 1 - } - ); + assert.deepEqual(reply, { + timestamp: 0, + value: 1 + }); }, GLOBAL.SERVERS.OPEN); }); }); diff --git a/packages/time-series/lib/commands/GET.ts b/packages/time-series/lib/commands/GET.ts index e2de752a0df..514b51edd2c 100644 --- a/packages/time-series/lib/commands/GET.ts +++ b/packages/time-series/lib/commands/GET.ts @@ -1,5 +1,4 @@ import { RedisArgument, TuplesReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; -import { pushLatestArgument } from '.'; export interface TsGetOptions { LATEST?: boolean; @@ -11,7 +10,13 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, options?: TsGetOptions) { - return pushLatestArgument(['TS.GET', key], options?.LATEST); + const args = ['TS.GET', key]; + + if (options?.LATEST) { + args.push('LATEST'); + } + + return args; }, transformReply: { 2(reply: Resp2Reply) { diff --git a/packages/time-series/lib/commands/INCRBY.spec.ts b/packages/time-series/lib/commands/INCRBY.spec.ts index 0745a1d26fa..8cd57ee4a2a 100644 --- a/packages/time-series/lib/commands/INCRBY.spec.ts +++ b/packages/time-series/lib/commands/INCRBY.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import INCRBY from './INCRBY'; -describe('INCRBY', () => { +describe('TS.INCRBY', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -82,10 +82,8 @@ describe('INCRBY', () => { testUtils.testWithClient('client.ts.incrBy', async client => { assert.equal( - await client.ts.incrBy('key', 1, { - TIMESTAMP: 0 - }), - 0 + typeof await client.ts.incrBy('key', 1), + 'number' ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/INCRBY.ts b/packages/time-series/lib/commands/INCRBY.ts index 413c33643ac..ece5defee6a 100644 --- a/packages/time-series/lib/commands/INCRBY.ts +++ b/packages/time-series/lib/commands/INCRBY.ts @@ -1,11 +1,46 @@ -import { IncrDecrOptions, transformIncrDecrArguments } from '.'; import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { Timestamp, transformTimestampArgument, pushRetentionArgument, pushChunkSizeArgument, Labels, pushLabelsArgument } from '.'; + +export interface TsIncrByOptions { + TIMESTAMP?: Timestamp; + RETENTION?: number; + UNCOMPRESSED?: boolean; + CHUNK_SIZE?: number; + LABELS?: Labels; +} + +export function transformIncrByArguments( + command: RedisArgument, + key: RedisArgument, + value: number, + options?: TsIncrByOptions +) { + const args = [ + command, + key, + value.toString() + ]; + + if (options?.TIMESTAMP !== undefined && options?.TIMESTAMP !== null) { + args.push('TIMESTAMP', transformTimestampArgument(options.TIMESTAMP)); + } + + pushRetentionArgument(args, options?.RETENTION); + + if (options?.UNCOMPRESSED) { + args.push('UNCOMPRESSED'); + } + + pushChunkSizeArgument(args, options?.CHUNK_SIZE); + + pushLabelsArgument(args, options?.LABELS); + + return args; +} export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { - return transformIncrDecrArguments('TS.INCRBY', key, value, options); - }, + transformArguments: transformIncrByArguments.bind(undefined, 'TS.INCRBY'), transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/time-series/lib/commands/INFO.spec.ts b/packages/time-series/lib/commands/INFO.spec.ts index c02cdd6da4d..a03049f03b6 100644 --- a/packages/time-series/lib/commands/INFO.spec.ts +++ b/packages/time-series/lib/commands/INFO.spec.ts @@ -3,7 +3,7 @@ import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { InfoReply, transformArguments } from './INFO'; -describe('INFO', () => { +describe('TS.INFO', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('key'), diff --git a/packages/time-series/lib/commands/INFO_DEBUG.spec.ts b/packages/time-series/lib/commands/INFO_DEBUG.spec.ts index 666689f5194..caff0e177f6 100644 --- a/packages/time-series/lib/commands/INFO_DEBUG.spec.ts +++ b/packages/time-series/lib/commands/INFO_DEBUG.spec.ts @@ -4,7 +4,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { assertInfo } from './INFO.spec'; import { transformArguments } from './INFO_DEBUG'; -describe('INFO_DEBUG', () => { +describe('TS.INFO_DEBUG', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('key'), diff --git a/packages/time-series/lib/commands/MADD.spec.ts b/packages/time-series/lib/commands/MADD.spec.ts index d5446763310..119fcfce60e 100644 --- a/packages/time-series/lib/commands/MADD.spec.ts +++ b/packages/time-series/lib/commands/MADD.spec.ts @@ -1,8 +1,9 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import MADD from './MADD'; +import { SimpleError } from '@redis/client/lib/errors'; -describe('MADD', () => { +describe.only('TS.MADD', () => { it('transformArguments', () => { assert.deepEqual( MADD.transformArguments([{ @@ -18,22 +19,23 @@ describe('MADD', () => { ); }); - // Should we check empty array? - testUtils.testWithClient('client.ts.mAdd', async client => { - await client.ts.create('key'); - - assert.deepEqual( - await client.ts.mAdd([{ + const [, reply] = await Promise.all([ + client.ts.create('key'), + client.ts.mAdd([{ key: 'key', timestamp: 0, - value: 0 + value: 1 }, { key: 'key', - timestamp: 1, + timestamp: 0, value: 1 - }]), - [0, 1] - ); + }]) + ]); + + assert.ok(Array.isArray(reply)); + assert.equal(reply.length, 2); + assert.equal(reply[0], 0); + assert.ok(reply[1] instanceof SimpleError); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MADD.ts b/packages/time-series/lib/commands/MADD.ts index fc4d22d13ae..59c1ed59bdb 100644 --- a/packages/time-series/lib/commands/MADD.ts +++ b/packages/time-series/lib/commands/MADD.ts @@ -1,5 +1,5 @@ import { Timestamp, transformTimestampArgument } from '.'; -import { ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { ArrayReply, NumberReply, SimpleErrorReply, Command } from '@redis/client/dist/lib/RESP/types'; export interface TsMAddSample { key: string; @@ -23,5 +23,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MGET.spec.ts b/packages/time-series/lib/commands/MGET.spec.ts index 61da3b96383..c932ff704ab 100644 --- a/packages/time-series/lib/commands/MGET.spec.ts +++ b/packages/time-series/lib/commands/MGET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MGET'; -describe('MGET', () => { +describe('TS.MGET', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( diff --git a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts index 55fcfde409d..67c3a4c7b35 100644 --- a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MGET_WITHLABELS'; -describe('MGET_WITHLABELS', () => { +describe('TS.MGET_WITHLABELS', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( diff --git a/packages/time-series/lib/commands/MRANGE.spec.ts b/packages/time-series/lib/commands/MRANGE.spec.ts index 4228cc06fb7..5f5a7930e50 100644 --- a/packages/time-series/lib/commands/MRANGE.spec.ts +++ b/packages/time-series/lib/commands/MRANGE.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; -describe('MRANGE', () => { +describe('TS.MRANGE', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('-', '+', 'label=value', { diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts index 983114f840e..729e32f19af 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MRANGE_WITHLABELS'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; -describe('MRANGE_WITHLABELS', () => { +describe('TS.MRANGE_WITHLABELS', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('-', '+', 'label=value', { diff --git a/packages/time-series/lib/commands/MREVRANGE.spec.ts b/packages/time-series/lib/commands/MREVRANGE.spec.ts index 6e5825d36d6..e5dcf5f5f77 100644 --- a/packages/time-series/lib/commands/MREVRANGE.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MREVRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; -describe('MREVRANGE', () => { +describe('TS.MREVRANGE', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('-', '+', 'label=value', { diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts index 7e80e965d4e..a3e50b7f26c 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MREVRANGE_WITHLABELS'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; -describe('MREVRANGE_WITHLABELS', () => { +describe('TS.MREVRANGE_WITHLABELS', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('-', '+', 'label=value', { diff --git a/packages/time-series/lib/commands/QUERYINDEX.spec.ts b/packages/time-series/lib/commands/QUERYINDEX.spec.ts index 010c5c8f639..68e473918a5 100644 --- a/packages/time-series/lib/commands/QUERYINDEX.spec.ts +++ b/packages/time-series/lib/commands/QUERYINDEX.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './QUERYINDEX'; -describe('QUERYINDEX', () => { +describe('TS.QUERYINDEX', () => { describe('transformArguments', () => { it('single filter', () => { assert.deepEqual( diff --git a/packages/time-series/lib/commands/RANGE.spec.ts b/packages/time-series/lib/commands/RANGE.spec.ts index 1e6a9958806..bc3c5498031 100644 --- a/packages/time-series/lib/commands/RANGE.spec.ts +++ b/packages/time-series/lib/commands/RANGE.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RANGE'; import { TimeSeriesAggregationType } from '.'; -describe('RANGE', () => { +describe('TS.RANGE', () => { it('transformArguments', () => { assert.deepEqual( transformArguments('key', '-', '+', { diff --git a/packages/time-series/lib/commands/REVRANGE.spec.ts b/packages/time-series/lib/commands/REVRANGE.spec.ts index ffd90268c81..6fd0f6a45a4 100644 --- a/packages/time-series/lib/commands/REVRANGE.spec.ts +++ b/packages/time-series/lib/commands/REVRANGE.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './REVRANGE'; import { TimeSeriesAggregationType } from '.'; -describe('REVRANGE', () => { +describe('TS.REVRANGE', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( diff --git a/packages/time-series/lib/commands/index.spec.ts b/packages/time-series/lib/commands/index.spec.ts index a29eefe860a..ba71ce777ca 100644 --- a/packages/time-series/lib/commands/index.spec.ts +++ b/packages/time-series/lib/commands/index.spec.ts @@ -1,439 +1,439 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { strict as assert } from 'assert'; -import { - transformTimestampArgument, - pushRetentionArgument, - TimeSeriesEncoding, - pushEncodingArgument, - pushChunkSizeArgument, - pushDuplicatePolicy, - pushLabelsArgument, - transformIncrDecrArguments, - transformSampleReply, - TimeSeriesAggregationType, - pushRangeArguments, - pushMRangeGroupByArguments, - TimeSeriesReducers, - pushFilterArgument, - pushMRangeArguments, - pushWithLabelsArgument, - pushMRangeWithLabelsArguments, - transformRangeReply, - transformMRangeReply, - transformMRangeWithLabelsReply, - TimeSeriesDuplicatePolicies, - pushLatestArgument, - TimeSeriesBucketTimestamp -} from '.'; - -describe('transformTimestampArgument', () => { - it('number', () => { - assert.equal( - transformTimestampArgument(0), - '0' - ); - }); - - it('Date', () => { - assert.equal( - transformTimestampArgument(new Date(0)), - '0' - ); - }); - - it('string', () => { - assert.equal( - transformTimestampArgument('*'), - '*' - ); - }); -}); - -function testOptionalArgument(fn: (args: RedisCommandArguments) => unknown): void { - it('undefined', () => { - assert.deepEqual( - fn([]), - [] - ); - }); -} - -describe('pushRetentionArgument', () => { - testOptionalArgument(pushRetentionArgument); - - it('number', () => { - assert.deepEqual( - pushRetentionArgument([], 1), - ['RETENTION', '1'] - ); - }); -}); - -describe('pushEncodingArgument', () => { - testOptionalArgument(pushEncodingArgument); - - it('UNCOMPRESSED', () => { - assert.deepEqual( - pushEncodingArgument([], TimeSeriesEncoding.UNCOMPRESSED), - ['ENCODING', 'UNCOMPRESSED'] - ); - }); -}); - -describe('pushChunkSizeArgument', () => { - testOptionalArgument(pushChunkSizeArgument); - - it('number', () => { - assert.deepEqual( - pushChunkSizeArgument([], 1), - ['CHUNK_SIZE', '1'] - ); - }); -}); - -describe('pushDuplicatePolicy', () => { - testOptionalArgument(pushDuplicatePolicy); - - it('BLOCK', () => { - assert.deepEqual( - pushDuplicatePolicy([], TimeSeriesDuplicatePolicies.BLOCK), - ['DUPLICATE_POLICY', 'BLOCK'] - ); - }); -}); - -describe('pushLabelsArgument', () => { - testOptionalArgument(pushLabelsArgument); - - it("{ label: 'value' }", () => { - assert.deepEqual( - pushLabelsArgument([], { label: 'value' }), - ['LABELS', 'label', 'value'] - ); - }); -}); - -describe('transformIncrDecrArguments', () => { - it('without options', () => { - assert.deepEqual( - transformIncrDecrArguments('TS.INCRBY', 'key', 1), - ['TS.INCRBY', 'key', '1'] - ); - }); - - it('with TIMESTAMP', () => { - assert.deepEqual( - transformIncrDecrArguments('TS.INCRBY', 'key', 1, { - TIMESTAMP: '*' - }), - ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*'] - ); - }); - - it('with UNCOMPRESSED', () => { - assert.deepEqual( - transformIncrDecrArguments('TS.INCRBY', 'key', 1, { - UNCOMPRESSED: true - }), - ['TS.INCRBY', 'key', '1', 'UNCOMPRESSED'] - ); - }); - - it('with UNCOMPRESSED false', () => { - assert.deepEqual( - transformIncrDecrArguments('TS.INCRBY', 'key', 1, { - UNCOMPRESSED: false - }), - ['TS.INCRBY', 'key', '1'] - ); - }); -}); - -it('transformSampleReply', () => { - assert.deepEqual( - transformSampleReply([1, '1.1']), - { - timestamp: 1, - value: 1.1 - } - ); -}); - -describe('pushRangeArguments', () => { - it('without options', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+'), - ['-', '+'] - ); - }); - - describe('with FILTER_BY_TS', () => { - it('string', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - FILTER_BY_TS: ['ts'] - }), - ['-', '+', 'FILTER_BY_TS', 'ts'] - ); - }); - - it('Array', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - FILTER_BY_TS: ['1', '2'] - }), - ['-', '+', 'FILTER_BY_TS', '1', '2'] - ); - }); - }); - - it('with FILTER_BY_VALUE', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - FILTER_BY_VALUE: { - min: 1, - max: 2 - } - }), - ['-', '+', 'FILTER_BY_VALUE', '1', '2'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - COUNT: 1 - }), - ['-', '+', 'COUNT', '1'] - ); - }); - - it('with ALIGN', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - ALIGN: 1 - }), - ['-', '+', 'ALIGN', '1'] - ); - }); - - describe('with AGGREGATION', () => { - it('without options', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - AGGREGATION: { - type: TimeSeriesAggregationType.FIRST, - timeBucket: 1 - } - }), - ['-', '+', 'AGGREGATION', 'FIRST', '1'] - ); - }); - - it('with BUCKETTIMESTAMP', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - AGGREGATION: { - type: TimeSeriesAggregationType.FIRST, - timeBucket: 1, - BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW - } - }), - ['-', '+', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-'] - ); - }); - - it('with BUCKETTIMESTAMP', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - AGGREGATION: { - type: TimeSeriesAggregationType.FIRST, - timeBucket: 1, - EMPTY: true - } - }), - ['-', '+', 'AGGREGATION', 'FIRST', '1', 'EMPTY'] - ); - }); - }); - - it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { - assert.deepEqual( - pushRangeArguments([], '-', '+', { - FILTER_BY_TS: ['ts'], - FILTER_BY_VALUE: { - min: 1, - max: 2 - }, - COUNT: 1, - ALIGN: 1, - AGGREGATION: { - type: TimeSeriesAggregationType.FIRST, - timeBucket: 1, - BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW, - EMPTY: true - } - }), - ['-', '+', 'FILTER_BY_TS', 'ts', 'FILTER_BY_VALUE', '1', '2', - 'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-', 'EMPTY'] - ); - }); -}); - -describe('pushMRangeGroupByArguments', () => { - it('undefined', () => { - assert.deepEqual( - pushMRangeGroupByArguments([]), - [] - ); - }); - - it('with GROUPBY', () => { - assert.deepEqual( - pushMRangeGroupByArguments([], { - label: 'label', - reducer: TimeSeriesReducers.MAXIMUM - }), - ['GROUPBY', 'label', 'REDUCE', 'MAX'] - ); - }); -}); - -describe('pushFilterArgument', () => { - it('string', () => { - assert.deepEqual( - pushFilterArgument([], 'label=value'), - ['FILTER', 'label=value'] - ); - }); - - it('Array', () => { - assert.deepEqual( - pushFilterArgument([], ['1=1', '2=2']), - ['FILTER', '1=1', '2=2'] - ); - }); -}); - -describe('pushMRangeArguments', () => { - it('without options', () => { - assert.deepEqual( - pushMRangeArguments([], '-', '+', 'label=value'), - ['-', '+', 'FILTER', 'label=value'] - ); - }); - - it('with GROUPBY', () => { - assert.deepEqual( - pushMRangeArguments([], '-', '+', 'label=value', { - GROUPBY: { - label: 'label', - reducer: TimeSeriesReducers.MAXIMUM - } - }), - ['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'MAX'] - ); - }); -}); - -describe('pushWithLabelsArgument', () => { - it('without selected labels', () => { - assert.deepEqual( - pushWithLabelsArgument([]), - ['WITHLABELS'] - ); - }); - - it('with selected labels', () => { - assert.deepEqual( - pushWithLabelsArgument([], ['label']), - ['SELECTED_LABELS', 'label'] - ); - }); -}); - -it('pushMRangeWithLabelsArguments', () => { - assert.deepEqual( - pushMRangeWithLabelsArguments([], '-', '+', 'label=value'), - ['-', '+', 'WITHLABELS', 'FILTER', 'label=value'] - ); -}); - -it('transformRangeReply', () => { - assert.deepEqual( - transformRangeReply([[1, '1.1'], [2, '2.2']]), - [{ - timestamp: 1, - value: 1.1 - }, { - timestamp: 2, - value: 2.2 - }] - ); -}); - -describe('transformMRangeReply', () => { - assert.deepEqual( - transformMRangeReply([[ - 'key', - [], - [[1, '1.1'], [2, '2.2']] - ]]), - [{ - key: 'key', - samples: [{ - timestamp: 1, - value: 1.1 - }, { - timestamp: 2, - value: 2.2 - }] - }] - ); -}); - -describe('transformMRangeWithLabelsReply', () => { - assert.deepEqual( - transformMRangeWithLabelsReply([[ - 'key', - [['label', 'value']], - [[1, '1.1'], [2, '2.2']] - ]]), - [{ - key: 'key', - labels: { - label: 'value' - }, - samples: [{ - timestamp: 1, - value: 1.1 - }, { - timestamp: 2, - value: 2.2 - }] - }] - ); -}); - -describe('pushLatestArgument', () => { - it('undefined', () => { - assert.deepEqual( - pushLatestArgument([]), - [] - ); - }); - - it('false', () => { - assert.deepEqual( - pushLatestArgument([], false), - [] - ); - }); - - it('true', () => { - assert.deepEqual( - pushLatestArgument([], true), - ['LATEST'] - ); - }); -}) +// import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +// import { strict as assert } from 'assert'; +// import { +// transformTimestampArgument, +// pushRetentionArgument, +// TimeSeriesEncoding, +// pushEncodingArgument, +// pushChunkSizeArgument, +// pushDuplicatePolicy, +// pushLabelsArgument, +// transformIncrDecrArguments, +// transformSampleReply, +// TimeSeriesAggregationType, +// pushRangeArguments, +// pushMRangeGroupByArguments, +// TimeSeriesReducers, +// pushFilterArgument, +// pushMRangeArguments, +// pushWithLabelsArgument, +// pushMRangeWithLabelsArguments, +// transformRangeReply, +// transformMRangeReply, +// transformMRangeWithLabelsReply, +// TimeSeriesDuplicatePolicies, +// pushLatestArgument, +// TimeSeriesBucketTimestamp +// } from '.'; + +// describe('transformTimestampArgument', () => { +// it('number', () => { +// assert.equal( +// transformTimestampArgument(0), +// '0' +// ); +// }); + +// it('Date', () => { +// assert.equal( +// transformTimestampArgument(new Date(0)), +// '0' +// ); +// }); + +// it('string', () => { +// assert.equal( +// transformTimestampArgument('*'), +// '*' +// ); +// }); +// }); + +// function testOptionalArgument(fn: (args: RedisCommandArguments) => unknown): void { +// it('undefined', () => { +// assert.deepEqual( +// fn([]), +// [] +// ); +// }); +// } + +// describe('pushRetentionArgument', () => { +// testOptionalArgument(pushRetentionArgument); + +// it('number', () => { +// assert.deepEqual( +// pushRetentionArgument([], 1), +// ['RETENTION', '1'] +// ); +// }); +// }); + +// describe('pushEncodingArgument', () => { +// testOptionalArgument(pushEncodingArgument); + +// it('UNCOMPRESSED', () => { +// assert.deepEqual( +// pushEncodingArgument([], TimeSeriesEncoding.UNCOMPRESSED), +// ['ENCODING', 'UNCOMPRESSED'] +// ); +// }); +// }); + +// describe('pushChunkSizeArgument', () => { +// testOptionalArgument(pushChunkSizeArgument); + +// it('number', () => { +// assert.deepEqual( +// pushChunkSizeArgument([], 1), +// ['CHUNK_SIZE', '1'] +// ); +// }); +// }); + +// describe('pushDuplicatePolicy', () => { +// testOptionalArgument(pushDuplicatePolicy); + +// it('BLOCK', () => { +// assert.deepEqual( +// pushDuplicatePolicy([], TimeSeriesDuplicatePolicies.BLOCK), +// ['DUPLICATE_POLICY', 'BLOCK'] +// ); +// }); +// }); + +// describe('pushLabelsArgument', () => { +// testOptionalArgument(pushLabelsArgument); + +// it("{ label: 'value' }", () => { +// assert.deepEqual( +// pushLabelsArgument([], { label: 'value' }), +// ['LABELS', 'label', 'value'] +// ); +// }); +// }); + +// describe('transformIncrDecrArguments', () => { +// it('without options', () => { +// assert.deepEqual( +// transformIncrDecrArguments('TS.INCRBY', 'key', 1), +// ['TS.INCRBY', 'key', '1'] +// ); +// }); + +// it('with TIMESTAMP', () => { +// assert.deepEqual( +// transformIncrDecrArguments('TS.INCRBY', 'key', 1, { +// TIMESTAMP: '*' +// }), +// ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*'] +// ); +// }); + +// it('with UNCOMPRESSED', () => { +// assert.deepEqual( +// transformIncrDecrArguments('TS.INCRBY', 'key', 1, { +// UNCOMPRESSED: true +// }), +// ['TS.INCRBY', 'key', '1', 'UNCOMPRESSED'] +// ); +// }); + +// it('with UNCOMPRESSED false', () => { +// assert.deepEqual( +// transformIncrDecrArguments('TS.INCRBY', 'key', 1, { +// UNCOMPRESSED: false +// }), +// ['TS.INCRBY', 'key', '1'] +// ); +// }); +// }); + +// it('transformSampleReply', () => { +// assert.deepEqual( +// transformSampleReply([1, '1.1']), +// { +// timestamp: 1, +// value: 1.1 +// } +// ); +// }); + +// describe('pushRangeArguments', () => { +// it('without options', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+'), +// ['-', '+'] +// ); +// }); + +// describe('with FILTER_BY_TS', () => { +// it('string', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// FILTER_BY_TS: ['ts'] +// }), +// ['-', '+', 'FILTER_BY_TS', 'ts'] +// ); +// }); + +// it('Array', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// FILTER_BY_TS: ['1', '2'] +// }), +// ['-', '+', 'FILTER_BY_TS', '1', '2'] +// ); +// }); +// }); + +// it('with FILTER_BY_VALUE', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// FILTER_BY_VALUE: { +// min: 1, +// max: 2 +// } +// }), +// ['-', '+', 'FILTER_BY_VALUE', '1', '2'] +// ); +// }); + +// it('with COUNT', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// COUNT: 1 +// }), +// ['-', '+', 'COUNT', '1'] +// ); +// }); + +// it('with ALIGN', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// ALIGN: 1 +// }), +// ['-', '+', 'ALIGN', '1'] +// ); +// }); + +// describe('with AGGREGATION', () => { +// it('without options', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// AGGREGATION: { +// type: TimeSeriesAggregationType.FIRST, +// timeBucket: 1 +// } +// }), +// ['-', '+', 'AGGREGATION', 'FIRST', '1'] +// ); +// }); + +// it('with BUCKETTIMESTAMP', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// AGGREGATION: { +// type: TimeSeriesAggregationType.FIRST, +// timeBucket: 1, +// BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW +// } +// }), +// ['-', '+', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-'] +// ); +// }); + +// it('with BUCKETTIMESTAMP', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// AGGREGATION: { +// type: TimeSeriesAggregationType.FIRST, +// timeBucket: 1, +// EMPTY: true +// } +// }), +// ['-', '+', 'AGGREGATION', 'FIRST', '1', 'EMPTY'] +// ); +// }); +// }); + +// it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { +// assert.deepEqual( +// pushRangeArguments([], '-', '+', { +// FILTER_BY_TS: ['ts'], +// FILTER_BY_VALUE: { +// min: 1, +// max: 2 +// }, +// COUNT: 1, +// ALIGN: 1, +// AGGREGATION: { +// type: TimeSeriesAggregationType.FIRST, +// timeBucket: 1, +// BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW, +// EMPTY: true +// } +// }), +// ['-', '+', 'FILTER_BY_TS', 'ts', 'FILTER_BY_VALUE', '1', '2', +// 'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-', 'EMPTY'] +// ); +// }); +// }); + +// describe('pushMRangeGroupByArguments', () => { +// it('undefined', () => { +// assert.deepEqual( +// pushMRangeGroupByArguments([]), +// [] +// ); +// }); + +// it('with GROUPBY', () => { +// assert.deepEqual( +// pushMRangeGroupByArguments([], { +// label: 'label', +// reducer: TimeSeriesReducers.MAXIMUM +// }), +// ['GROUPBY', 'label', 'REDUCE', 'MAX'] +// ); +// }); +// }); + +// describe('pushFilterArgument', () => { +// it('string', () => { +// assert.deepEqual( +// pushFilterArgument([], 'label=value'), +// ['FILTER', 'label=value'] +// ); +// }); + +// it('Array', () => { +// assert.deepEqual( +// pushFilterArgument([], ['1=1', '2=2']), +// ['FILTER', '1=1', '2=2'] +// ); +// }); +// }); + +// describe('pushMRangeArguments', () => { +// it('without options', () => { +// assert.deepEqual( +// pushMRangeArguments([], '-', '+', 'label=value'), +// ['-', '+', 'FILTER', 'label=value'] +// ); +// }); + +// it('with GROUPBY', () => { +// assert.deepEqual( +// pushMRangeArguments([], '-', '+', 'label=value', { +// GROUPBY: { +// label: 'label', +// reducer: TimeSeriesReducers.MAXIMUM +// } +// }), +// ['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'MAX'] +// ); +// }); +// }); + +// describe('pushWithLabelsArgument', () => { +// it('without selected labels', () => { +// assert.deepEqual( +// pushWithLabelsArgument([]), +// ['WITHLABELS'] +// ); +// }); + +// it('with selected labels', () => { +// assert.deepEqual( +// pushWithLabelsArgument([], ['label']), +// ['SELECTED_LABELS', 'label'] +// ); +// }); +// }); + +// it('pushMRangeWithLabelsArguments', () => { +// assert.deepEqual( +// pushMRangeWithLabelsArguments([], '-', '+', 'label=value'), +// ['-', '+', 'WITHLABELS', 'FILTER', 'label=value'] +// ); +// }); + +// it('transformRangeReply', () => { +// assert.deepEqual( +// transformRangeReply([[1, '1.1'], [2, '2.2']]), +// [{ +// timestamp: 1, +// value: 1.1 +// }, { +// timestamp: 2, +// value: 2.2 +// }] +// ); +// }); + +// describe('transformMRangeReply', () => { +// assert.deepEqual( +// transformMRangeReply([[ +// 'key', +// [], +// [[1, '1.1'], [2, '2.2']] +// ]]), +// [{ +// key: 'key', +// samples: [{ +// timestamp: 1, +// value: 1.1 +// }, { +// timestamp: 2, +// value: 2.2 +// }] +// }] +// ); +// }); + +// describe('transformMRangeWithLabelsReply', () => { +// assert.deepEqual( +// transformMRangeWithLabelsReply([[ +// 'key', +// [['label', 'value']], +// [[1, '1.1'], [2, '2.2']] +// ]]), +// [{ +// key: 'key', +// labels: { +// label: 'value' +// }, +// samples: [{ +// timestamp: 1, +// value: 1.1 +// }, { +// timestamp: 2, +// value: 2.2 +// }] +// }] +// ); +// }); + +// describe('pushLatestArgument', () => { +// it('undefined', () => { +// assert.deepEqual( +// pushLatestArgument([]), +// [] +// ); +// }); + +// it('false', () => { +// assert.deepEqual( +// pushLatestArgument([], false), +// [] +// ); +// }); + +// it('true', () => { +// assert.deepEqual( +// pushLatestArgument([], true), +// ['LATEST'] +// ); +// }); +// }) diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index 0b0b56d2630..2c8fb48ce64 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -1,467 +1,367 @@ -import * as ADD from './ADD'; -import * as ALTER from './ALTER'; -import * as CREATE from './CREATE'; -import * as CREATERULE from './CREATERULE'; -import * as DECRBY from './DECRBY'; -import * as DEL from './DEL'; -import * as DELETERULE from './DELETERULE'; -import * as GET from './GET'; -import * as INCRBY from './INCRBY'; -import * as INFO_DEBUG from './INFO_DEBUG'; -import * as INFO from './INFO'; -import * as MADD from './MADD'; -import * as MGET from './MGET'; -import * as MGET_WITHLABELS from './MGET_WITHLABELS'; -import * as QUERYINDEX from './QUERYINDEX'; -import * as RANGE from './RANGE'; -import * as REVRANGE from './REVRANGE'; -import * as MRANGE from './MRANGE'; -import * as MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; -import * as MREVRANGE from './MREVRANGE'; -import * as MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import type { RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types'; +import ADD from './ADD'; +import ALTER from './ALTER'; +import CREATE from './CREATE'; +import CREATERULE from './CREATERULE'; +import DECRBY from './DECRBY'; +import DEL from './DEL'; +import DELETERULE from './DELETERULE'; +import GET from './GET'; +import INCRBY from './INCRBY'; +// import INFO_DEBUG from './INFO_DEBUG'; +// import INFO from './INFO'; +import MADD from './MADD'; +// import MGET from './MGET'; +// import MGET_WITHLABELS from './MGET_WITHLABELS'; +// import QUERYINDEX from './QUERYINDEX'; +// import RANGE from './RANGE'; +// import REVRANGE from './REVRANGE'; +// import MRANGE from './MRANGE'; +// import MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; +// import MREVRANGE from './MREVRANGE'; +// import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; export default { - ADD, - add: ADD, - ALTER, - alter: ALTER, - CREATE, - create: CREATE, - CREATERULE, - createRule: CREATERULE, - DECRBY, - decrBy: DECRBY, - DEL, - del: DEL, - DELETERULE, - deleteRule: DELETERULE, - GET, - get: GET, - INCRBY, - incrBy: INCRBY, - INFO_DEBUG, - infoDebug: INFO_DEBUG, - INFO, - info: INFO, - MADD, - mAdd: MADD, - MGET, - mGet: MGET, - MGET_WITHLABELS, - mGetWithLabels: MGET_WITHLABELS, - QUERYINDEX, - queryIndex: QUERYINDEX, - RANGE, - range: RANGE, - REVRANGE, - revRange: REVRANGE, - MRANGE, - mRange: MRANGE, - MRANGE_WITHLABELS, - mRangeWithLabels: MRANGE_WITHLABELS, - MREVRANGE, - mRevRange: MREVRANGE, - MREVRANGE_WITHLABELS, - mRevRangeWithLabels: MREVRANGE_WITHLABELS -}; - -export enum TimeSeriesAggregationType { - AVG = 'AVG', - // @deprecated - AVERAGE = 'AVG', - FIRST = 'FIRST', - LAST = 'LAST', - MIN = 'MIN', - // @deprecated - MINIMUM = 'MIN', - MAX = 'MAX', - // @deprecated - MAXIMUM = 'MAX', - SUM = 'SUM', - RANGE = 'RANGE', - COUNT = 'COUNT', - STD_P = 'STD.P', - STD_S = 'STD.S', - VAR_P = 'VAR.P', - VAR_S = 'VAR.S', - TWA = 'TWA' -} - -export enum TimeSeriesDuplicatePolicies { - BLOCK = 'BLOCK', - FIRST = 'FIRST', - LAST = 'LAST', - MIN = 'MIN', - MAX = 'MAX', - SUM = 'SUM' -} - -export enum TimeSeriesReducers { - AVG = 'AVG', - SUM = 'SUM', - MIN = 'MIN', - // @deprecated - MINIMUM = 'MIN', - MAX = 'MAX', - // @deprecated - MAXIMUM = 'MAX', - RANGE = 'range', - COUNT = 'COUNT', - STD_P = 'STD.P', - STD_S = 'STD.S', - VAR_P = 'VAR.P', - VAR_S = 'VAR.S', + ADD, + add: ADD, + ALTER, + alter: ALTER, + CREATE, + create: CREATE, + CREATERULE, + createRule: CREATERULE, + DECRBY, + decrBy: DECRBY, + DEL, + del: DEL, + DELETERULE, + deleteRule: DELETERULE, + GET, + get: GET, + INCRBY, + incrBy: INCRBY, + // INFO_DEBUG, + // infoDebug: INFO_DEBUG, + // INFO, + // info: INFO, + MADD, + mAdd: MADD, + // MGET, + // mGet: MGET, + // MGET_WITHLABELS, + // mGetWithLabels: MGET_WITHLABELS, + // QUERYINDEX, + // queryIndex: QUERYINDEX, + // RANGE, + // range: RANGE, + // REVRANGE, + // revRange: REVRANGE, + // MRANGE, + // mRange: MRANGE, + // MRANGE_WITHLABELS, + // mRangeWithLabels: MRANGE_WITHLABELS, + // MREVRANGE, + // mRevRange: MREVRANGE, + // MREVRANGE_WITHLABELS, + // mRevRangeWithLabels: MREVRANGE_WITHLABELS +} as const satisfies RedisCommands; + +export function pushRetentionArgument(args: Array, retention?: number) { + if (retention !== undefined) { + args.push('RETENTION', retention.toString()); + } +} + +export const TIME_SERIES_ENCODING = { + COMPRESSED: 'COMPRESSED', + UNCOMPRESSED: 'UNCOMPRESSED' +} as const; + +export type TimeSeriesEncoding = typeof TIME_SERIES_ENCODING[keyof typeof TIME_SERIES_ENCODING]; + +export function pushEncodingArgument(args: Array, encoding?: TimeSeriesEncoding) { + if (encoding !== undefined) { + args.push('ENCODING', encoding); + } +} + +export function pushChunkSizeArgument(args: Array, chunkSize?: number) { + if (chunkSize !== undefined) { + args.push('CHUNK_SIZE', chunkSize.toString()); + } +} + +export const TIME_SERIES_DUPLICATE_POLICIES = { + BLOCK: 'BLOCK', + FIRST: 'FIRST', + LAST: 'LAST', + MIN: 'MIN', + MAX: 'MAX', + SUM: 'SUM' +} as const; + +export type TimeSeriesDuplicatePolicies = typeof TIME_SERIES_DUPLICATE_POLICIES[keyof typeof TIME_SERIES_DUPLICATE_POLICIES]; + +export function pushDuplicatePolicy(args: Array, duplicatePolicy?: TimeSeriesDuplicatePolicies) { + if (duplicatePolicy !== undefined) { + args.push('DUPLICATE_POLICY', duplicatePolicy); + } } export type Timestamp = number | Date | string; export function transformTimestampArgument(timestamp: Timestamp): string { - if (typeof timestamp === 'string') return timestamp; - - return ( - typeof timestamp === 'number' ? - timestamp : - timestamp.getTime() - ).toString(); -} - -export function pushRetentionArgument(args: RedisCommandArguments, retention?: number): RedisCommandArguments { - if (retention !== undefined) { - args.push( - 'RETENTION', - retention.toString() - ); - } + if (typeof timestamp === 'string') return timestamp; - return args; + return ( + typeof timestamp === 'number' ? + timestamp : + timestamp.getTime() + ).toString(); } -export enum TimeSeriesEncoding { - COMPRESSED = 'COMPRESSED', - UNCOMPRESSED = 'UNCOMPRESSED' -} - -export function pushEncodingArgument(args: RedisCommandArguments, encoding?: TimeSeriesEncoding): RedisCommandArguments { - if (encoding !== undefined) { - args.push( - 'ENCODING', - encoding - ); - } - - return args; -} - -export function pushChunkSizeArgument(args: RedisCommandArguments, chunkSize?: number): RedisCommandArguments { - if (chunkSize !== undefined) { - args.push( - 'CHUNK_SIZE', - chunkSize.toString() - ); - } - - return args; -} - -export function pushDuplicatePolicy(args: RedisCommandArguments, duplicatePolicy?: TimeSeriesDuplicatePolicies): RedisCommandArguments { - if (duplicatePolicy !== undefined) { - args.push( - 'DUPLICATE_POLICY', - duplicatePolicy - ); - } - - return args; -} - -export type RawLabels = Array<[label: string, value: string]>; - export type Labels = { - [label: string]: string; + [label: string]: string; }; -export function transformLablesReply(reply: RawLabels): Labels { - const labels: Labels = {}; - - for (const [key, value] of reply) { - labels[key] = value; - } - - return labels -} - -export function pushLabelsArgument(args: RedisCommandArguments, labels?: Labels): RedisCommandArguments { - if (labels) { - args.push('LABELS'); - - for (const [label, value] of Object.entries(labels)) { - args.push(label, value); - } - } - - return args; -} - -export interface IncrDecrOptions { - TIMESTAMP?: Timestamp; - RETENTION?: number; - UNCOMPRESSED?: boolean; - CHUNK_SIZE?: number; - LABELS?: Labels; -} - -export function transformIncrDecrArguments( - command: 'TS.INCRBY' | 'TS.DECRBY', - key: string, - value: number, - options?: IncrDecrOptions -): RedisCommandArguments { - const args = [ - command, - key, - value.toString() - ]; - - if (options?.TIMESTAMP !== undefined && options?.TIMESTAMP !== null) { - args.push('TIMESTAMP', transformTimestampArgument(options.TIMESTAMP)); - } - - pushRetentionArgument(args, options?.RETENTION); - - if (options?.UNCOMPRESSED) { - args.push('UNCOMPRESSED'); - } - - pushChunkSizeArgument(args, options?.CHUNK_SIZE); - - pushLabelsArgument(args, options?.LABELS); - - return args; -} - -export type SampleRawReply = [timestamp: number, value: string]; - -export interface SampleReply { - timestamp: number; - value: number; -} - -export function transformSampleReply(reply: SampleRawReply): SampleReply { - return { - timestamp: reply[0], - value: Number(reply[1]) - }; -} - -export enum TimeSeriesBucketTimestamp { - LOW = '-', - HIGH = '+', - MID = '~' -} - -export interface RangeOptions { - LATEST?: boolean; - FILTER_BY_TS?: Array; - FILTER_BY_VALUE?: { - min: number; - max: number; - }; - COUNT?: number; - ALIGN?: Timestamp; - AGGREGATION?: { - type: TimeSeriesAggregationType; - timeBucket: Timestamp; - BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp; - EMPTY?: boolean; - }; -} - -export function pushRangeArguments( - args: RedisCommandArguments, - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - options?: RangeOptions -): RedisCommandArguments { - args.push( - transformTimestampArgument(fromTimestamp), - transformTimestampArgument(toTimestamp) - ); - - pushLatestArgument(args, options?.LATEST); - - if (options?.FILTER_BY_TS) { - args.push('FILTER_BY_TS'); - for (const ts of options.FILTER_BY_TS) { - args.push(transformTimestampArgument(ts)); - } - } - - if (options?.FILTER_BY_VALUE) { - args.push( - 'FILTER_BY_VALUE', - options.FILTER_BY_VALUE.min.toString(), - options.FILTER_BY_VALUE.max.toString() - ); - } - - if (options?.COUNT) { - args.push( - 'COUNT', - options.COUNT.toString() - ); - } - - if (options?.ALIGN) { - args.push( - 'ALIGN', - transformTimestampArgument(options.ALIGN) - ); - } - - if (options?.AGGREGATION) { - args.push( - 'AGGREGATION', - options.AGGREGATION.type, - transformTimestampArgument(options.AGGREGATION.timeBucket) - ); - - if (options.AGGREGATION.BUCKETTIMESTAMP) { - args.push( - 'BUCKETTIMESTAMP', - options.AGGREGATION.BUCKETTIMESTAMP - ); - } - - if (options.AGGREGATION.EMPTY) { - args.push('EMPTY'); - } - } - - return args; -} - -interface MRangeGroupBy { - label: string; - reducer: TimeSeriesReducers; -} - -export function pushMRangeGroupByArguments(args: RedisCommandArguments, groupBy?: MRangeGroupBy): RedisCommandArguments { - if (groupBy) { - args.push( - 'GROUPBY', - groupBy.label, - 'REDUCE', - groupBy.reducer - ); - } - - return args; -} - -export type Filter = string | Array; - -export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array): RedisCommandArguments { - args.push('FILTER'); - return pushVariadicArguments(args, filter); -} - -export interface MRangeOptions extends RangeOptions { - GROUPBY?: MRangeGroupBy; -} - -export function pushMRangeArguments( - args: RedisCommandArguments, - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filter: Filter, - options?: MRangeOptions -): RedisCommandArguments { - args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); - args = pushFilterArgument(args, filter); - return pushMRangeGroupByArguments(args, options?.GROUPBY); -} - -export type SelectedLabels = string | Array; +export function pushLabelsArgument(args: Array, labels?: Labels) { + if (labels) { + args.push('LABELS'); -export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments { - if (!selectedLabels) { - args.push('WITHLABELS'); - } else { - args.push('SELECTED_LABELS'); - args = pushVariadicArguments(args, selectedLabels); + for (const [label, value] of Object.entries(labels)) { + args.push(label, value); } - - return args; -} - -export interface MRangeWithLabelsOptions extends MRangeOptions { - SELECTED_LABELS?: SelectedLabels; -} - -export function pushMRangeWithLabelsArguments( - args: RedisCommandArguments, - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filter: Filter, - options?: MRangeWithLabelsOptions -): RedisCommandArguments { - args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); - args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); - args = pushFilterArgument(args, filter); - return pushMRangeGroupByArguments(args, options?.GROUPBY); -} - -export function transformRangeReply(reply: Array): Array { - return reply.map(transformSampleReply); -} - -type MRangeRawReply = Array<[ - key: string, - labels: RawLabels, - samples: Array -]>; - -interface MRangeReplyItem { - key: string; - samples: Array; -} - -export function transformMRangeReply(reply: MRangeRawReply): Array { - const args = []; - - for (const [key, _, sample] of reply) { - args.push({ - key, - samples: sample.map(transformSampleReply) - }); - } - - return args; -} -export interface MRangeWithLabelsReplyItem extends MRangeReplyItem { - labels: Labels; -} - -export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array { - const args = []; - - for (const [key, labels, samples] of reply) { - args.push({ - key, - labels: transformLablesReply(labels), - samples: samples.map(transformSampleReply) - }); - } - - return args; -} - -export function pushLatestArgument(args: RedisCommandArguments, latest?: boolean): RedisCommandArguments { - if (latest) { - args.push('LATEST'); - } - - return args; -} + } + + return args; +} + +// export type RawLabelsReply = ArrayReply>; + +// export function transformLablesReply(reply: RawLabelsReply) { +// const labels: Record = {}; + +// for (const [key, value] of reply) { +// labels[key.toString()] = value; +// } + +// return labels +// } + + +// export type SampleRawReply = [timestamp: number, value: string]; + +// export interface SampleReply { +// timestamp: number; +// value: number; +// } + +// export function transformSampleReply(reply: SampleRawReply): SampleReply { +// return { +// timestamp: reply[0], +// value: Number(reply[1]) +// }; +// } + +// export enum TimeSeriesBucketTimestamp { +// LOW = '-', +// HIGH = '+', +// MID = '~' +// } + +// export interface RangeOptions { +// LATEST?: boolean; +// FILTER_BY_TS?: Array; +// FILTER_BY_VALUE?: { +// min: number; +// max: number; +// }; +// COUNT?: number; +// ALIGN?: Timestamp; +// AGGREGATION?: { +// type: TimeSeriesAggregationType; +// timeBucket: Timestamp; +// BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp; +// EMPTY?: boolean; +// }; +// } + +// export function pushRangeArguments( +// args: RedisCommandArguments, +// fromTimestamp: Timestamp, +// toTimestamp: Timestamp, +// options?: RangeOptions +// ): RedisCommandArguments { +// args.push( +// transformTimestampArgument(fromTimestamp), +// transformTimestampArgument(toTimestamp) +// ); + +// pushLatestArgument(args, options?.LATEST); + +// if (options?.FILTER_BY_TS) { +// args.push('FILTER_BY_TS'); +// for (const ts of options.FILTER_BY_TS) { +// args.push(transformTimestampArgument(ts)); +// } +// } + +// if (options?.FILTER_BY_VALUE) { +// args.push( +// 'FILTER_BY_VALUE', +// options.FILTER_BY_VALUE.min.toString(), +// options.FILTER_BY_VALUE.max.toString() +// ); +// } + +// if (options?.COUNT) { +// args.push( +// 'COUNT', +// options.COUNT.toString() +// ); +// } + +// if (options?.ALIGN) { +// args.push( +// 'ALIGN', +// transformTimestampArgument(options.ALIGN) +// ); +// } + +// if (options?.AGGREGATION) { +// args.push( +// 'AGGREGATION', +// options.AGGREGATION.type, +// transformTimestampArgument(options.AGGREGATION.timeBucket) +// ); + +// if (options.AGGREGATION.BUCKETTIMESTAMP) { +// args.push( +// 'BUCKETTIMESTAMP', +// options.AGGREGATION.BUCKETTIMESTAMP +// ); +// } + +// if (options.AGGREGATION.EMPTY) { +// args.push('EMPTY'); +// } +// } + +// return args; +// } + +// interface MRangeGroupBy { +// label: string; +// reducer: TimeSeriesReducers; +// } + +// export function pushMRangeGroupByArguments(args: RedisCommandArguments, groupBy?: MRangeGroupBy): RedisCommandArguments { +// if (groupBy) { +// args.push( +// 'GROUPBY', +// groupBy.label, +// 'REDUCE', +// groupBy.reducer +// ); +// } + +// return args; +// } + +// export type Filter = string | Array; + +// export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array): RedisCommandArguments { +// args.push('FILTER'); +// return pushVariadicArguments(args, filter); +// } + +// export interface MRangeOptions extends RangeOptions { +// GROUPBY?: MRangeGroupBy; +// } + +// export function pushMRangeArguments( +// args: RedisCommandArguments, +// fromTimestamp: Timestamp, +// toTimestamp: Timestamp, +// filter: Filter, +// options?: MRangeOptions +// ): RedisCommandArguments { +// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); +// args = pushFilterArgument(args, filter); +// return pushMRangeGroupByArguments(args, options?.GROUPBY); +// } + +// export type SelectedLabels = string | Array; + +// export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments { +// if (!selectedLabels) { +// args.push('WITHLABELS'); +// } else { +// args.push('SELECTED_LABELS'); +// args = pushVariadicArguments(args, selectedLabels); +// } + +// return args; +// } + +// export interface MRangeWithLabelsOptions extends MRangeOptions { +// SELECTED_LABELS?: SelectedLabels; +// } + +// export function pushMRangeWithLabelsArguments( +// args: RedisCommandArguments, +// fromTimestamp: Timestamp, +// toTimestamp: Timestamp, +// filter: Filter, +// options?: MRangeWithLabelsOptions +// ): RedisCommandArguments { +// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); +// args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); +// args = pushFilterArgument(args, filter); +// return pushMRangeGroupByArguments(args, options?.GROUPBY); +// } + +// export function transformRangeReply(reply: Array): Array { +// return reply.map(transformSampleReply); +// } + +// type MRangeRawReply = Array<[ +// key: string, +// labels: RawLabels, +// samples: Array +// ]>; + +// interface MRangeReplyItem { +// key: string; +// samples: Array; +// } + +// export function transformMRangeReply(reply: MRangeRawReply): Array { +// const args = []; + +// for (const [key, _, sample] of reply) { +// args.push({ +// key, +// samples: sample.map(transformSampleReply) +// }); +// } + +// return args; +// } +// export interface MRangeWithLabelsReplyItem extends MRangeReplyItem { +// labels: Labels; +// } + +// export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array { +// const args = []; + +// for (const [key, labels, samples] of reply) { +// args.push({ +// key, +// labels: transformLablesReply(labels), +// samples: samples.map(transformSampleReply) +// }); +// } + +// return args; +// } diff --git a/packages/time-series/lib/index.ts b/packages/time-series/lib/index.ts index 6002556ca1a..e0b3c967057 100644 --- a/packages/time-series/lib/index.ts +++ b/packages/time-series/lib/index.ts @@ -1,9 +1,11 @@ export { default } from './commands'; export { - TimeSeriesDuplicatePolicies, + TIME_SERIES_ENCODING, TimeSeriesEncoding, - TimeSeriesAggregationType, - TimeSeriesReducers, - TimeSeriesBucketTimestamp + TIME_SERIES_DUPLICATE_POLICIES, + TimeSeriesDuplicatePolicies, + // TimeSeriesBucketTimestamp } from './commands'; + +export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE'; diff --git a/packages/time-series/lib/test-utils.ts b/packages/time-series/lib/test-utils.ts index 6d534ccccef..3c7fb035ae0 100644 --- a/packages/time-series/lib/test-utils.ts +++ b/packages/time-series/lib/test-utils.ts @@ -2,19 +2,19 @@ import TestUtils from '@redis/test-utils'; import TimeSeries from '.'; export default new TestUtils({ - dockerImageName: 'redislabs/redistimeseries', - dockerImageVersionArgument: 'timeseries-version' + dockerImageName: 'redislabs/redistimeseries', + dockerImageVersionArgument: 'timeseries-version' }); export const GLOBAL = { - SERVERS: { - OPEN: { - serverArguments: ['--loadmodule /usr/lib/redis/modules/redistimeseries.so'], - clientOptions: { - modules: { - ts: TimeSeries - } - } + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/redistimeseries.so'], + clientOptions: { + modules: { + ts: TimeSeries } + } } + } }; From a3e813d3aced74f999cc77b50526bcdca0192aba Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 13 Jul 2023 13:42:59 -0400 Subject: [PATCH 190/325] convert "resp types" to interfaces to allow circular references --- packages/client/lib/RESP/types.ts | 157 ++++++++++-------- packages/client/lib/client/index.ts | 1 - packages/client/lib/commands/ACL_GETUSER.ts | 17 +- packages/client/lib/commands/ACL_LOG.ts | 32 ++-- packages/client/lib/commands/BITFIELD.spec.ts | 6 + packages/client/lib/commands/BLPOP.ts | 4 +- packages/client/lib/commands/BZPOPMAX.ts | 6 +- .../client/lib/commands/CLIENT_INFO.spec.ts | 82 ++++----- .../client/lib/commands/CLIENT_LIST.spec.ts | 127 +++++++------- packages/client/lib/commands/CLIENT_LIST.ts | 2 +- .../lib/commands/CLIENT_TRACKINGINFO.ts | 4 +- packages/client/lib/commands/CLUSTER_LINKS.ts | 21 ++- packages/client/lib/commands/CLUSTER_SLOTS.ts | 11 +- .../lib/commands/COMMAND_GETKEYSANDFLAGS.ts | 15 +- .../client/lib/commands/FUNCTION_LIST.spec.ts | 26 +-- packages/client/lib/commands/FUNCTION_LIST.ts | 32 ++-- .../commands/FUNCTION_LIST_WITHCODE.spec.ts | 32 ++-- .../lib/commands/FUNCTION_LIST_WITHCODE.ts | 30 ++-- packages/client/lib/commands/GEOPOS.ts | 13 +- .../client/lib/commands/GEOSEARCH_WITH.ts | 14 +- packages/client/lib/commands/HELLO.ts | 4 +- .../commands/HRANDFIELD_COUNT_WITHVALUES.ts | 17 +- packages/client/lib/commands/LCS_IDX.ts | 4 +- .../lib/commands/LCS_IDX_WITHMATCHLEN.ts | 4 +- packages/client/lib/commands/MEMORY_STATS.ts | 9 +- packages/client/lib/commands/MODULE_LIST.ts | 15 +- packages/client/lib/commands/PUBSUB_NUMSUB.ts | 4 +- packages/client/lib/commands/ROLE.ts | 23 +-- packages/client/lib/commands/XAUTOCLAIM.ts | 4 +- .../client/lib/commands/XAUTOCLAIM_JUSTID.ts | 4 +- .../client/lib/commands/XINFO_CONSUMERS.ts | 19 ++- packages/client/lib/commands/XINFO_GROUPS.ts | 23 +-- packages/client/lib/commands/XINFO_STREAM.ts | 2 +- packages/client/lib/commands/XPENDING.ts | 16 +- .../client/lib/commands/XPENDING_RANGE.ts | 19 ++- packages/client/lib/commands/ZMPOP.ts | 21 ++- packages/client/lib/commands/ZMSCORE.ts | 4 +- packages/client/lib/commands/ZPOPMAX.ts | 6 +- .../client/lib/commands/ZRANK_WITHSCORE.ts | 6 +- .../lib/commands/generic-transformers.ts | 48 +++--- packages/client/lib/errors.ts | 70 ++++---- 41 files changed, 524 insertions(+), 430 deletions(-) diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 53f4d8a7427..004da46756e 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -1,3 +1,4 @@ +import { BlobError, SimpleError } from '../errors'; import { RedisScriptConfig, SHA1 } from '../lua-script'; import { RESP_TYPES } from './decoder'; import { VerbatimString } from './verbatim-string'; @@ -6,120 +7,138 @@ export type RESP_TYPES = typeof RESP_TYPES; export type RespTypes = RESP_TYPES[keyof RESP_TYPES]; -export type RespType< +// using interface(s) to allow circular references +// type X = BlobStringReply | ArrayReply; + +export interface RespType< RESP_TYPE extends RespTypes, DEFAULT, TYPES = never, - FLAG_TYPES = DEFAULT | TYPES -> = (DEFAULT | TYPES) & { + TYPE_MAPPING = DEFAULT | TYPES +> { RESP_TYPE: RESP_TYPE; DEFAULT: DEFAULT; TYPES: TYPES; - FLAG: Flag; -}; + TYPE_MAPPING: MappedType; +} -export type NullReply = RespType< +export interface NullReply extends RespType< RESP_TYPES['NULL'], null ->; -export type BooleanReply< +> {} + +export interface BooleanReply< T extends boolean = boolean -> = RespType< +> extends RespType< RESP_TYPES['BOOLEAN'], T ->; -export type NumberReply< +> {} + +export interface NumberReply< T extends number = number -> = RespType< +> extends RespType< RESP_TYPES['NUMBER'], T, `${T}`, number | string ->; -export type BigNumberReply< +> {} + +export interface BigNumberReply< T extends bigint = bigint -> = RespType< +> extends RespType< RESP_TYPES['BIG_NUMBER'], T, number | `${T}`, bigint | number | string ->; -export type DoubleReply< +> {} + +export interface DoubleReply< T extends number = number -> = RespType< +> extends RespType< RESP_TYPES['DOUBLE'], T, `${T}`, number | string ->; -export type SimpleStringReply< +> {} + +export interface SimpleStringReply< T extends string = string -> = RespType< +> extends RespType< RESP_TYPES['SIMPLE_STRING'], T, Buffer, string | Buffer ->; -export type BlobStringReply< +> {} + +export interface BlobStringReply< T extends string = string -> = RespType< +> extends RespType< RESP_TYPES['BLOB_STRING'], T, Buffer, string | Buffer ->; -export type VerbatimStringReply< +> {} + +export interface VerbatimStringReply< T extends string = string -> = RespType< +> extends RespType< RESP_TYPES['VERBATIM_STRING'], T, Buffer | VerbatimString, string | Buffer | VerbatimString ->; -export type SimpleErrorReply = RespType< +> {} + +export interface SimpleErrorReply extends RespType< RESP_TYPES['SIMPLE_ERROR'], + SimpleError, Buffer ->; -export type BlobErrorReply = RespType< +> {} + +export interface BlobErrorReply extends RespType< RESP_TYPES['BLOB_ERROR'], + BlobError, Buffer ->; -export type ArrayReply = RespType< +> {} + +export interface ArrayReply extends RespType< RESP_TYPES['ARRAY'], Array, never, Array ->; -export type TuplesReply]> = RespType< +> {} + +export interface TuplesReply]> extends RespType< RESP_TYPES['ARRAY'], T, never, Array ->; -export type SetReply = RespType< +> {} + +export interface SetReply extends RespType< RESP_TYPES['SET'], Array, Set, Array | Set ->; -export type MapReply = RespType< +> {} + +export interface MapReply extends RespType< RESP_TYPES['MAP'], { [key: string]: V }, Map | Array, Map | Array ->; +> {} type MapKeyValue = [key: BlobStringReply, value: unknown]; type MapTuples = Array; -export type TuplesToMapReply = RespType< +export interface TuplesToMapReply extends RespType< RESP_TYPES['MAP'], { [P in T[number] as P[0] extends BlobStringReply ? S : never]: P[1]; }, Map | FlattenTuples ->; +> {} type FlattenTuples = ( T extends [] ? [] : @@ -131,31 +150,28 @@ type FlattenTuples = ( never ); -export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply | - // cannot reuse ArrayReply, SetReply and MapReply because of circular reference - RespType< - RESP_TYPES['ARRAY'], - Array - > | - RespType< - RESP_TYPES['SET'], - Array, - Set - > | - RespType< - RESP_TYPES['MAP'], - { [key: string]: ReplyUnion }, - Map | Array - >; - -export type Reply = ReplyWithTypeMapping; - -export type Flag = ((...args: any) => T) | (new (...args: any) => T); - -type RespTypeUnion = T extends RespType ? FLAG_TYPES : never; +export type ReplyUnion = ( + NullReply | + BooleanReply | + NumberReply | + BigNumberReply | + DoubleReply | + SimpleStringReply | + BlobStringReply | + VerbatimStringReply | + SimpleErrorReply | + BlobErrorReply | + ArrayReply | + SetReply | + MapReply +); + +export type MappedType = ((...args: any) => T) | (new (...args: any) => T); + +type InferTypeMapping = T extends RespType ? FLAG_TYPES : never; export type TypeMapping = { - [P in RespTypes]?: Flag>>>; + [P in RespTypes]?: MappedType>>>; }; type MapKey< @@ -167,13 +183,15 @@ type MapKey< [RESP_TYPES.BLOB_STRING]: StringConstructor; }>; +export type UnwrapReply> = REPLY['DEFAULT' | 'TYPES']; + export type ReplyWithTypeMapping< REPLY, TYPE_MAPPING extends TypeMapping > = ( // if REPLY is a type, extract the coresponding type from TYPE_MAPPING or use the default type REPLY extends RespType ? - TYPE_MAPPING[RESP_TYPE] extends Flag ? + TYPE_MAPPING[RESP_TYPE] extends MappedType ? ReplyWithTypeMapping, TYPE_MAPPING> : ReplyWithTypeMapping : ( @@ -193,6 +211,11 @@ export type ReplyWithTypeMapping< ) ); +type a = ReplyWithTypeMapping< + ArrayReply>, + {} +>; + export type TransformReply = (this: void, reply: any, preserve?: any) => any; // TODO; export type RedisArgument = string | Buffer; @@ -323,7 +346,7 @@ export type CommandReply< // if transformReply[RESP] is a function, use its return type COMMAND['transformReply'] extends Record infer T> ? T : // otherwise use the generic reply type - Reply + ReplyUnion ); export type CommandSignature< diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 5a96388b4df..dbf8b85b034 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -425,7 +425,6 @@ export default class RedisClient< } catch (err) { this._queue.decoder.reset(); this.emit('error', err); - } }) .on('error', err => { diff --git a/packages/client/lib/commands/ACL_GETUSER.ts b/packages/client/lib/commands/ACL_GETUSER.ts index c9489abaf51..cbbf48a4c69 100644 --- a/packages/client/lib/commands/ACL_GETUSER.ts +++ b/packages/client/lib/commands/ACL_GETUSER.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; type AclUser = TuplesToMapReply<[ [BlobStringReply<'flags'>, ArrayReply], @@ -23,17 +23,20 @@ export default { return ['ACL', 'GETUSER', username]; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ flags: reply[1], passwords: reply[3], commands: reply[5], keys: reply[7], channels: reply[9], - selectors: reply[11]?.map(selector => ({ - commands: selector[1], - keys: selector[3], - channels: selector[5] - })) + selectors: (reply[11] as unknown as UnwrapReply)?.map(selector => { + const inferred = selector as unknown as UnwrapReply; + return { + commands: inferred[1], + keys: inferred[3], + channels: inferred[5] + }; + }) }), 3: undefined as unknown as () => AclUser } diff --git a/packages/client/lib/commands/ACL_LOG.ts b/packages/client/lib/commands/ACL_LOG.ts index 55172095d1b..fab870f27c3 100644 --- a/packages/client/lib/commands/ACL_LOG.ts +++ b/packages/client/lib/commands/ACL_LOG.ts @@ -1,5 +1,4 @@ -import { DoubleReply, Resp2Reply } from '../RESP/types'; -import { ArrayReply, BlobStringReply, Command, NumberReply, TuplesToMapReply } from '../RESP/types'; +import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export type AclLogReply = ArrayReply, NumberReply], @@ -30,18 +29,23 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => reply.map(item => ({ - count: item[1], - reason: item[3], - context: item[5], - object: item[7], - username: item[9], - 'age-seconds': Number(item[11]), - 'client-info': item[13], - 'entry-id': item[15], - 'timestamp-created': item[17], - 'timestamp-last-updated': item[19] - })), + 2: (reply: UnwrapReply>) => { + return reply.map(item => { + const inferred = item as unknown as UnwrapReply; + return { + count: inferred[1], + reason: inferred[3], + context: inferred[5], + object: inferred[7], + username: inferred[9], + 'age-seconds': Number(inferred[11]), + 'client-info': inferred[13], + 'entry-id': inferred[15], + 'timestamp-created': inferred[17], + 'timestamp-last-updated': inferred[19] + }; + }) + }, 3: undefined as unknown as () => AclLogReply } } as const satisfies Command; diff --git a/packages/client/lib/commands/BITFIELD.spec.ts b/packages/client/lib/commands/BITFIELD.spec.ts index 9b94b19d240..93ca665deb7 100644 --- a/packages/client/lib/commands/BITFIELD.spec.ts +++ b/packages/client/lib/commands/BITFIELD.spec.ts @@ -34,6 +34,12 @@ describe('BITFIELD', () => { }); testUtils.testAll('bitField', async client => { + const a = client.bitField('key', [{ + operation: 'GET', + encoding: 'i8', + offset: 0 + }]); + assert.deepEqual( await client.bitField('key', [{ operation: 'GET', diff --git a/packages/client/lib/commands/BLPOP.ts b/packages/client/lib/commands/BLPOP.ts index c40a18b3c80..c9f8b4775eb 100644 --- a/packages/client/lib/commands/BLPOP.ts +++ b/packages/client/lib/commands/BLPOP.ts @@ -1,4 +1,4 @@ -import { BlobStringReply, NullReply, Command } from '../RESP/types'; +import { UnwrapReply, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { @@ -12,7 +12,7 @@ export default { args.push(timeout.toString()); return args; }, - transformReply(reply: NullReply | [BlobStringReply, BlobStringReply]) { + transformReply(reply: UnwrapReply>) { if (reply === null) return null; return { diff --git a/packages/client/lib/commands/BZPOPMAX.ts b/packages/client/lib/commands/BZPOPMAX.ts index 64059f1f784..c498a3b8045 100644 --- a/packages/client/lib/commands/BZPOPMAX.ts +++ b/packages/client/lib/commands/BZPOPMAX.ts @@ -1,4 +1,4 @@ -import { RedisArgument, Command, NullReply, TuplesReply, BlobStringReply, DoubleReply } from '../RESP/types'; +import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export function transformBZPopArguments( @@ -20,14 +20,14 @@ export default { return transformBZPopArguments('BZPOPMAX', ...args); }, transformReply: { - 2: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, BlobStringReply]>) => { + 2(reply: UnwrapReply>) { return reply === null ? null : { key: reply[0], value: reply[1], score: Number(reply[2]) }; }, - 3: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, DoubleReply]>) => { + 3(reply: UnwrapReply>) { return reply === null ? null : { key: reply[0], value: reply[1], diff --git a/packages/client/lib/commands/CLIENT_INFO.spec.ts b/packages/client/lib/commands/CLIENT_INFO.spec.ts index ccb99017cf3..ecc290d2f2c 100644 --- a/packages/client/lib/commands/CLIENT_INFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_INFO.spec.ts @@ -1,50 +1,50 @@ import { strict as assert } from 'assert'; -import { transformArguments, transformReply } from './CLIENT_INFO'; +import CLIENT_INFO from './CLIENT_INFO'; import testUtils, { GLOBAL } from '../test-utils'; describe('CLIENT INFO', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'INFO'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLIENT_INFO.transformArguments(), + ['CLIENT', 'INFO'] + ); + }); - testUtils.testWithClient('client.clientInfo', async client => { - const reply = await client.clientInfo(); - assert.equal(typeof reply.id, 'number'); - assert.equal(typeof reply.addr, 'string'); - assert.equal(typeof reply.laddr, 'string'); - assert.equal(typeof reply.fd, 'number'); - assert.equal(typeof reply.name, 'string'); - assert.equal(typeof reply.age, 'number'); - assert.equal(typeof reply.idle, 'number'); - assert.equal(typeof reply.flags, 'string'); - assert.equal(typeof reply.db, 'number'); - assert.equal(typeof reply.sub, 'number'); - assert.equal(typeof reply.psub, 'number'); - assert.equal(typeof reply.multi, 'number'); - assert.equal(typeof reply.qbuf, 'number'); - assert.equal(typeof reply.qbufFree, 'number'); - assert.equal(typeof reply.argvMem, 'number'); - assert.equal(typeof reply.obl, 'number'); - assert.equal(typeof reply.oll, 'number'); - assert.equal(typeof reply.omem, 'number'); - assert.equal(typeof reply.totMem, 'number'); - assert.equal(typeof reply.events, 'string'); - assert.equal(typeof reply.cmd, 'string'); - assert.equal(typeof reply.user, 'string'); - assert.equal(typeof reply.redir, 'number'); + testUtils.testWithClient('client.clientInfo', async client => { + const reply = await client.clientInfo(); + assert.equal(typeof reply.id, 'number'); + assert.equal(typeof reply.addr, 'string'); + assert.equal(typeof reply.laddr, 'string'); + assert.equal(typeof reply.fd, 'number'); + assert.equal(typeof reply.name, 'string'); + assert.equal(typeof reply.age, 'number'); + assert.equal(typeof reply.idle, 'number'); + assert.equal(typeof reply.flags, 'string'); + assert.equal(typeof reply.db, 'number'); + assert.equal(typeof reply.sub, 'number'); + assert.equal(typeof reply.psub, 'number'); + assert.equal(typeof reply.multi, 'number'); + assert.equal(typeof reply.qbuf, 'number'); + assert.equal(typeof reply.qbufFree, 'number'); + assert.equal(typeof reply.argvMem, 'number'); + assert.equal(typeof reply.obl, 'number'); + assert.equal(typeof reply.oll, 'number'); + assert.equal(typeof reply.omem, 'number'); + assert.equal(typeof reply.totMem, 'number'); + assert.equal(typeof reply.events, 'string'); + assert.equal(typeof reply.cmd, 'string'); + assert.equal(typeof reply.user, 'string'); + assert.equal(typeof reply.redir, 'number'); - if (testUtils.isVersionGreaterThan([7, 0])) { - assert.equal(typeof reply.multiMem, 'number'); - assert.equal(typeof reply.resp, 'number'); - } + if (testUtils.isVersionGreaterThan([7, 0])) { + assert.equal(typeof reply.multiMem, 'number'); + assert.equal(typeof reply.resp, 'number'); - if (testUtils.isVersionGreaterThan([7, 0, 3])) { - assert.equal(typeof reply.ssub, 'number'); - } - }, GLOBAL.SERVERS.OPEN); + if (testUtils.isVersionGreaterThan([7, 0, 3])) { + assert.equal(typeof reply.ssub, 'number'); + } + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_LIST.spec.ts b/packages/client/lib/commands/CLIENT_LIST.spec.ts index c9c720e12ef..5da86aa2971 100644 --- a/packages/client/lib/commands/CLIENT_LIST.spec.ts +++ b/packages/client/lib/commands/CLIENT_LIST.spec.ts @@ -1,78 +1,77 @@ import { strict as assert } from 'assert'; -import { transformArguments, transformReply } from './CLIENT_LIST'; +import CLIENT_LIST from './CLIENT_LIST'; import testUtils, { GLOBAL } from '../test-utils'; describe('CLIENT LIST', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['CLIENT', 'LIST'] - ); - }); - - it('with TYPE', () => { - assert.deepEqual( - transformArguments({ - TYPE: 'NORMAL' - }), - ['CLIENT', 'LIST', 'TYPE', 'NORMAL'] - ); - }); - - it('with ID', () => { - assert.deepEqual( - transformArguments({ - ID: ['1', '2'] - }), - ['CLIENT', 'LIST', 'ID', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CLIENT_LIST.transformArguments(), + ['CLIENT', 'LIST'] + ); }); - testUtils.testWithClient('client.clientList', async client => { - const reply = await client.clientList(); - assert.ok(Array.isArray(reply)); - - for (const item of reply) { - assert.equal(typeof item.id, 'number'); - assert.equal(typeof item.addr, 'string'); - assert.equal(typeof item.fd, 'number'); - assert.equal(typeof item.name, 'string'); - assert.equal(typeof item.age, 'number'); - assert.equal(typeof item.idle, 'number'); - assert.equal(typeof item.flags, 'string'); - assert.equal(typeof item.db, 'number'); - assert.equal(typeof item.sub, 'number'); - assert.equal(typeof item.psub, 'number'); - assert.equal(typeof item.multi, 'number'); - assert.equal(typeof item.qbuf, 'number'); - assert.equal(typeof item.qbufFree, 'number'); - assert.equal(typeof item.obl, 'number'); - assert.equal(typeof item.oll, 'number'); - assert.equal(typeof item.omem, 'number'); - assert.equal(typeof item.events, 'string'); - assert.equal(typeof item.cmd, 'string'); + it('with TYPE', () => { + assert.deepEqual( + CLIENT_LIST.transformArguments({ + TYPE: 'NORMAL' + }), + ['CLIENT', 'LIST', 'TYPE', 'NORMAL'] + ); + }); - if (testUtils.isVersionGreaterThan([6, 0])) { - assert.equal(typeof item.argvMem, 'number'); - assert.equal(typeof item.totMem, 'number'); - assert.equal(typeof item.user, 'string'); - } + it('with ID', () => { + assert.deepEqual( + CLIENT_LIST.transformArguments({ + ID: ['1', '2'] + }), + ['CLIENT', 'LIST', 'ID', '1', '2'] + ); + }); + }); - if (testUtils.isVersionGreaterThan([6, 2])) { - assert.equal(typeof item.redir, 'number'); - assert.equal(typeof item.laddr, 'string'); - } + testUtils.testWithClient('client.clientList', async client => { + const reply = await client.clientList(); + assert.ok(Array.isArray(reply)); + for (const item of reply) { + assert.equal(typeof item.id, 'number'); + assert.equal(typeof item.addr, 'string'); + assert.equal(typeof item.fd, 'number'); + assert.equal(typeof item.name, 'string'); + assert.equal(typeof item.age, 'number'); + assert.equal(typeof item.idle, 'number'); + assert.equal(typeof item.flags, 'string'); + assert.equal(typeof item.db, 'number'); + assert.equal(typeof item.sub, 'number'); + assert.equal(typeof item.psub, 'number'); + assert.equal(typeof item.multi, 'number'); + assert.equal(typeof item.qbuf, 'number'); + assert.equal(typeof item.qbufFree, 'number'); + assert.equal(typeof item.obl, 'number'); + assert.equal(typeof item.oll, 'number'); + assert.equal(typeof item.omem, 'number'); + assert.equal(typeof item.events, 'string'); + assert.equal(typeof item.cmd, 'string'); - if (testUtils.isVersionGreaterThan([7, 0])) { - assert.equal(typeof item.multiMem, 'number'); - assert.equal(typeof item.resp, 'number'); - } + if (testUtils.isVersionGreaterThan([6, 0])) { + assert.equal(typeof item.argvMem, 'number'); + assert.equal(typeof item.totMem, 'number'); + assert.equal(typeof item.user, 'string'); + + if (testUtils.isVersionGreaterThan([6, 2])) { + assert.equal(typeof item.redir, 'number'); + assert.equal(typeof item.laddr, 'string'); + + if (testUtils.isVersionGreaterThan([7, 0])) { + assert.equal(typeof item.multiMem, 'number'); + assert.equal(typeof item.resp, 'number'); if (testUtils.isVersionGreaterThan([7, 0, 3])) { - assert.equal(typeof item.ssub, 'number'); + assert.equal(typeof item.ssub, 'number'); } + } } - }, GLOBAL.SERVERS.OPEN); + } + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_LIST.ts b/packages/client/lib/commands/CLIENT_LIST.ts index f50634d56d3..dc43fb8855d 100644 --- a/packages/client/lib/commands/CLIENT_LIST.ts +++ b/packages/client/lib/commands/CLIENT_LIST.ts @@ -36,7 +36,7 @@ export default { length = split.length - 1, reply: Array = []; for (let i = 0; i < length; i++) { - reply.push(CLIENT_INFO.transformReply(split[i] as VerbatimStringReply)); + reply.push(CLIENT_INFO.transformReply(split[i] as unknown as VerbatimStringReply)); } return reply; diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts index 4c443532f5f..d969ba0219e 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.ts @@ -1,4 +1,4 @@ -import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, Resp2Reply, Command } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; type TrackingInfo = TuplesToMapReply<[ [BlobStringReply<'flags'>, SetReply], @@ -13,7 +13,7 @@ export default { return ['CLIENT', 'TRACKINGINFO']; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ flags: reply[1], redirect: reply[3], prefixes: reply[5] diff --git a/packages/client/lib/commands/CLUSTER_LINKS.ts b/packages/client/lib/commands/CLUSTER_LINKS.ts index 486553f9d07..df83f3f7a11 100644 --- a/packages/client/lib/commands/CLUSTER_LINKS.ts +++ b/packages/client/lib/commands/CLUSTER_LINKS.ts @@ -1,4 +1,4 @@ -import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types'; +import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; type ClusterLinksReply = ArrayReply, BlobStringReply], @@ -16,14 +16,17 @@ export default { return ['CLUSTER', 'LINKS']; }, transformReply: { - 2: (reply: Resp2Reply) => reply.map(link => ({ - direction: link[1], - node: link[3], - 'create-time': link[5], - events: link[7], - 'send-buffer-allocated': link[9], - 'send-buffer-used': link[11] - })), + 2: (reply: UnwrapReply>) => reply.map(link => { + const unwrapped = link as unknown as UnwrapReply; + return { + direction: unwrapped[1], + node: unwrapped[3], + 'create-time': unwrapped[5], + events: unwrapped[7], + 'send-buffer-allocated': unwrapped[9], + 'send-buffer-used': unwrapped[11] + }; + }), 3: undefined as unknown as () => ClusterLinksReply } } as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.ts b/packages/client/lib/commands/CLUSTER_SLOTS.ts index 13a925e9a48..1b523328bbb 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.ts @@ -1,10 +1,10 @@ -import { NumberReply, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { TuplesReply, BlobStringReply, NumberReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; -type RawNode = [ +type RawNode = TuplesReply<[ host: BlobStringReply, port: NumberReply, id: BlobStringReply -]; +]>; type ClusterSlotsRawReply = ArrayReply<[ from: NumberReply, @@ -21,7 +21,7 @@ export default { transformArguments() { return ['CLUSTER', 'SLOTS']; }, - transformReply(reply: ClusterSlotsRawReply) { + transformReply(reply: UnwrapReply) { return reply.map(([from, to, master, ...replicas]) => ({ from, to, @@ -31,7 +31,8 @@ export default { } } as const satisfies Command; -function transformNode([host, port, id ]: RawNode) { +function transformNode(node: RawNode) { + const [host, port, id] = node as unknown as UnwrapReply; return { host, port, diff --git a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts index a3581237f42..a032190c16e 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, UnwrapReply, Command } from '../RESP/types'; export type CommandGetKeysAndFlagsRawReply = ArrayReply) { return ['COMMAND', 'GETKEYSANDFLAGS', ...args]; }, - transformReply(reply: CommandGetKeysAndFlagsRawReply) { - return reply.map(([key, flags]) => ({ - key, - flags - })); + transformReply(reply: UnwrapReply) { + return reply.map(entry => { + const [key, flags] = entry as unknown as UnwrapReply; + return { + key, + flags + }; + }); } } as const satisfies Command; diff --git a/packages/client/lib/commands/FUNCTION_LIST.spec.ts b/packages/client/lib/commands/FUNCTION_LIST.spec.ts index c630b3aa52d..52c0ea9b63b 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.spec.ts @@ -25,19 +25,21 @@ describe('FUNCTION LIST', () => { }); testUtils.testWithClient('client.functionList', async client => { - await loadMathFunction(client); + const [, reply] = await Promise.all([ + loadMathFunction(client), + client.functionList() + ]); - assert.deepEqual( - await client.functionList(), - [{ - library_name: MATH_FUNCTION.name, - engine: MATH_FUNCTION.engine, - functions: [{ - name: MATH_FUNCTION.library.square.NAME, - description: null, - flags: ['no-writes'] - }] + reply[0].library_name; + + assert.deepEqual(reply, [{ + library_name: MATH_FUNCTION.name, + engine: MATH_FUNCTION.engine, + functions: [{ + name: MATH_FUNCTION.library.square.NAME, + description: null, + flags: ['no-writes'] }] - ); + }]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LIST.ts b/packages/client/lib/commands/FUNCTION_LIST.ts index 7150499e6de..8993496ca2c 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.ts @@ -1,18 +1,18 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, Resp2Reply, CommandArguments, Command } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types'; export interface FunctionListOptions { LIBRARYNAME?: RedisArgument; } export type FunctionListReplyItem = [ - [BlobStringReply<'library_name'>, BlobStringReply], + [BlobStringReply<'library_name'>, BlobStringReply | NullReply], [BlobStringReply<'engine'>, BlobStringReply], [BlobStringReply<'functions'>, ArrayReply, BlobStringReply], [BlobStringReply<'description'>, BlobStringReply | NullReply], [BlobStringReply<'flags'>, SetReply], ]>>] -] +]; export type FunctionListReply = ArrayReply>; @@ -29,16 +29,22 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => { - return reply.map(library => ({ - library_name: library[1], - engine: library[3], - functions: library[5].map(fn => ({ - name: fn[1], - description: fn[3], - flags: fn[5] - })) - })); + 2: (reply: UnwrapReply>) => { + return reply.map(library => { + const unwrapped = library as unknown as UnwrapReply; + return { + library_name: unwrapped[1], + engine: unwrapped[3], + functions: (unwrapped[5] as unknown as UnwrapReply).map(fn => { + const unwrapped = fn as unknown as UnwrapReply; + return { + name: unwrapped[1], + description: unwrapped[3], + flags: unwrapped[5] + }; + }) + }; + }); }, 3: undefined as unknown as () => FunctionListReply } diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts index 3c8342ab50c..528062eba66 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts @@ -25,20 +25,24 @@ describe('FUNCTION LIST WITHCODE', () => { }); testUtils.testWithClient('client.functionListWithCode', async client => { - await loadMathFunction(client); + const [, reply] = await Promise.all([ + loadMathFunction(client), + client.functionListWithCode() + ]); + + const a = reply[0]; + + const b = a.functions[0].description; - assert.deepEqual( - await client.functionListWithCode(), - [{ - library_name: MATH_FUNCTION.name, - engine: MATH_FUNCTION.engine, - functions: [{ - name: MATH_FUNCTION.library.square.NAME, - description: null, - flags: ['no-writes'] - }], - library_code: MATH_FUNCTION.code - }] - ); + assert.deepEqual(reply, [{ + library_name: MATH_FUNCTION.name, + engine: MATH_FUNCTION.engine, + functions: [{ + name: MATH_FUNCTION.library.square.NAME, + description: null, + flags: ['no-writes'] + }], + library_code: MATH_FUNCTION.code + }]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts index 6aa83d1d6a8..47a02a3da8a 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.ts @@ -1,4 +1,4 @@ -import { TuplesToMapReply, BlobStringReply, ArrayReply, Command, Resp2Reply } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; import FUNCTION_LIST, { FunctionListReplyItem } from './FUNCTION_LIST'; export type FunctionListWithCodeReply = ArrayReply) => { - return reply.map((library: any) => ({ - library_name: library[1], - engine: library[3], - functions: library[5].map((fn: any) => ({ - name: fn[1], - description: fn[3], - flags: fn[5] - })), - library_code: library[7] - })) as unknown as number; + 2: (reply: UnwrapReply>) => { + return reply.map(library => { + const unwrapped = library as unknown as UnwrapReply; + return { + library_name: unwrapped[1], + engine: unwrapped[3], + functions: (unwrapped[5] as unknown as UnwrapReply).map(fn => { + const unwrapped = fn as unknown as UnwrapReply; + return { + name: unwrapped[1], + description: unwrapped[3], + flags: unwrapped[5] + }; + }), + library_code: unwrapped[7] + }; + }); }, 3: undefined as unknown as () => FunctionListWithCodeReply } diff --git a/packages/client/lib/commands/GEOPOS.ts b/packages/client/lib/commands/GEOPOS.ts index d9fb5d3a25d..30273c64c18 100644 --- a/packages/client/lib/commands/GEOPOS.ts +++ b/packages/client/lib/commands/GEOPOS.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, NullReply, Command, RedisArgument } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NullReply, UnwrapReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { @@ -10,10 +10,13 @@ export default { ) { return pushVariadicArguments(['GEOPOS', key], member); }, - transformReply(reply: ArrayReply<[BlobStringReply, BlobStringReply] | NullReply>) { - return reply.map(item => item === null ? null : { - longitude: item[0], - latitude: item[1] + transformReply(reply: UnwrapReply | NullReply>>) { + return reply.map(item => { + const unwrapped = item as unknown as UnwrapReply; + return unwrapped === null ? null : { + longitude: unwrapped[0], + latitude: unwrapped[1] + }; }); } } as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts index 7dfb65c34cf..19088230f0f 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, NumberReply, DoubleReply, Command, RedisArgument } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Command } from '../RESP/types'; import GEOSEARCH, { GeoSearchBy, GeoSearchFrom, GeoSearchOptions } from './GEOSEARCH'; export const GEO_REPLY_WITH = { @@ -35,7 +35,7 @@ export default { return args; }, transformReply( - reply: ArrayReply<[BlobStringReply, ...Array]>, + reply: UnwrapReply]>>>, replyWith: Array ) { const replyWithSet = new Set(replyWith); @@ -45,20 +45,22 @@ export default { coordinatesIndex = replyWithSet.has(GEO_REPLY_WITH.COORDINATES) && ++index; return reply.map(raw => { + const unwrapped = raw as unknown as UnwrapReply; + const item: GeoReplyWithMember = { - member: raw[0] + member: unwrapped[0] }; if (distanceIndex) { - item.distance = raw[distanceIndex]; + item.distance = unwrapped[distanceIndex]; } if (hashIndex) { - item.hash = raw[hashIndex]; + item.hash = unwrapped[hashIndex]; } if (coordinatesIndex) { - const [longitude, latitude] = raw[coordinatesIndex]; + const [longitude, latitude] = unwrapped[coordinatesIndex]; item.coordinates = { longitude, latitude diff --git a/packages/client/lib/commands/HELLO.ts b/packages/client/lib/commands/HELLO.ts index 717ee05130d..0fb2960d028 100644 --- a/packages/client/lib/commands/HELLO.ts +++ b/packages/client/lib/commands/HELLO.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, BlobStringReply, Command, NumberReply, Resp2Reply, RespVersions, TuplesToMapReply } from '../RESP/types'; +import { RedisArgument, RespVersions, TuplesToMapReply, BlobStringReply, NumberReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export interface HelloOptions { protover?: RespVersions; @@ -45,7 +45,7 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ server: reply[1], version: reply[3], proto: reply[5], diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts index 2c7b17d5761..ab36183c4ad 100644 --- a/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT_WITHVALUES.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, UnwrapReply, Command } from '../RESP/types'; export type HRandFieldCountWithValuesReply = Array<{ field: BlobStringReply; @@ -12,7 +12,7 @@ export default { return ['HRANDFIELD', key, count.toString(), 'WITHVALUES']; }, transformReply: { - 2: (rawReply: ArrayReply) => { + 2: (rawReply: UnwrapReply>) => { const reply: HRandFieldCountWithValuesReply = []; let i = 0; @@ -25,11 +25,14 @@ export default { return reply; }, - 3: (reply: ArrayReply<[BlobStringReply, BlobStringReply]>) => { - return reply.map(([field, value]) => ({ - field, - value - })) satisfies HRandFieldCountWithValuesReply; + 3: (reply: UnwrapReply>>) => { + return reply.map(entry => { + const [field, value] = entry as unknown as UnwrapReply; + return { + field, + value + }; + }) satisfies HRandFieldCountWithValuesReply; } } } as const satisfies Command; diff --git a/packages/client/lib/commands/LCS_IDX.ts b/packages/client/lib/commands/LCS_IDX.ts index 41a0b61e8a8..0c266fffe1c 100644 --- a/packages/client/lib/commands/LCS_IDX.ts +++ b/packages/client/lib/commands/LCS_IDX.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, UnwrapReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; import LCS from './LCS'; export interface LcsIdxOptions { @@ -41,7 +41,7 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ matches: reply[1], len: reply[3] }), diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts index abd3bb361f5..4e645852035 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, TuplesReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; import LCS_IDX, { LcsIdxOptions, LcsIdxRange } from './LCS_IDX'; export type LcsIdxWithMatchLenMatches = ArrayReply< @@ -27,7 +27,7 @@ export default { return args; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ matches: reply[1], len: reply[3] }), diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 4e6997ff99c..38deae90134 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -1,4 +1,4 @@ -import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Command, Resp2Reply } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export type MemoryStatsReply = TuplesToMapReply<[ [BlobStringReply<'peak.allocated'>, NumberReply], @@ -39,13 +39,12 @@ export default { return ['MEMORY', 'STATS']; }, transformReply: { - 2: (rawReply: Array) => { - const reply: Partial> = {}; + 2: (rawReply: UnwrapReply>) => { + const reply: any = {}; let i = 0; while (i < rawReply.length) { - const key = rawReply[i++] as keyof MemoryStatsReply['DEFAULT']; - reply[key] = rawReply[i++] as any; + reply[rawReply[i++] as any] = rawReply[i++]; } return reply as MemoryStatsReply['DEFAULT']; diff --git a/packages/client/lib/commands/MODULE_LIST.ts b/packages/client/lib/commands/MODULE_LIST.ts index 9c61dcf07af..5ddd4e91ff6 100644 --- a/packages/client/lib/commands/MODULE_LIST.ts +++ b/packages/client/lib/commands/MODULE_LIST.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, NumberReply, Command, Resp2Reply, TuplesToMapReply } from '../RESP/types'; +import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export type ModuleListReply = ArrayReply, BlobStringReply], @@ -12,11 +12,14 @@ export default { return ['MODULE', 'LIST']; }, transformReply: { - 2: (reply: Resp2Reply) => { - return reply.map(module => ({ - name: module[1], - ver: module[3] - })); + 2: (reply: UnwrapReply>) => { + return reply.map(module => { + const unwrapped = module as unknown as UnwrapReply; + return { + name: unwrapped[1], + ver: unwrapped[3] + }; + }); }, 3: undefined as unknown as () => ModuleListReply } diff --git a/packages/client/lib/commands/PUBSUB_NUMSUB.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.ts index aaa6cf749c0..1f7c41f5bdd 100644 --- a/packages/client/lib/commands/PUBSUB_NUMSUB.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; +import { ArrayReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '../RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; export default { @@ -11,7 +11,7 @@ export default { return args; }, - transformReply(rawReply: ArrayReply) { + transformReply(rawReply: UnwrapReply>) { const reply = Object.create(null); let i = 0; while (i < rawReply.length) { diff --git a/packages/client/lib/commands/ROLE.ts b/packages/client/lib/commands/ROLE.ts index 40b9d67047b..7828e53fb61 100644 --- a/packages/client/lib/commands/ROLE.ts +++ b/packages/client/lib/commands/ROLE.ts @@ -1,9 +1,9 @@ -import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types'; +import { BlobStringReply, NumberReply, ArrayReply, TuplesReply, UnwrapReply, Command } from '../RESP/types'; type MasterRole = [ role: BlobStringReply<'master'>, replicationOffest: NumberReply, - replicas: ArrayReply<[host: BlobStringReply, port: BlobStringReply, replicationOffest: BlobStringReply]> + replicas: ArrayReply> ]; type SlaveRole = [ @@ -19,7 +19,7 @@ type SentinelRole = [ masterNames: ArrayReply ]; -type Role = MasterRole | SlaveRole | SentinelRole; +type Role = TuplesReply; export default { FIRST_KEY_INDEX: undefined, @@ -27,18 +27,21 @@ export default { transformArguments() { return ['ROLE']; }, - transformReply(reply: Role) { - switch (reply[0] as Role[0]['DEFAULT']) { + transformReply(reply: UnwrapReply) { + switch (reply[0] as unknown as UnwrapReply) { case 'master': { const [role, replicationOffest, replicas] = reply as MasterRole; return { role, replicationOffest, - replicas: replicas.map(([host, port, replicationOffest]) => ({ - host, - port: Number(port), - replicationOffest: Number(replicationOffest) - })), + replicas: (replicas as unknown as UnwrapReply).map(replica => { + const [host, port, replicationOffest] = replica as unknown as UnwrapReply; + return { + host, + port: Number(port), + replicationOffest: Number(replicationOffest) + }; + }) }; } diff --git a/packages/client/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts index b7a04734a3f..4c78aa12312 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types'; +import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; import { StreamMessagesRawReply, transformStreamMessagesReply } from './generic-transformers'; export interface XAutoClaimOptions { @@ -37,7 +37,7 @@ export default { return args; }, - transformReply(reply: XAutoClaimRawReply) { + transformReply(reply: UnwrapReply) { return { nextId: reply[0], messages: transformStreamMessagesReply(reply[1]), diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts index 2dc0961bc24..e2832f23536 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.ts @@ -1,4 +1,4 @@ -import { TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types'; +import { TuplesReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; import XAUTOCLAIM from './XAUTOCLAIM'; type XAutoClaimJustIdRawReply = TuplesReply<[ @@ -15,7 +15,7 @@ export default { redisArgs.push('JUSTID'); return redisArgs; }, - transformReply(reply: XAutoClaimJustIdRawReply) { + transformReply(reply: UnwrapReply) { return { nextId: reply[0], messages: reply[1], diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.ts b/packages/client/lib/commands/XINFO_CONSUMERS.ts index 81da67d161f..ca0076d6335 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export type XInfoConsumersReply = ArrayReply, BlobStringReply], @@ -18,13 +18,16 @@ export default { return ['XINFO', 'CONSUMERS', key, group]; }, transformReply: { - 2: (reply: Resp2Reply) => { - return reply.map(consumer => ({ - name: consumer[1], - pending: consumer[3], - idle: consumer[5], - inactive: consumer[7] - })); + 2: (reply: UnwrapReply>) => { + return reply.map(consumer => { + const unwrapped = consumer as unknown as UnwrapReply; + return { + name: unwrapped[1], + pending: unwrapped[3], + idle: unwrapped[5], + inactive: unwrapped[7] + }; + }); }, 3: undefined as unknown as () => XInfoConsumersReply } diff --git a/packages/client/lib/commands/XINFO_GROUPS.ts b/packages/client/lib/commands/XINFO_GROUPS.ts index e2e566d0e28..24661ecde84 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command, NullReply } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, NullReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; export type XInfoGroupsReply = ArrayReply, BlobStringReply], @@ -18,15 +18,18 @@ export default { return ['XINFO', 'GROUPS', key]; }, transformReply: { - 2: (reply: Resp2Reply) => { - return reply.map(group => ({ - name: group[1], - consumers: group[3], - pending: group[5], - 'last-delivered-id': group[7], - 'entries-read': group[9], - lag: group[11] - })); + 2: (reply: UnwrapReply>) => { + return reply.map(group => { + const unwrapped = group as unknown as UnwrapReply; + return { + name: unwrapped[1], + consumers: unwrapped[3], + pending: unwrapped[5], + 'last-delivered-id': unwrapped[7], + 'entries-read': unwrapped[9], + lag: unwrapped[11] + }; + }); }, 3: undefined as unknown as () => XInfoGroupsReply } diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index 93416ae40ae..9d809d4ab57 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -67,5 +67,5 @@ export default { } as const satisfies Command; function transformEntry(entry: StreamMessageRawReply | NullReply) { - return entry === null ? null : transformStreamMessageReply(entry); + return entry === null ? null : transformStreamMessageReply(entry as StreamMessageRawReply); } diff --git a/packages/client/lib/commands/XPENDING.ts b/packages/client/lib/commands/XPENDING.ts index efe07ceefb6..a6ca4f5a774 100644 --- a/packages/client/lib/commands/XPENDING.ts +++ b/packages/client/lib/commands/XPENDING.ts @@ -1,4 +1,4 @@ -import { RedisArgument, BlobStringReply, NullReply, TuplesReply, NumberReply, Command, ArrayReply } from '../RESP/types'; +import { RedisArgument, BlobStringReply, NullReply, ArrayReply, TuplesReply, NumberReply, UnwrapReply, Command } from '../RESP/types'; type XPendingRawReply = TuplesReply<[ pending: NumberReply, @@ -16,15 +16,19 @@ export default { transformArguments(key: RedisArgument, group: RedisArgument) { return ['XPENDING', key, group]; }, - transformReply(reply: XPendingRawReply) { + transformReply(reply: UnwrapReply) { + const consumers = reply[3] as unknown as UnwrapReply; return { pending: reply[0], firstId: reply[1], lastId: reply[2], - consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({ - name, - deliveriesCounter: Number(deliveriesCounter) - })) + consumers: consumers === null ? null : consumers.map(consumer => { + const [name, deliveriesCounter] = consumer as unknown as UnwrapReply; + return { + name, + deliveriesCounter: Number(deliveriesCounter) + }; + }) } } } as const satisfies Command; diff --git a/packages/client/lib/commands/XPENDING_RANGE.ts b/packages/client/lib/commands/XPENDING_RANGE.ts index 4fdf9b2b119..60a28e5172d 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '../RESP/types'; export interface XPendingRangeOptions { IDLE?: number; @@ -41,12 +41,15 @@ export default { return args; }, - transformReply(reply: XPendingRangeRawReply) { - return reply.map(pending => ({ - id: pending[0], - consumer: pending[1], - millisecondsSinceLastDelivery: pending[2], - deliveriesCounter: pending[3] - })); + transformReply(reply: UnwrapReply) { + return reply.map(pending => { + const unwrapped = pending as unknown as UnwrapReply; + return { + id: unwrapped[0], + consumer: unwrapped[1], + millisecondsSinceLastDelivery: unwrapped[2], + deliveriesCounter: unwrapped[3] + }; + }); } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts index 6960006173b..4cd8fc80276 100644 --- a/packages/client/lib/commands/ZMPOP.ts +++ b/packages/client/lib/commands/ZMPOP.ts @@ -1,5 +1,5 @@ -import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command, RedisArgument } from '../RESP/types'; -import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply } from './generic-transformers'; +import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; +import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply, transformDoubleReply } from './generic-transformers'; export interface ZMPopOptions { COUNT?: number; @@ -39,20 +39,23 @@ export default { return transformZMPopArguments(['ZMPOP'], ...args); }, transformReply: { - 2: (reply: Resp2Reply) => { + 2(reply: UnwrapReply>) { return reply === null ? null : { key: reply[0], - members: reply[1].map(([value, score]) => ({ - value, - score: Number(score) - })) + members: (reply[1] as unknown as UnwrapReply).map(member => { + const [value, score] = member as unknown as UnwrapReply; + return { + value, + score: transformDoubleReply[2](score) + }; + }) }; }, - 3: (reply: ZMPopRawReply) => { + 3(reply: UnwrapReply) { return reply === null ? null : { key: reply[0], members: transformSortedSetReply[3](reply[1]) }; - }, + } } } as const satisfies Command; diff --git a/packages/client/lib/commands/ZMSCORE.ts b/packages/client/lib/commands/ZMSCORE.ts index 4c3903b011b..983503983d5 100644 --- a/packages/client/lib/commands/ZMSCORE.ts +++ b/packages/client/lib/commands/ZMSCORE.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types'; import { pushVariadicArguments, RedisVariadicArgument, transformNullableDoubleReply } from './generic-transformers'; export default { @@ -11,7 +11,7 @@ export default { return pushVariadicArguments(['ZMSCORE', key], member); }, transformReply: { - 2: (reply: ArrayReply) => { + 2: (reply: UnwrapReply>) => { return reply.map(transformNullableDoubleReply[2]); }, 3: undefined as unknown as () => ArrayReply diff --git a/packages/client/lib/commands/ZPOPMAX.ts b/packages/client/lib/commands/ZPOPMAX.ts index fb4d2d958b7..012ba1fbb52 100644 --- a/packages/client/lib/commands/ZPOPMAX.ts +++ b/packages/client/lib/commands/ZPOPMAX.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -7,7 +7,7 @@ export default { return ['ZPOPMAX', key]; }, transformReply: { - 2: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, BlobStringReply]>) => { + 2: (reply: UnwrapReply>) => { if (reply.length === 0) return null; return { @@ -15,7 +15,7 @@ export default { score: Number(reply[1]) }; }, - 3: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, DoubleReply]>) => { + 3: (reply: UnwrapReply>) => { if (reply.length === 0) return null; return { diff --git a/packages/client/lib/commands/ZRANK_WITHSCORE.ts b/packages/client/lib/commands/ZRANK_WITHSCORE.ts index e68c31c20cb..39c788535e3 100644 --- a/packages/client/lib/commands/ZRANK_WITHSCORE.ts +++ b/packages/client/lib/commands/ZRANK_WITHSCORE.ts @@ -1,4 +1,4 @@ -import { NullReply, TuplesReply, NumberReply, BlobStringReply, DoubleReply, Command } from '../RESP/types'; +import { NullReply, TuplesReply, NumberReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types'; import ZRANK from './ZRANK'; export default { @@ -10,7 +10,7 @@ export default { return redisArgs; }, transformReply: { - 2: (reply: NullReply | TuplesReply<[NumberReply, BlobStringReply]>) => { + 2: (reply: UnwrapReply>) => { if (reply === null) return null; return { @@ -18,7 +18,7 @@ export default { score: Number(reply[1]) }; }, - 3: (reply: NullReply | TuplesReply<[BlobStringReply, DoubleReply]>) => { + 3: (reply: UnwrapReply>) => { if (reply === null) return null; return { diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 50fa903ea1c..017b1922adc 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,12 +1,14 @@ -import { ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; +import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; export const transformBooleanReply = { - 2: (reply: NumberReply<0 | 1>) => reply === 1, + 2: (reply: NumberReply<0 | 1>) => reply as unknown as UnwrapReply === 1, 3: undefined as unknown as () => BooleanReply }; export const transformBooleanArrayReply = { - 2: (reply: ArrayReply>) => reply.map(transformBooleanReply[2]), + 2: (reply: ArrayReply>) => { + return (reply as unknown as UnwrapReply).map(transformBooleanReply[2]); + }, 3: undefined as unknown as () => ArrayReply }; @@ -60,7 +62,7 @@ export const transformNullableDoubleReply = { 2: (reply: BlobStringReply | NullReply) => { if (reply === null) return null; - return transformDoubleReply[2](reply); + return transformDoubleReply[2](reply as BlobStringReply); }, 3: undefined as unknown as () => DoubleReply | NullReply }; @@ -68,10 +70,11 @@ export const transformNullableDoubleReply = { export function transformTuplesReply( reply: ArrayReply ): Record { - const message = Object.create(null); + const inferred = reply as unknown as UnwrapReply, + message = Object.create(null); - for (let i = 0; i < reply.length; i += 2) { - message[reply[i].toString()] = reply[i + 1]; + for (let i = 0; i < inferred.length; i += 2) { + message[inferred[i].toString()] = inferred[i + 1]; } return message; @@ -82,7 +85,8 @@ export type StreamMessageRawReply = TuplesReply<[ message: ArrayReply ]>; -export function transformStreamMessageReply([id, message]: StreamMessageRawReply) { +export function transformStreamMessageReply(reply: StreamMessageRawReply) { + const [id, message] = reply as unknown as UnwrapReply; return { id, message: transformTuplesReply(message) @@ -92,13 +96,11 @@ export function transformStreamMessageReply([id, message]: StreamMessageRawReply export type StreamMessagesRawReply = ArrayReply; export function transformStreamMessagesReply(reply: StreamMessagesRawReply) { - return reply.map(transformStreamMessageReply); + return (reply as unknown as UnwrapReply) + .map(message => transformStreamMessageReply(message)); } -// export type StreamsMessagesReply = Array<{ -// name: RedisArgument; -// messages: StreamMessagesReply; -// }> | null; +// export type StreamsMessagesReply = MapReply; // export function transformStreamsMessagesReply(reply: Array | null): StreamsMessagesReply | null { // if (reply === null) return null; @@ -118,21 +120,25 @@ export type SortedSetSide = 'MIN' | 'MAX'; export const transformSortedSetReply = { 2: (reply: ArrayReply) => { - const members = []; - for (let i = 0; i < reply.length; i += 2) { + const inferred = reply as unknown as UnwrapReply, + members = []; + for (let i = 0; i < inferred.length; i += 2) { members.push({ - value: reply[i], - score: transformDoubleReply[2](reply[i + 1]) + value: inferred[i], + score: transformDoubleReply[2](inferred[i + 1]) }); } return members; }, 3: (reply: ArrayReply>) => { - return reply.map(([value, score]) => ({ - value, - score - })); + return (reply as unknown as UnwrapReply).map(member => { + const [value, score] = member as unknown as UnwrapReply; + return { + value, + score + }; + }); } } diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index 898d3833a52..c0815ebde8a 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -1,67 +1,67 @@ export class AbortError extends Error { - constructor() { - super('The command was aborted'); - } + constructor() { + super('The command was aborted'); + } } export class WatchError extends Error { - constructor() { - super('One (or more) of the watched keys has been changed'); - } + constructor() { + super('One (or more) of the watched keys has been changed'); + } } export class ConnectionTimeoutError extends Error { - constructor() { - super('Connection timeout'); - } + constructor() { + super('Connection timeout'); + } } export class ClientClosedError extends Error { - constructor() { - super('The client is closed'); - } + constructor() { + super('The client is closed'); + } } export class ClientOfflineError extends Error { - constructor() { - super('The client is offline'); - } + constructor() { + super('The client is offline'); + } } export class DisconnectsClientError extends Error { - constructor() { - super('Disconnects client'); - } + constructor() { + super('Disconnects client'); + } } export class SocketClosedUnexpectedlyError extends Error { - constructor() { - super('Socket closed unexpectedly'); - } + constructor() { + super('Socket closed unexpectedly'); + } } export class RootNodesUnavailableError extends Error { - constructor() { - super('All the root nodes are unavailable'); - } + constructor() { + super('All the root nodes are unavailable'); + } } export class ReconnectStrategyError extends Error { - originalError: Error; - socketError: unknown; + originalError: Error; + socketError: unknown; - constructor(originalError: Error, socketError: unknown) { - super(originalError.message); - this.originalError = originalError; - this.socketError = socketError; - } + constructor(originalError: Error, socketError: unknown) { + super(originalError.message); + this.originalError = originalError; + this.socketError = socketError; + } } export class ErrorReply extends Error { - constructor(message: string) { - super(message); - this.stack = undefined; - } + constructor(message: string) { + super(message); + this.stack = undefined; + } } export class SimpleError extends ErrorReply {} From 418f1f9ac848eefdb06538b4992c5431635feb6c Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 13 Jul 2023 14:13:23 -0400 Subject: [PATCH 191/325] fix graph --- packages/graph/lib/commands/QUERY.ts | 4 ++-- packages/graph/lib/commands/SLOWLOG.ts | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index b86382a49d6..c77406ff4f8 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, Command, ArrayReply, BlobStringReply, NumberReply, NullReply, TuplesReply } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, NumberReply, NullReply, TuplesReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; type Headers = ArrayReply; @@ -89,7 +89,7 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, transformArguments: transformQueryArguments.bind(undefined, 'GRAPH.QUERY'), - transformReply(reply: QueryRawReply) { + transformReply(reply: UnwrapReply) { return reply.length === 1 ? { headers: undefined, data: undefined, diff --git a/packages/graph/lib/commands/SLOWLOG.ts b/packages/graph/lib/commands/SLOWLOG.ts index b0271ccae68..52927f6040b 100644 --- a/packages/graph/lib/commands/SLOWLOG.ts +++ b/packages/graph/lib/commands/SLOWLOG.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; type SlowLogRawReply = ArrayReply ({ - timestamp: Number(timestamp), - command, - query, - took: Number(took) - })); + transformReply(reply: UnwrapReply) { + return reply.map(log => { + const [timestamp, command, query, took] = log as unknown as UnwrapReply; + return { + timestamp: Number(timestamp), + command, + query, + took: Number(took) + }; + }); } } as const satisfies Command; From 8501db0243d09775e486fb5cc64a47f03b250e82 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 13 Jul 2023 14:13:47 -0400 Subject: [PATCH 192/325] fix bloom tarball files --- packages/bloom/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index b151421c70a..350d742178d 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -5,7 +5,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" From fdd1978d92b192c2a85cf50e5dbe5c504270750a Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 18 Jul 2023 16:32:45 -0400 Subject: [PATCH 193/325] WIP --- .../lib/ping/local-resp3-buffer-proxy.js | 23 ++ benchmark/lib/ping/local-resp3-buffer.js | 24 ++ benchmark/lib/runner.js | 10 +- docs/v4-to-v5.md | 4 + packages/bloom/lib/commands/bloom/SCANDUMP.ts | 4 +- .../lib/commands/count-min-sketch/INFO.ts | 4 +- .../bloom/lib/commands/cuckoo/SCANDUMP.ts | 4 +- packages/bloom/lib/commands/top-k/INFO.ts | 4 +- .../lib/commands/top-k/LIST_WITHCOUNT.ts | 8 +- packages/json/lib/commands/ARRAPPEND.spec.ts | 10 +- packages/json/lib/commands/ARRAPPEND.ts | 4 +- packages/json/lib/commands/ARRINDEX.spec.ts | 46 ++-- packages/json/lib/commands/ARRINDEX.ts | 22 +- packages/json/lib/commands/ARRINSERT.spec.ts | 10 +- packages/json/lib/commands/ARRINSERT.ts | 20 +- packages/json/lib/commands/ARRLEN.spec.ts | 16 +- packages/json/lib/commands/ARRLEN.ts | 12 +- packages/json/lib/commands/ARRTRIM.spec.ts | 10 +- packages/json/lib/commands/ARRTRIM.ts | 2 +- packages/json/lib/commands/CLEAR.spec.ts | 10 +- packages/json/lib/commands/CLEAR.ts | 10 +- .../json/lib/commands/DEBUG_MEMORY.spec.ts | 6 +- packages/json/lib/commands/DEBUG_MEMORY.ts | 2 +- packages/json/lib/commands/DEL.spec.ts | 10 +- packages/json/lib/commands/DEL.ts | 10 +- packages/json/lib/commands/FORGET.spec.ts | 6 +- packages/json/lib/commands/FORGET.ts | 10 +- packages/json/lib/commands/GET.ts | 62 ++--- packages/json/lib/commands/NUMINCRBY.ts | 9 +- packages/json/lib/commands/OBJKEYS.ts | 4 +- packages/json/lib/commands/OBJLEN.spec.ts | 12 +- packages/json/lib/commands/OBJLEN.ts | 6 +- packages/json/lib/commands/STRAPPEND.ts | 11 + packages/json/lib/commands/STRLEN.spec.ts | 10 +- packages/json/lib/commands/STRLEN.ts | 2 +- packages/json/lib/commands/TOGGLE.spec.ts | 10 +- packages/json/lib/commands/TOGGLE.ts | 6 +- packages/json/lib/commands/index.ts | 143 +++++----- packages/json/lib/test-utils.ts | 20 +- packages/json/test.js | 11 + packages/time-series/lib/commands/GET.ts | 6 +- test.mjs | 260 ------------------ tsconfig.json | 10 +- 43 files changed, 377 insertions(+), 506 deletions(-) create mode 100644 benchmark/lib/ping/local-resp3-buffer-proxy.js create mode 100644 benchmark/lib/ping/local-resp3-buffer.js create mode 100644 packages/json/test.js delete mode 100644 test.mjs diff --git a/benchmark/lib/ping/local-resp3-buffer-proxy.js b/benchmark/lib/ping/local-resp3-buffer-proxy.js new file mode 100644 index 00000000000..2ded38b21ca --- /dev/null +++ b/benchmark/lib/ping/local-resp3-buffer-proxy.js @@ -0,0 +1,23 @@ +import { createClient, RESP_TYPES } from 'redis-local'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + RESP: 3 + }).withTypeMapping({ + [RESP_TYPES.SIMPLE_STRING]: Buffer + }); + + await client.connect(); + + return { + benchmark() { + return client.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/ping/local-resp3-buffer.js b/benchmark/lib/ping/local-resp3-buffer.js new file mode 100644 index 00000000000..624a524ce06 --- /dev/null +++ b/benchmark/lib/ping/local-resp3-buffer.js @@ -0,0 +1,24 @@ +import { createClient, RESP_TYPES } from 'redis-local'; + +export default async (host) => { + const client = createClient({ + socket: { + host + }, + commandOptions: { + [RESP_TYPES.SIMPLE_STRING]: Buffer + }, + RESP: 3 + }); + + await client.connect(); + + return { + benchmark() { + return client.ping(); + }, + teardown() { + return client.disconnect(); + } + }; +}; diff --git a/benchmark/lib/runner.js b/benchmark/lib/runner.js index 3787cbabd1b..fd61a1a1e5c 100644 --- a/benchmark/lib/runner.js +++ b/benchmark/lib/runner.js @@ -73,11 +73,11 @@ const benchmarkStart = process.hrtime.bigint(), json = { // timestamp, operationsPerSecond: times / Number(benchmarkNanoseconds) * 1_000_000_000, - // p0: histogram.getValueAtPercentile(0), - // p50: histogram.getValueAtPercentile(50), - // p95: histogram.getValueAtPercentile(95), - // p99: histogram.getValueAtPercentile(99), - // p100: histogram.getValueAtPercentile(100) + p0: histogram.getValueAtPercentile(0), + p50: histogram.getValueAtPercentile(50), + p95: histogram.getValueAtPercentile(95), + p99: histogram.getValueAtPercentile(99), + p100: histogram.getValueAtPercentile(100) }; console.log(`[${basename(path)}]:`); console.table(json); diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 9536523ae00..66d94fb0a8f 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -177,6 +177,10 @@ Some command arguments/replies have changed to align more closely to data types - `FT.SUGDEL`: [^boolean-to-number] - `TOPK.QUERY`: `Array` -> `Array` - `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` +- `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] +- `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing] +- `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing] +- `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing] [^enum-to-constants]: TODO diff --git a/packages/bloom/lib/commands/bloom/SCANDUMP.ts b/packages/bloom/lib/commands/bloom/SCANDUMP.ts index be5367b872f..588957b1743 100644 --- a/packages/bloom/lib/commands/bloom/SCANDUMP.ts +++ b/packages/bloom/lib/commands/bloom/SCANDUMP.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,7 +6,7 @@ export default { transformArguments(key: RedisArgument, iterator: number) { return ['BF.SCANDUMP', key, iterator.toString()]; }, - transformReply(reply: TuplesReply<[NumberReply, BlobStringReply]>) { + transformReply(reply: UnwrapReply>) { return { iterator: reply[0], chunk: reply[1] diff --git a/packages/bloom/lib/commands/count-min-sketch/INFO.ts b/packages/bloom/lib/commands/count-min-sketch/INFO.ts index e298efd16ad..8ded9b6cd60 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INFO.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INFO.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; export type BfInfoReply = TuplesToMapReply<[ [BlobStringReply<'width'>, NumberReply], @@ -13,7 +13,7 @@ export default { return ['CMS.INFO', key]; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ width: reply[1], depth: reply[3], count: reply[5] diff --git a/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts b/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts index af33315750f..dc076689288 100644 --- a/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts +++ b/packages/bloom/lib/commands/cuckoo/SCANDUMP.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, TuplesReply, NumberReply, BlobStringReply, NullReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,7 +6,7 @@ export default { transformArguments(key: RedisArgument, iterator: number) { return ['CF.SCANDUMP', key, iterator.toString()]; }, - transformReply(reply: TuplesReply<[NumberReply, BlobStringReply | NullReply]>) { + transformReply(reply: UnwrapReply>) { return { iterator: reply[0], chunk: reply[1] diff --git a/packages/bloom/lib/commands/top-k/INFO.ts b/packages/bloom/lib/commands/top-k/INFO.ts index bd694eace2a..6d943b7a02b 100644 --- a/packages/bloom/lib/commands/top-k/INFO.ts +++ b/packages/bloom/lib/commands/top-k/INFO.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; export type TopKInfoReply = TuplesToMapReply<[ [BlobStringReply<'k'>, NumberReply], @@ -14,7 +14,7 @@ export default { return ['TOPK.INFO', key]; }, transformReply: { - 2: (reply: Resp2Reply) => ({ + 2: (reply: UnwrapReply>) => ({ k: reply[1], width: reply[3], depth: reply[5], diff --git a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts index a135e5db46f..a4a5249c5be 100644 --- a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts +++ b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, SimpleStringReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, SimpleStringReply, NumberReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,11 +6,11 @@ export default { transformArguments(key: RedisArgument) { return ['TOPK.LIST', key, 'WITHCOUNT']; }, - transformReply(rawReply: ArrayReply) { - const reply = [] as unknown as ArrayReply<{ + transformReply(rawReply: UnwrapReply>) { + const reply: Array<{ item: SimpleStringReply; count: NumberReply; - }>; + }> = []; for (let i = 0; i < rawReply.length; i++) { reply.push({ diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts index cd2001d5ea5..991185dd924 100644 --- a/packages/json/lib/commands/ARRAPPEND.spec.ts +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -20,11 +20,11 @@ describe('ARRAPPEND', () => { }); testUtils.testWithClient('client.json.arrAppend', async client => { - await client.json.set('key', '$', []); + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrAppend('key', '$', 1) + ]); - assert.deepEqual( - await client.json.arrAppend('key', '$', 1), - [1] - ); + assert.deepEqual(reply, [1]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRAPPEND.ts b/packages/json/lib/commands/ARRAPPEND.ts index 934a534cfcd..7f5b49eead2 100644 --- a/packages/json/lib/commands/ARRAPPEND.ts +++ b/packages/json/lib/commands/ARRAPPEND.ts @@ -1,5 +1,5 @@ import { RedisJSON, transformRedisJsonArgument } from '.'; -import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -13,5 +13,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/ARRINDEX.spec.ts b/packages/json/lib/commands/ARRINDEX.spec.ts index 290d0a237f6..fc65dbdf0fa 100644 --- a/packages/json/lib/commands/ARRINDEX.spec.ts +++ b/packages/json/lib/commands/ARRINDEX.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRINDEX from './ARRINDEX'; -describe('ARRINDEX', () => { +describe('JSON.ARRINDEX', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( @@ -10,28 +10,40 @@ describe('ARRINDEX', () => { ['JSON.ARRINDEX', 'key', '$', '"json"'] ); }); + - it('with start', () => { - assert.deepEqual( - ARRINDEX.transformArguments('key', '$', 'json', 1), - ['JSON.ARRINDEX', 'key', '$', '"json"', '1'] - ); - }); + describe('with range', () => { + it('start only', () => { + assert.deepEqual( + ARRINDEX.transformArguments('key', '$', 'json', { + range: { + start: 0 + } + }), + ['JSON.ARRINDEX', 'key', '$', '"json"', '0'] + ); + }); - it('with start, end', () => { - assert.deepEqual( - ARRINDEX.transformArguments('key', '$', 'json', 1, 2), - ['JSON.ARRINDEX', 'key', '$', '"json"', '1', '2'] - ); + it('with start and stop', () => { + assert.deepEqual( + ARRINDEX.transformArguments('key', '$', 'json', { + range: { + start: 0, + stop: 1 + } + }), + ['JSON.ARRINDEX', 'key', '$', '"json"', '0', '1'] + ); + }); }); }); testUtils.testWithClient('client.json.arrIndex', async client => { - await client.json.set('key', '$', []); + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrIndex('key', '$', 'json') + ]); - assert.deepEqual( - await client.json.arrIndex('key', '$', 'json'), - [-1] - ); + assert.deepEqual(reply, [-1]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRINDEX.ts b/packages/json/lib/commands/ARRINDEX.ts index f085e1afb93..77c54b92522 100644 --- a/packages/json/lib/commands/ARRINDEX.ts +++ b/packages/json/lib/commands/ARRINDEX.ts @@ -1,6 +1,13 @@ -import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; +export interface JsonArrIndexOptions { + range?: { + start: number; + stop?: number; + }; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, @@ -8,20 +15,19 @@ export default { key: RedisArgument, path: RedisArgument, json: RedisJSON, - start?: number, - stop?: number + options?: JsonArrIndexOptions ) { const args = ['JSON.ARRINDEX', key, path, transformRedisJsonArgument(json)]; - if (start !== undefined && start !== null) { - args.push(start.toString()); + if (options?.range) { + args.push(options.range.start.toString()); - if (stop !== undefined && stop !== null) { - args.push(stop.toString()); + if (options.range.stop !== undefined) { + args.push(options.range.stop.toString()); } } return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts index 8bf3d0d633e..e0815935396 100644 --- a/packages/json/lib/commands/ARRINSERT.spec.ts +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -20,11 +20,11 @@ describe('JSON.ARRINSERT', () => { }); testUtils.testWithClient('client.json.arrInsert', async client => { - await client.json.set('key', '$', []); + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrInsert('key', '$', 0, 'json') + ]); - assert.deepEqual( - await client.json.arrInsert('key', '$', 0, 'json'), - [1] - ); + assert.deepEqual(reply, [1]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRINSERT.ts b/packages/json/lib/commands/ARRINSERT.ts index 66663c646fa..da2a3ed440a 100644 --- a/packages/json/lib/commands/ARRINSERT.ts +++ b/packages/json/lib/commands/ARRINSERT.ts @@ -1,11 +1,23 @@ -import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path: RedisArgument, index: number, ...jsons: Array) { - const args = ['JSON.ARRINSERT', key, path, index.toString()]; + transformArguments( + key: RedisArgument, + path: RedisArgument, + index: number, + json: RedisJSON, + ...jsons: Array + ) { + const args = [ + 'JSON.ARRINSERT', + key, + path, + index.toString(), + transformRedisJsonArgument(json) + ]; for (const json of jsons) { args.push(transformRedisJsonArgument(json)); @@ -13,5 +25,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts index 803b108ddea..ec2e0e46f5e 100644 --- a/packages/json/lib/commands/ARRLEN.spec.ts +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -4,7 +4,7 @@ import ARRLEN from './ARRLEN'; describe('JSON.ARRLEN', () => { describe('transformArguments', () => { - it('without path', () => { + it('simple', () => { assert.deepEqual( ARRLEN.transformArguments('key'), ['JSON.ARRLEN', 'key'] @@ -13,18 +13,20 @@ describe('JSON.ARRLEN', () => { it('with path', () => { assert.deepEqual( - ARRLEN.transformArguments('key', '$'), + ARRLEN.transformArguments('key', { + path: '$' + }), ['JSON.ARRLEN', 'key', '$'] ); }); }); testUtils.testWithClient('client.json.arrLen', async client => { - await client.json.set('key', '$', []); + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrLen('key') + ]); - assert.deepEqual( - await client.json.arrLen('key', '$'), - [0] - ); + assert.deepEqual(reply, 0); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRLEN.ts b/packages/json/lib/commands/ARRLEN.ts index 26155a109db..5763b893fa3 100644 --- a/packages/json/lib/commands/ARRLEN.ts +++ b/packages/json/lib/commands/ARRLEN.ts @@ -1,16 +1,20 @@ import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonArrLenOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonArrLenOptions) { const args = ['JSON.ARRLEN', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/ARRTRIM.spec.ts b/packages/json/lib/commands/ARRTRIM.spec.ts index 241c1b509b8..03cd80a0e7c 100644 --- a/packages/json/lib/commands/ARRTRIM.spec.ts +++ b/packages/json/lib/commands/ARRTRIM.spec.ts @@ -11,11 +11,11 @@ describe('JSON.ARRTRIM', () => { }); testUtils.testWithClient('client.json.arrTrim', async client => { - await client.json.set('key', '$', []); + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrTrim('key', '$', 0, 1) + ]); - assert.deepEqual( - await client.json.arrTrim('key', '$', 0, 1), - [0] - ); + assert.deepEqual(reply, [0]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRTRIM.ts b/packages/json/lib/commands/ARRTRIM.ts index a3de83fff10..ab31f159491 100644 --- a/packages/json/lib/commands/ARRTRIM.ts +++ b/packages/json/lib/commands/ARRTRIM.ts @@ -6,5 +6,5 @@ export default { transformArguments(key: RedisArgument, path: RedisArgument, start: number, stop: number) { return ['JSON.ARRTRIM', key, path, start.toString(), stop.toString()]; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/CLEAR.spec.ts b/packages/json/lib/commands/CLEAR.spec.ts index 5b53b77c3c3..e9ada575a8e 100644 --- a/packages/json/lib/commands/CLEAR.spec.ts +++ b/packages/json/lib/commands/CLEAR.spec.ts @@ -4,17 +4,19 @@ import CLEAR from './CLEAR'; describe('JSON.CLEAR', () => { describe('transformArguments', () => { - it('key', () => { + it('simple', () => { assert.deepEqual( CLEAR.transformArguments('key'), ['JSON.CLEAR', 'key'] ); }); - it('key, path', () => { + it('with path', () => { assert.deepEqual( - CLEAR.transformArguments('key', '$.path'), - ['JSON.CLEAR', 'key', '$.path'] + CLEAR.transformArguments('key', { + path: '$' + }), + ['JSON.CLEAR', 'key', '$'] ); }); }); diff --git a/packages/json/lib/commands/CLEAR.ts b/packages/json/lib/commands/CLEAR.ts index a5730f5b4e6..186ce296bce 100644 --- a/packages/json/lib/commands/CLEAR.ts +++ b/packages/json/lib/commands/CLEAR.ts @@ -1,12 +1,18 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonClearOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonClearOptions) { const args = ['JSON.CLEAR', key]; - if (path) args.push(path); + if (options?.path) { + args.push(options.path); + } return args; }, diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts index 51b6f7e2da8..b0e969ab172 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEBUG_MEMORY from './DEBUG_MEMORY'; -describe('DEBUG MEMORY', () => { +describe('JSON.DEBUG MEMORY', () => { describe('transformArguments', () => { it('without path', () => { assert.deepEqual( @@ -19,10 +19,10 @@ describe('DEBUG MEMORY', () => { }); }); - testUtils.testWithClient('client.json.arrTrim', async client => { + testUtils.testWithClient('client.json.debugMemory', async client => { assert.deepEqual( await client.json.debugMemory('key', '$'), - [] + 0 ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts index 3b1c4460373..765d2da3579 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, ArrayReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 2, diff --git a/packages/json/lib/commands/DEL.spec.ts b/packages/json/lib/commands/DEL.spec.ts index 4d67d7cb3e0..590f70d7889 100644 --- a/packages/json/lib/commands/DEL.spec.ts +++ b/packages/json/lib/commands/DEL.spec.ts @@ -2,18 +2,20 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEL from './DEL'; -describe('DEL', () => { +describe('JSON.DEL', () => { describe('transformArguments', () => { - it('key', () => { + it('simple', () => { assert.deepEqual( DEL.transformArguments('key'), ['JSON.DEL', 'key'] ); }); - it('key, path', () => { + it('with path', () => { assert.deepEqual( - DEL.transformArguments('key', '$.path'), + DEL.transformArguments('key', { + path: '$.path' + }), ['JSON.DEL', 'key', '$.path'] ); }); diff --git a/packages/json/lib/commands/DEL.ts b/packages/json/lib/commands/DEL.ts index 922fc7a7832..13632840c6a 100644 --- a/packages/json/lib/commands/DEL.ts +++ b/packages/json/lib/commands/DEL.ts @@ -1,13 +1,17 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonDelOptions { + path?: RedisArgument +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonDelOptions) { const args = ['JSON.DEL', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/FORGET.spec.ts b/packages/json/lib/commands/FORGET.spec.ts index b0e19615064..ec9f2221eb7 100644 --- a/packages/json/lib/commands/FORGET.spec.ts +++ b/packages/json/lib/commands/FORGET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import FORGET from './FORGET'; -describe('FORGET', () => { +describe('JSON.FORGET', () => { describe('transformArguments', () => { it('key', () => { assert.deepEqual( @@ -13,7 +13,9 @@ describe('FORGET', () => { it('key, path', () => { assert.deepEqual( - FORGET.transformArguments('key', '$.path'), + FORGET.transformArguments('key', { + path: '$.path' + }), ['JSON.FORGET', 'key', '$.path'] ); }); diff --git a/packages/json/lib/commands/FORGET.ts b/packages/json/lib/commands/FORGET.ts index b55015e9488..1820f8f2024 100644 --- a/packages/json/lib/commands/FORGET.ts +++ b/packages/json/lib/commands/FORGET.ts @@ -1,13 +1,17 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonForgetOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonForgetOptions) { const args = ['JSON.FORGET', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/GET.ts b/packages/json/lib/commands/GET.ts index 107f9dd9750..445f0b3eaef 100644 --- a/packages/json/lib/commands/GET.ts +++ b/packages/json/lib/commands/GET.ts @@ -1,42 +1,42 @@ -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +// import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +// import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -interface GetOptions { - path?: string | Array; - INDENT?: string; - NEWLINE?: string; - SPACE?: string; - NOESCAPE?: true; -} +// interface GetOptions { +// path?: string | Array; +// INDENT?: string; +// NEWLINE?: string; +// SPACE?: string; +// NOESCAPE?: true; +// } -export function transformArguments(key: string, options?: GetOptions): RedisCommandArguments { - let args: RedisCommandArguments = ['JSON.GET', key]; +// export function transformArguments(key: string, options?: GetOptions): RedisCommandArguments { +// let args: RedisCommandArguments = ['JSON.GET', key]; - if (options?.path) { - args = pushVariadicArguments(args, options.path); - } +// if (options?.path) { +// args = pushVariadicArguments(args, options.path); +// } - if (options?.INDENT) { - args.push('INDENT', options.INDENT); - } +// if (options?.INDENT) { +// args.push('INDENT', options.INDENT); +// } - if (options?.NEWLINE) { - args.push('NEWLINE', options.NEWLINE); - } +// if (options?.NEWLINE) { +// args.push('NEWLINE', options.NEWLINE); +// } - if (options?.SPACE) { - args.push('SPACE', options.SPACE); - } +// if (options?.SPACE) { +// args.push('SPACE', options.SPACE); +// } - if (options?.NOESCAPE) { - args.push('NOESCAPE'); - } +// if (options?.NOESCAPE) { +// args.push('NOESCAPE'); +// } - return args; -} +// return args; +// } -export { transformRedisJsonNullReply as transformReply } from '.'; +// export { transformRedisJsonNullReply as transformReply } from '.'; diff --git a/packages/json/lib/commands/NUMINCRBY.ts b/packages/json/lib/commands/NUMINCRBY.ts index d025c249dd0..68c1de2b0bb 100644 --- a/packages/json/lib/commands/NUMINCRBY.ts +++ b/packages/json/lib/commands/NUMINCRBY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, Command, ArrayReply, NumberReply, DoubleReply, NullReply } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, DoubleReply, NullReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,5 +6,10 @@ export default { transformArguments(key: RedisArgument, path: RedisArgument, by: number) { return ['JSON.NUMINCRBY', key, path, by.toString()]; }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: { + 2: (reply: UnwrapReply) => { + return JSON.parse(reply.toString()) as number | Array; + }, + 3: undefined as unknown as () => NumberReply | DoubleReply | NullReply + } } as const satisfies Command; diff --git a/packages/json/lib/commands/OBJKEYS.ts b/packages/json/lib/commands/OBJKEYS.ts index e9541bdb524..7b4d9d963d2 100644 --- a/packages/json/lib/commands/OBJKEYS.ts +++ b/packages/json/lib/commands/OBJKEYS.ts @@ -1,7 +1,5 @@ import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; -type ReplyItem = ArrayReply | NullReply; - export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, @@ -14,5 +12,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => ReplyItem | ArrayReply + transformReply: undefined as unknown as () => ArrayReply | ArrayReply | NullReply> } as const satisfies Command; diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts index b2eed67c525..edea703aa11 100644 --- a/packages/json/lib/commands/OBJLEN.spec.ts +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -19,10 +19,10 @@ describe('JSON.OBJLEN', () => { }); }); - // testUtils.testWithClient('client.json.objLen', async client => { - // assert.equal( - // await client.json.objLen('key', '$'), - // [null] - // ); - // }, GLOBAL.SERVERS.OPEN); + 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 index 4063feea397..45b8855561f 100644 --- a/packages/json/lib/commands/OBJLEN.ts +++ b/packages/json/lib/commands/OBJLEN.ts @@ -1,8 +1,8 @@ -import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.OBJLEN', key]; @@ -12,5 +12,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/STRAPPEND.ts b/packages/json/lib/commands/STRAPPEND.ts index 9f3ef316fd0..3f8e98e6bc1 100644 --- a/packages/json/lib/commands/STRAPPEND.ts +++ b/packages/json/lib/commands/STRAPPEND.ts @@ -19,3 +19,14 @@ // } // export declare function transformReply(): number | Array; + +import { SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments() { + return ['JSON.STRAPPEND']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts index f05a45cf953..687a55553e9 100644 --- a/packages/json/lib/commands/STRLEN.spec.ts +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -20,11 +20,11 @@ describe('JSON.STRLEN', () => { }); testUtils.testWithClient('client.json.strLen', async client => { - await client.json.set('key', '$', ''); + const [, reply] = await Promise.all([ + client.json.set('key', '$', ''), + client.json.strLen('key', '$') + ]); - assert.deepEqual( - await client.json.strLen('key', '$'), - [0] - ); + assert.deepEqual(reply, [0]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/STRLEN.ts b/packages/json/lib/commands/STRLEN.ts index a2bab3b1f49..256414fb912 100644 --- a/packages/json/lib/commands/STRLEN.ts +++ b/packages/json/lib/commands/STRLEN.ts @@ -12,5 +12,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts index 7ffb5094894..3ce922a7b82 100644 --- a/packages/json/lib/commands/TOGGLE.spec.ts +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -20,11 +20,11 @@ describe('JSON.TOGGLE', () => { }); testUtils.testWithClient('client.json.toggle', async client => { - await client.json.set('key', '$', ''); + const [, reply] = await Promise.all([ + client.json.set('key', '$', ''), + client.json.toggle('key', '$') + ]); - assert.deepEqual( - await client.json.toggle('key', '$'), - [0] - ); + assert.deepEqual(reply, [0]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/TOGGLE.ts b/packages/json/lib/commands/TOGGLE.ts index 45b632952a6..85e5e479aae 100644 --- a/packages/json/lib/commands/TOGGLE.ts +++ b/packages/json/lib/commands/TOGGLE.ts @@ -1,12 +1,14 @@ import { RedisArgument, ArrayReply, NumberReply, NullReply, Command, } from '@redis/client/dist/lib/RESP/types'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, transformArguments(key: RedisArgument, path?: RedisArgument) { const args = ['JSON.TOGGLE', key] - if (path) args.push(path); + if (path) { + args.push(path); + } return args; }, diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index 218462f4dbf..4405f1b423c 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -1,93 +1,96 @@ -import * as ARRAPPEND from './ARRAPPEND'; -import * as ARRINDEX from './ARRINDEX'; -import * as ARRINSERT from './ARRINSERT'; +import ARRAPPEND from './ARRAPPEND'; +import ARRINDEX from './ARRINDEX'; +import ARRINSERT from './ARRINSERT'; import CLEAR from './CLEAR'; -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'; +import ARRLEN from './ARRLEN'; +// import ARRPOP from './ARRPOP'; +import ARRTRIM from './ARRTRIM'; +import DEBUG_MEMORY from './DEBUG_MEMORY'; +import DEL from './DEL'; +import FORGET from './FORGET'; +// import GET from './GET'; +// import MGET from './MGET'; +import NUMINCRBY from './NUMINCRBY'; +import NUMMULTBY from './NUMMULTBY'; +import OBJKEYS from './OBJKEYS'; +import OBJLEN from './OBJLEN'; +// import RESP from './RESP'; +import SET from './SET'; +import STRAPPEND from './STRAPPEND'; +import STRLEN from './STRLEN'; +import TOGGLE from './TOGGLE'; +// import TYPE from './TYPE'; export default { - ARRAPPEND, - arrAppend: ARRAPPEND, - ARRINDEX, - arrIndex: ARRINDEX, - ARRINSERT, - arrInsert: ARRINSERT, - CLEAR, - clear: CLEAR, - 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 + ARRAPPEND, + arrAppend: ARRAPPEND, + ARRINDEX, + arrIndex: ARRINDEX, + ARRINSERT, + arrInsert: ARRINSERT, + CLEAR, + clear: CLEAR, + 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, + TOGGLE, + toggle: TOGGLE, + // TYPE, + // type: TYPE }; // https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RedisJSONArray extends Array {} +interface RedisJSONArray extends Array { } interface RedisJSONObject { - [key: string]: RedisJSON; - [key: number]: RedisJSON; + [key: string]: RedisJSON; + [key: number]: RedisJSON; } export type RedisJSON = null | boolean | number | string | Date | RedisJSONArray | RedisJSONObject; export function transformRedisJsonArgument(json: RedisJSON): string { - return JSON.stringify(json); + return JSON.stringify(json); } export function transformRedisJsonReply(json: string): RedisJSON { - return JSON.parse(json); + return JSON.parse(json); } export function transformRedisJsonNullReply(json: string | null): RedisJSON | null { - if (json === null) return null; + if (json === null) return null; - return transformRedisJsonReply(json); + return transformRedisJsonReply(json); } export function transformNumbersReply(reply: string): number | Array { - return JSON.parse(reply); + return JSON.parse(reply); } diff --git a/packages/json/lib/test-utils.ts b/packages/json/lib/test-utils.ts index f4c4e4eb201..8c598e90906 100644 --- a/packages/json/lib/test-utils.ts +++ b/packages/json/lib/test-utils.ts @@ -2,19 +2,19 @@ import TestUtils from '@redis/test-utils'; import RedisJSON from '.'; export default new TestUtils({ - dockerImageName: 'redislabs/rejson', - dockerImageVersionArgument: 'rejson-version' + dockerImageName: 'redislabs/rejson', + dockerImageVersionArgument: 'rejson-version' }); export const GLOBAL = { - SERVERS: { - OPEN: { - serverArguments: ['--loadmodule /usr/lib/redis/modules/rejson.so'], - clientOptions: { - modules: { - json: RedisJSON - } - } + SERVERS: { + OPEN: { + serverArguments: ['--loadmodule /usr/lib/redis/modules/rejson.so'], + clientOptions: { + modules: { + json: RedisJSON } + } } + } }; diff --git a/packages/json/test.js b/packages/json/test.js new file mode 100644 index 00000000000..f9845cc4304 --- /dev/null +++ b/packages/json/test.js @@ -0,0 +1,11 @@ +import { createClient } from '@redis/client'; +import RedisJSON from '.'; + +const client = createClient({ + modules: { + json: RedisJSON, + JSON: RedisJSON + } +}); + +client.JSON. \ No newline at end of file diff --git a/packages/time-series/lib/commands/GET.ts b/packages/time-series/lib/commands/GET.ts index 514b51edd2c..78e5e3bced0 100644 --- a/packages/time-series/lib/commands/GET.ts +++ b/packages/time-series/lib/commands/GET.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, TuplesReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; export interface TsGetOptions { LATEST?: boolean; @@ -19,13 +19,13 @@ export default { return args; }, transformReply: { - 2(reply: Resp2Reply) { + 2(reply: UnwrapReply>) { return reply.length === 0 ? null : { timestamp: reply[0], value: Number(reply[1]) }; }, - 3(reply: TsGetReply) { + 3(reply: UnwrapReply) { return reply.length === 0 ? null : { timestamp: reply[0], value: reply[1] diff --git a/test.mjs b/test.mjs deleted file mode 100644 index 6aa12b67e51..00000000000 --- a/test.mjs +++ /dev/null @@ -1,260 +0,0 @@ -// // // import { createClient } from './benchmark/node_modules/@redis/client/dist/index.js'; -// // // import Redis from './benchmark/node_modules/ioredis/built/index.js'; -// // // import { setTimeout } from 'node:timers/promises'; - -// // // const client = createClient(); -// // // client.on('error', err => console.error(err)); - -// // // await client.connect(); - -// // // const io = new Redis({ -// // // lazyConnect: true, -// // // enableAutoPipelining: true -// // // }); -// // // await io.connect(); - -// // // const TIMES = 1_000; - -// // // while (true) { -// // // await benchmark('redis', () => { -// // // const promises = []; -// // // for (let i = 0; i < TIMES; i++) { -// // // promises.push(client.ping()); -// // // } - -// // // return Promise.all(promises); -// // // }); - -// // // await benchmark('ioredis', () => { -// // // const promises = []; -// // // for (let i = 0; i < TIMES; i++) { -// // // promises.push(io.ping()); -// // // } - -// // // return Promise.all(promises); -// // // }); -// // // } - -// // // async function benchmark(name, fn) { -// // // const start = process.hrtime.bigint(); - -// // // await fn(); - -// // // const took = Number(process.hrtime.bigint() - start); -// // // console.log(took, name); - -// // // console.log('Sleep'); -// // // await setTimeout(1000); -// // // console.log('Continue'); -// // // } - - // import Redis from 'ioredis'; - - // const cluster = new Redis.Cluster([{ - // port: 6379, - // host: "127.0.0.1", - // }]); - - // setInterval(() => { - // let i = 0; - // cluster.on('node-', () => { - // if (++3) { - // cluster.refreshSlotsCache(err => { - // console.log('done', err); - // }); - // i = 0; - // } - // }) - - // }, 5000); - -// import { createCluster } from './packages/client/dist/index.js'; -// import { setTimeout } from 'node:timers/promises'; - -// const cluster = createCluster({ -// rootNodes: [{}] -// }); - -// cluster.on('error', err => console.error(err)); - -// await cluster.connect(); - -// console.log( -// await Promise.all([ -// cluster.ping(), -// cluster.ping(), -// cluster.set('1', '1'), -// cluster.get('1'), -// cluster.get('2'), -// cluster.multi().ping().ping().get('a').set('a', 'b').get('a').execTyped() -// // cluster -// ]) -// ); - -// import { createClient } from './packages/client/dist/index.js'; - -// const client = createClient(); - -// client.a(); - -// client.on('error', err => console.error('Redis Client Error', err)); - -// await client.connect(); - -// const legacy = client.legacy(); - -// console.log( -// await client.multi() -// .ping() -// .ping() -// .aaa() -// .exec(), -// await client.multi() -// .ping() -// .ping() -// .execTyped() -// ); - -// legacy.multi() -// .ping() -// .ping() -// .sendCommand(['PING', 'LEIBALE']) -// .exec((err, replies) => { -// console.log(err, replies); -// client.destroy(); -// }) - -// for (let i = 0; i < 100; i++) { -// const promises = []; -// for (let j = 0; j < 5; j++) { -// promises.push(client.sendCommand(['PING'])); -// } - -// console.log( -// await Promise.all(promises) -// ); -// } - -// // // const I = 100, -// // // J = 1_000; - -// // // for (let i = 0; i < I; i++) { -// // // const promises = new Array(J); -// // // for (let j = 0; j < J; j++) { -// // // promises[j] = client.ping(); -// // // } - -// // // await Promise.all(promises); -// // // } - -// import { writeFile } from 'node:fs/promises'; - -// function gen() { - -// const lines = [ -// `// ${new Date().toJSON()}`, -// 'import * as B from "./b";', -// 'export default {' -// ]; - -// for (let i = 0; i < 40000; i++) { -// lines.push(` ${i}: B,`); -// } - -// lines.push('} as const;'); - -// return lines.join('\n'); -// } - -// await writeFile('./a.ts', gen()); - -// import { createClient } from '@redis/client'; - -// console.log(new Date().toJSON()); - -// const client = createClient({ -// url: 'redis://default:VugDBHGYAectnTj25wmCCAuhPOu3xkhk@redis-11344.c240.us-east-1-3.ec2.cloud.redislabs.com:11344' -// }); - -// client.on('error', err => console.error('11111', err, new Date().toJSON())); - -// await client.connect(); - -// const client2 = createClient({ -// url: 'redis://default:VugDBHGYAectnTj25wmCCAuhPOu3xkhk@redis-11344.c240.us-east-1-3.ec2.cloud.redislabs.com:11344', -// pingInterval: 60000 -// }); - -// client2.on('error', err => console.error('22222', err, new Date().toJSON())); - -// await client2.connect(); - -import { createClient, RESP_TYPES } from '@redis/client'; - -const client = createClient({ - RESP: 3, - name: 'test', - commandOptions: { - asap: true, - typeMapping: { - [RESP_TYPES.BLOB_STRING]: Buffer - } - } -}); - -client.on('error', err => console.error(err)); - -await client.connect(); - - -const controller = new AbortController(); - -try { - const promise = client.withAbortSignal(controller.signal).set('key', 'value'); - controller.abort(); - console.log('!!', await promise); -} catch (err) { - // AbortError -} - -await Promise.all([ - client.ping('a'), - client.ping('b') -]) - -const asap = client.asap(); - -await Promise.all([ - asap.ping('aa'), - asap.ping('bb') -]) - -await client.set('another', 'value'); - -for await (const keys of client.scanIterator()) { - console.log(keys); -} - -// console.log( -// await Promise.all([ -// client.get('key'), -// client.asap().get('a'), -// client.withTypeMapping({}).get('key') -// ]) -// ); - -// await client.set('key', 'value'); - -// const controller = new AbortController(); - -// controller.abort(); - -// client.withAbortSignal(controller.signal).get('key') -// .then(a => console.log(a)) -// .catch(err => { -// console.error(err); -// }); - -// controller.abort(); - -// client.destroy(); diff --git a/tsconfig.json b/tsconfig.json index 3c2207d4ffe..c65451d427b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,7 @@ "path": "./packages/test-utils" }, { "path": "./packages/bloom" - }], - "todo": [{ + }, { "path": "./packages/graph" }, { "path": "./packages/json" @@ -16,10 +15,5 @@ "path": "./packages/time-series" }, { "path": "./packages/redis" - }], - "typedocOptions": { - "entryPoints": ["./packages/client"], - "entryPointStrategy": "packages", - "out": "./documentation" - } + }] } \ No newline at end of file From c9dae346a295030adc10c46d1b7bf26bc4b46bc5 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 19 Jul 2023 13:59:44 -0400 Subject: [PATCH 194/325] ref #2565 - handle null message in `XAUTOCLAIM` --- .../client/lib/commands/XAUTOCLAIM.spec.ts | 23 +++++++++++++------ packages/client/lib/commands/XAUTOCLAIM.ts | 10 ++++---- .../lib/commands/generic-transformers.ts | 6 ++++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index bb4b1d65942..5efdc4f1154 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import XAUTOCLAIM from './XAUTOCLAIM'; -describe('XAUTOCLAIM', () => { +describe.only('XAUTOCLAIM', () => { testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { @@ -31,26 +31,35 @@ describe('XAUTOCLAIM', () => { } }); - const [, , id, , reply] = await Promise.all([ + const [, , id1, id2, , , reply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), client.xGroupCreateConsumer('key', 'group', 'consumer'), client.xAdd('key', '*', message), + client.xAdd('key', '*', message), client.xReadGroup('group', 'consumer', { key: 'key', id: '>' }), + client.xTrim('key', 'MAXLEN', 1), client.xAutoClaim('key', 'group', 'consumer', 0, '0-0') ]); assert.deepEqual(reply, { nextId: '0-0', - messages: [{ - id, - message - }], - deletedMessages: testUtils.isVersionGreaterThan([7, 0]) ? [] : undefined + ...(testUtils.isVersionGreaterThan([7, 0]) ? { + messages: [{ + id: id2, + message + }], + deletedMessages: [id1] + } : { + messages: [null, { + id: id2, + message + }] + }) }); }, { client: GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts index 4c78aa12312..1fcd1cf32d5 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.ts @@ -1,5 +1,5 @@ -import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; -import { StreamMessagesRawReply, transformStreamMessagesReply } from './generic-transformers'; +import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, NullReply, UnwrapReply, Command } from '../RESP/types'; +import { StreamMessageRawReply, isNullReply, transformStreamMessageReply } from './generic-transformers'; export interface XAutoClaimOptions { COUNT?: number; @@ -7,7 +7,7 @@ export interface XAutoClaimOptions { export type XAutoClaimRawReply = TuplesReply<[ nextId: BlobStringReply, - messages: StreamMessagesRawReply, + messages: ArrayReply, deletedMessages: ArrayReply ]>; @@ -40,7 +40,9 @@ export default { transformReply(reply: UnwrapReply) { return { nextId: reply[0], - messages: transformStreamMessagesReply(reply[1]), + messages: (reply[1] as unknown as UnwrapReply).map(message => { + return isNullReply(message) ? null : transformStreamMessageReply(message); + }), deletedMessages: reply[2] }; } diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 017b1922adc..3c51100cc73 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,4 +1,8 @@ -import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; +import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply, RespType } from '../RESP/types'; + +export function isNullReply(reply: unknown): reply is NullReply { + return reply === null; +} export const transformBooleanReply = { 2: (reply: NumberReply<0 | 1>) => reply as unknown as UnwrapReply === 1, From c02de006db4bebd125fd5098b2bf0f3983f2c9a7 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 19 Jul 2023 14:22:04 -0400 Subject: [PATCH 195/325] remove .only --- packages/client/lib/commands/XAUTOCLAIM.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index 5efdc4f1154..3e0ddd710ed 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import XAUTOCLAIM from './XAUTOCLAIM'; -describe.only('XAUTOCLAIM', () => { +describe('XAUTOCLAIM', () => { testUtils.isVersionGreaterThanHook([6, 2]); describe('transformArguments', () => { From 51a1000603c939c41619aa18ca97d128fae5d636 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 19 Jul 2023 15:11:29 -0400 Subject: [PATCH 196/325] fix XAUTOCLAIM test for <7.0 --- packages/client/lib/commands/XAUTOCLAIM.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index 3e0ddd710ed..229e71513fd 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -58,7 +58,8 @@ describe('XAUTOCLAIM', () => { messages: [null, { id: id2, message - }] + }], + deletedMessages: undefined }) }); }, { From 8369448d05b2782d766bc30326f3423c319de504 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 20 Jul 2023 16:04:51 -0400 Subject: [PATCH 197/325] ref #2565 - fix `X[AUTO]CLAIM` --- .../client/lib/commands/XAUTOCLAIM.spec.ts | 3 +-- packages/client/lib/commands/XAUTOCLAIM.ts | 8 +++--- packages/client/lib/commands/XCLAIM.spec.ts | 27 ++++++++++++++++--- packages/client/lib/commands/XCLAIM.ts | 8 +++--- packages/client/lib/commands/XINFO_STREAM.ts | 23 +++++++++++----- packages/client/lib/commands/XRANGE.ts | 8 +++--- .../lib/commands/generic-transformers.ts | 24 ++++------------- 7 files changed, 59 insertions(+), 42 deletions(-) diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index 229e71513fd..bf3b11c6c00 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -31,11 +31,10 @@ describe('XAUTOCLAIM', () => { } }); - const [, , id1, id2, , , reply] = await Promise.all([ + const [, id1, id2, , , reply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), - client.xGroupCreateConsumer('key', 'group', 'consumer'), client.xAdd('key', '*', message), client.xAdd('key', '*', message), client.xReadGroup('group', 'consumer', { diff --git a/packages/client/lib/commands/XAUTOCLAIM.ts b/packages/client/lib/commands/XAUTOCLAIM.ts index 1fcd1cf32d5..57ad010991d 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.ts @@ -1,5 +1,5 @@ import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, NullReply, UnwrapReply, Command } from '../RESP/types'; -import { StreamMessageRawReply, isNullReply, transformStreamMessageReply } from './generic-transformers'; +import { StreamMessageReply, transformStreamMessageNullReply } from './generic-transformers'; export interface XAutoClaimOptions { COUNT?: number; @@ -7,7 +7,7 @@ export interface XAutoClaimOptions { export type XAutoClaimRawReply = TuplesReply<[ nextId: BlobStringReply, - messages: ArrayReply, + messages: ArrayReply, deletedMessages: ArrayReply ]>; @@ -40,9 +40,7 @@ export default { transformReply(reply: UnwrapReply) { return { nextId: reply[0], - messages: (reply[1] as unknown as UnwrapReply).map(message => { - return isNullReply(message) ? null : transformStreamMessageReply(message); - }), + messages: (reply[1] as unknown as UnwrapReply).map(transformStreamMessageNullReply), deletedMessages: reply[2] }; } diff --git a/packages/client/lib/commands/XCLAIM.spec.ts b/packages/client/lib/commands/XCLAIM.spec.ts index ffe2deeaaeb..48546eecdbe 100644 --- a/packages/client/lib/commands/XCLAIM.spec.ts +++ b/packages/client/lib/commands/XCLAIM.spec.ts @@ -89,16 +89,35 @@ describe('XCLAIM', () => { }); }); - // TODO: test with messages testUtils.testAll('xClaim', async client => { - const [, reply] = await Promise.all([ + const message = Object.create(null, { + field: { + value: 'value', + enumerable: true + } + }); + + const [, , , , , reply] = await Promise.all([ client.xGroupCreate('key', 'group', '$', { MKSTREAM: true }), - client.xClaim('key', 'group', 'consumer', 1, '0-0') + client.xAdd('key', '1-0', message), + client.xAdd('key', '2-0', message), + client.xReadGroup('group', 'consumer', { + key: 'key', + id: '>' + }), + client.xTrim('key', 'MAXLEN', 1), + client.xClaim('key', 'group', 'consumer', 0, ['1-0', '2-0']) ]); - assert.deepEqual(reply, []); + assert.deepEqual(reply, [ + ...(testUtils.isVersionGreaterThan([7, 0]) ? [] : [null]), + { + id: '2-0', + message + } + ]); }, { client: GLOBAL.SERVERS.OPEN, cluster: GLOBAL.CLUSTERS.OPEN diff --git a/packages/client/lib/commands/XCLAIM.ts b/packages/client/lib/commands/XCLAIM.ts index 2c04123976e..3ec4f6639ba 100644 --- a/packages/client/lib/commands/XCLAIM.ts +++ b/packages/client/lib/commands/XCLAIM.ts @@ -1,5 +1,5 @@ -import { RedisArgument, Command } from '../RESP/types'; -import { RedisVariadicArgument, pushVariadicArguments, transformStreamMessagesReply } from './generic-transformers'; +import { RedisArgument, ArrayReply, NullReply, UnwrapReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments, StreamMessageReply, transformStreamMessageNullReply } from './generic-transformers'; export interface XClaimOptions { IDLE?: number; @@ -50,5 +50,7 @@ export default { return args; }, - transformReply: transformStreamMessagesReply + transformReply(reply: UnwrapReply>) { + return reply.map(transformStreamMessageNullReply); + } } as const satisfies Command; diff --git a/packages/client/lib/commands/XINFO_STREAM.ts b/packages/client/lib/commands/XINFO_STREAM.ts index 9d809d4ab57..04721d0ad32 100644 --- a/packages/client/lib/commands/XINFO_STREAM.ts +++ b/packages/client/lib/commands/XINFO_STREAM.ts @@ -1,5 +1,5 @@ -import { TuplesToMapReply, BlobStringReply, NumberReply, NullReply, Resp2Reply, Command, RespType, RESP_TYPES, RedisArgument } from '../RESP/types'; -import { StreamMessageRawReply, transformStreamMessageReply } from './generic-transformers'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, NullReply, TuplesReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; +import { isNullReply, transformTuplesReply } from './generic-transformers'; export type XInfoStreamReply = TuplesToMapReply<[ [BlobStringReply<'length'>, NumberReply], @@ -13,8 +13,8 @@ export type XInfoStreamReply = TuplesToMapReply<[ /** added in 7.2 */ [BlobStringReply<'recorded-first-entry-id'>, BlobStringReply], [BlobStringReply<'groups'>, NumberReply], - [BlobStringReply<'first-entry'>, ReturnType | NullReply], - [BlobStringReply<'last-entry'>, ReturnType | NullReply] + [BlobStringReply<'first-entry'>, ReturnType], + [BlobStringReply<'last-entry'>, ReturnType] ]>; export default { @@ -66,6 +66,17 @@ export default { } } as const satisfies Command; -function transformEntry(entry: StreamMessageRawReply | NullReply) { - return entry === null ? null : transformStreamMessageReply(entry as StreamMessageRawReply); +type RawEntry = TuplesReply<[ + id: BlobStringReply, + message: ArrayReply +]> | NullReply; + +function transformEntry(entry: RawEntry) { + if (isNullReply(entry)) return entry; + + const [id, message] = entry as unknown as UnwrapReply; + return { + id, + message: transformTuplesReply(message) + }; } diff --git a/packages/client/lib/commands/XRANGE.ts b/packages/client/lib/commands/XRANGE.ts index 1eed1e12b94..908e3d717fb 100644 --- a/packages/client/lib/commands/XRANGE.ts +++ b/packages/client/lib/commands/XRANGE.ts @@ -1,5 +1,5 @@ -import { RedisArgument, Command } from '../RESP/types'; -import { transformStreamMessagesReply } from './generic-transformers'; +import { RedisArgument, ArrayReply, UnwrapReply, Command } from '../RESP/types'; +import { StreamMessageReply, transformStreamMessageReply } from './generic-transformers'; export interface XRangeOptions { COUNT?: number; @@ -25,5 +25,7 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments: transformXRangeArguments.bind(undefined, 'XRANGE'), - transformReply: transformStreamMessagesReply + transformReply(reply: UnwrapReply>) { + return reply.map(transformStreamMessageReply); + } } as const satisfies Command; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 3c51100cc73..789464fddb7 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -84,37 +84,23 @@ export function transformTuplesReply( return message; } -export type StreamMessageRawReply = TuplesReply<[ +export type StreamMessageReply = TuplesReply<[ id: BlobStringReply, message: ArrayReply ]>; -export function transformStreamMessageReply(reply: StreamMessageRawReply) { - const [id, message] = reply as unknown as UnwrapReply; +export function transformStreamMessageReply(reply: StreamMessageReply) { + const [ id, message ] = reply as unknown as UnwrapReply; return { id, message: transformTuplesReply(message) }; } -export type StreamMessagesRawReply = ArrayReply; - -export function transformStreamMessagesReply(reply: StreamMessagesRawReply) { - return (reply as unknown as UnwrapReply) - .map(message => transformStreamMessageReply(message)); +export function transformStreamMessageNullReply(reply: StreamMessageReply | NullReply) { + return isNullReply(reply) ? reply : transformStreamMessageReply(reply); } -// export type StreamsMessagesReply = MapReply; - -// export function transformStreamsMessagesReply(reply: Array | null): StreamsMessagesReply | null { -// if (reply === null) return null; - -// return reply.map(([name, rawMessages]) => ({ -// name, -// messages: transformStreamMessagesReply(rawMessages) -// })); -// } - export interface SortedSetMember { value: RedisArgument; score: number; From 61c3e8b95b56f349f35d79d3d9814e047c1a86e3 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 26 Jul 2023 11:10:28 -0400 Subject: [PATCH 198/325] fix TOPK commands --- packages/bloom/lib/commands/top-k/ADD.ts | 4 ++-- packages/bloom/lib/commands/top-k/LIST.ts | 4 ++-- packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/bloom/lib/commands/top-k/ADD.ts b/packages/bloom/lib/commands/top-k/ADD.ts index 4043c86c56d..99982cc8e64 100644 --- a/packages/bloom/lib/commands/top-k/ADD.ts +++ b/packages/bloom/lib/commands/top-k/ADD.ts @@ -1,4 +1,4 @@ -import { ArrayReply, SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export default { @@ -7,5 +7,5 @@ export default { transformArguments(key: RedisArgument, items: RedisVariadicArgument) { return pushVariadicArguments(['TOPK.ADD', key], items); }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/LIST.ts b/packages/bloom/lib/commands/top-k/LIST.ts index d4c9f4cce78..26345b72462 100644 --- a/packages/bloom/lib/commands/top-k/LIST.ts +++ b/packages/bloom/lib/commands/top-k/LIST.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,5 +6,5 @@ export default { transformArguments(key: RedisArgument) { return ['TOPK.LIST', key]; }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts index a4a5249c5be..d26936fd3c7 100644 --- a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts +++ b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.ts @@ -1,4 +1,4 @@ -import { RedisArgument, ArrayReply, SimpleStringReply, NumberReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,15 +6,15 @@ export default { transformArguments(key: RedisArgument) { return ['TOPK.LIST', key, 'WITHCOUNT']; }, - transformReply(rawReply: UnwrapReply>) { + transformReply(rawReply: UnwrapReply>) { const reply: Array<{ - item: SimpleStringReply; + item: BlobStringReply; count: NumberReply; }> = []; for (let i = 0; i < rawReply.length; i++) { reply.push({ - item: rawReply[i] as SimpleStringReply, + item: rawReply[i] as BlobStringReply, count: rawReply[++i] as NumberReply }); } From ff07bbf3d37ff4d2a75a2c4dbcaf8c20ddb425f0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Jul 2023 11:23:34 -0400 Subject: [PATCH 199/325] WIP --- docs/v4-to-v5.md | 1 + packages/client/lib/commands/PING.ts | 4 +- .../time-series/lib/commands/ALTER.spec.ts | 2 +- .../time-series/lib/commands/MADD.spec.ts | 2 +- .../time-series/lib/commands/MGET.spec.ts | 62 +++--- packages/time-series/lib/commands/MGET.ts | 48 ++--- .../lib/commands/MGET_WITHLABELS.spec.ts | 62 +++--- .../lib/commands/MGET_WITHLABELS.ts | 49 ++--- .../time-series/lib/commands/MRANGE.spec.ts | 88 ++++----- packages/time-series/lib/commands/MRANGE.ts | 83 ++++++-- .../lib/commands/MRANGE_WITHLABELS.spec.ts | 91 ++++----- .../lib/commands/MRANGE_WITHLABELS.ts | 45 +++-- .../lib/commands/MREVRANGE.spec.ts | 84 +++++---- .../time-series/lib/commands/MREVRANGE.ts | 28 +-- .../lib/commands/MREVRANGE_WITHLABELS.spec.ts | 90 ++++----- .../lib/commands/MREVRANGE_WITHLABELS.ts | 30 +-- .../lib/commands/QUERYINDEX.spec.ts | 52 ++--- .../time-series/lib/commands/QUERYINDEX.ts | 21 ++- .../time-series/lib/commands/RANGE.spec.ts | 64 ++++--- packages/time-series/lib/commands/RANGE.ts | 133 +++++++++++-- .../time-series/lib/commands/REVRANGE.spec.ts | 178 +++++++++--------- packages/time-series/lib/commands/REVRANGE.ts | 33 +--- packages/time-series/lib/commands/index.ts | 106 ++++++----- packages/time-series/lib/index.ts | 4 +- packages/time-series/package.json | 3 +- 25 files changed, 739 insertions(+), 624 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 66d94fb0a8f..c500815cd66 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -181,6 +181,7 @@ Some command arguments/replies have changed to align more closely to data types - `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing] - `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing] - `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing] +- `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` [^enum-to-constants]: TODO diff --git a/packages/client/lib/commands/PING.ts b/packages/client/lib/commands/PING.ts index fabdfae6501..7f6fd31047e 100644 --- a/packages/client/lib/commands/PING.ts +++ b/packages/client/lib/commands/PING.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { RedisArgument, SimpleStringReply, BlobStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, @@ -11,5 +11,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply | BlobStringReply } as const satisfies Command; diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index 6889cd2b2c4..d09d40db66e 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -64,7 +64,7 @@ describe('TS.ALTER', () => { testUtils.testWithClient('client.ts.alter', async client => { const [, reply] = await Promise.all([ client.ts.create('key'), - client.ts.alter('key', { RETENTION: 1 }) + client.ts.alter('key') ]); assert.equal(reply, 'OK'); diff --git a/packages/time-series/lib/commands/MADD.spec.ts b/packages/time-series/lib/commands/MADD.spec.ts index 119fcfce60e..d9585ffbe7c 100644 --- a/packages/time-series/lib/commands/MADD.spec.ts +++ b/packages/time-series/lib/commands/MADD.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils'; import MADD from './MADD'; import { SimpleError } from '@redis/client/lib/errors'; -describe.only('TS.MADD', () => { +describe('TS.MADD', () => { it('transformArguments', () => { assert.deepEqual( MADD.transformArguments([{ diff --git a/packages/time-series/lib/commands/MGET.spec.ts b/packages/time-series/lib/commands/MGET.spec.ts index c932ff704ab..810e54068bd 100644 --- a/packages/time-series/lib/commands/MGET.spec.ts +++ b/packages/time-series/lib/commands/MGET.spec.ts @@ -1,40 +1,40 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MGET'; +import MGET from './MGET'; describe('TS.MGET', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('label=value'), - ['TS.MGET', 'FILTER', 'label=value'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + MGET.transformArguments('label=value'), + ['TS.MGET', 'FILTER', 'label=value'] + ); + }); - it('with LATEST', () => { - assert.deepEqual( - transformArguments('label=value', { - LATEST: true - }), - ['TS.MGET', 'LATEST', 'FILTER', 'label=value'] - ); - }); + it('with LATEST', () => { + assert.deepEqual( + MGET.transformArguments('label=value', { + LATEST: true + }), + ['TS.MGET', 'LATEST', 'FILTER', 'label=value'] + ); }); + }); - testUtils.testWithClient('client.ts.mGet', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value' } - }); + testUtils.testWithClient('client.ts.mGet', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 0, { + LABELS: { label: 'value' } + }), + client.ts.mGet('label=value') + ]); - assert.deepEqual( - await client.ts.mGet('label=value'), - [{ - key: 'key', - sample: { - timestamp: 0, - value: 0 - } - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + key: 'key', + sample: { + timestamp: 0, + value: 0 + } + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MGET.ts b/packages/time-series/lib/commands/MGET.ts index 67315722eb6..861c23b1e42 100644 --- a/packages/time-series/lib/commands/MGET.ts +++ b/packages/time-series/lib/commands/MGET.ts @@ -1,31 +1,31 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { Filter, pushFilterArgument, pushLatestArgument, RawLabels, SampleRawReply, SampleReply, transformSampleReply } from '.'; +import { CommandArguments, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -export const IS_READ_ONLY = true; - -export interface MGetOptions { - LATEST?: boolean; -} - -export function transformArguments(filter: Filter, options?: MGetOptions): RedisCommandArguments { - const args = pushLatestArgument(['TS.MGET'], options?.LATEST); - return pushFilterArgument(args, filter); +export interface TsMGetOptions { + LATEST?: boolean; } -export type MGetRawReply = Array<[ - key: string, - labels: RawLabels, - sample: SampleRawReply -]>; +export function pushLatestArgument(args: CommandArguments, latest?: boolean) { + if (latest) { + args.push('LATEST'); + } -export interface MGetReply { - key: string, - sample: SampleReply + return args; } -export function transformReply(reply: MGetRawReply): Array { - return reply.map(([key, _, sample]) => ({ - key, - sample: transformSampleReply(sample) - })); +export function pushFilterArgument(args: CommandArguments, filter: RedisVariadicArgument) { + args.push('FILTER'); + return pushVariadicArguments(args, filter); } + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(filter: RedisVariadicArgument, options?: TsMGetOptions) { + const args = pushLatestArgument(['TS.MGET'], options?.LATEST); + return pushFilterArgument(args, filter); + }, + // TODO + // transformSampleReply + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts index 67c3a4c7b35..1a2d223cb7e 100644 --- a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts @@ -1,39 +1,41 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MGET_WITHLABELS'; +import MGET_WITHLABELS from './MGET_WITHLABELS'; describe('TS.MGET_WITHLABELS', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('label=value'), - ['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + MGET_WITHLABELS.transformArguments('label=value'), + ['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value'] + ); + }); - it('with SELECTED_LABELS', () => { - assert.deepEqual( - transformArguments('label=value', { SELECTED_LABELS: 'label' }), - ['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value'] - ); - }); + it('with SELECTED_LABELS', () => { + assert.deepEqual( + MGET_WITHLABELS.transformArguments('label=value', { + SELECTED_LABELS: 'label' + }), + ['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value'] + ); }); + }); - testUtils.testWithClient('client.ts.mGetWithLabels', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value' } - }); + testUtils.testWithClient('client.ts.mGetWithLabels', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 0, { + LABELS: { label: 'value' } + }), + client.ts.mGetWithLabels('label=value') + ]); - assert.deepEqual( - await client.ts.mGetWithLabels('label=value'), - [{ - key: 'key', - labels: { label: 'value'}, - sample: { - timestamp: 0, - value: 0 - } - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + key: 'key', + labels: { label: 'value' }, + sample: { + timestamp: 0, + value: 0 + } + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MGET_WITHLABELS.ts b/packages/time-series/lib/commands/MGET_WITHLABELS.ts index 232c17a0ada..273e71729b1 100644 --- a/packages/time-series/lib/commands/MGET_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MGET_WITHLABELS.ts @@ -1,37 +1,20 @@ -import { - SelectedLabels, - pushWithLabelsArgument, - Labels, - transformLablesReply, - transformSampleReply, - Filter, - pushFilterArgument -} from '.'; -import { MGetOptions, MGetRawReply, MGetReply } from './MGET'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { TsMGetOptions, pushLatestArgument, pushFilterArgument } from './MGET'; +import { pushWithLabelsArgument } from '.'; -export const IS_READ_ONLY = true; - -interface MGetWithLabelsOptions extends MGetOptions { - SELECTED_LABELS?: SelectedLabels; +export interface TsMGetWithLabelsOptions extends TsMGetOptions { + SELECTED_LABELS?: RedisVariadicArgument; } -export function transformArguments( - filter: Filter, - options?: MGetWithLabelsOptions -): RedisCommandArguments { - const args = pushWithLabelsArgument(['TS.MGET'], options?.SELECTED_LABELS); +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(filter: RedisVariadicArgument, options?: TsMGetWithLabelsOptions) { + let args = pushLatestArgument(['TS.MGET'], options?.LATEST); + args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); return pushFilterArgument(args, filter); -} - -export interface MGetWithLabelsReply extends MGetReply { - labels: Labels; -}; - -export function transformReply(reply: MGetRawReply): Array { - return reply.map(([key, labels, sample]) => ({ - key, - labels: transformLablesReply(labels), - sample: transformSampleReply(sample) - })); -} + }, + // TODO + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/MRANGE.spec.ts b/packages/time-series/lib/commands/MRANGE.spec.ts index 5f5a7930e50..32cdd37c6f2 100644 --- a/packages/time-series/lib/commands/MRANGE.spec.ts +++ b/packages/time-series/lib/commands/MRANGE.spec.ts @@ -1,50 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MRANGE'; +import MRANGE from './MRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; describe('TS.MRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('-', '+', 'label=value', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 0, - max: 1 - }, - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - }, - GROUPBY: { - label: 'label', - reducer: TimeSeriesReducers.SUM - }, - }), - ['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', - 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value', - 'GROUPBY', 'label', 'REDUCE', 'SUM'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MRANGE.transformArguments('-', '+', 'label=value', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 0, + max: 1 + }, + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 1 + }, + GROUPBY: { + label: 'label', + reducer: TimeSeriesReducers.SUM + }, + }), + [ + 'TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', + 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value', + 'GROUPBY', 'label', 'REDUCE', 'SUM' + ] + ); + }); - testUtils.testWithClient('client.ts.mRange', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value'} - }); + testUtils.testWithClient('client.ts.mRange', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 0, { + LABELS: { + label: 'value' + } + }), + client.ts.mRange('-', '+', 'label=value', { + COUNT: 1 + }) + ]); - assert.deepEqual( - await client.ts.mRange('-', '+', 'label=value', { - COUNT: 1 - }), - [{ - key: 'key', - samples: [{ - timestamp: 0, - value: 0 - }] - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + key: 'key', + samples: [{ + timestamp: 0, + value: 0 + }] + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MRANGE.ts b/packages/time-series/lib/commands/MRANGE.ts index d589ac0332a..8fbbe7cb81c 100644 --- a/packages/time-series/lib/commands/MRANGE.ts +++ b/packages/time-series/lib/commands/MRANGE.ts @@ -1,21 +1,68 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.'; - -export const IS_READ_ONLY = true; - -export function transformArguments( - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filters: Filter, - options?: MRangeOptions -): RedisCommandArguments { - return pushMRangeArguments( - ['TS.MRANGE'], - fromTimestamp, - toTimestamp, - filters, - options +import { RedisArgument, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { Timestamp } from '.'; +import { TsRangeOptions, pushRangeArguments } from './RANGE'; +import { pushFilterArgument } from './MGET'; + +export const TIME_SERIES_REDUCERS = { + AVG: 'AVG', + SUM: 'SUM', + MIN: 'MIN', + MAX: 'MAX', + RANGE: 'RANGE', + COUNT: 'COUNT', + STD_P: 'STD.P', + STD_S: 'STD.S', + VAR_P: 'VAR.P', + VAR_S: 'VAR.S' +}; + +export type TimeSeriesReducers = typeof TIME_SERIES_REDUCERS[keyof typeof TIME_SERIES_REDUCERS]; + +export interface TsMRangeOptions extends TsRangeOptions { + GROUPBY?: { + label: RedisArgument; + reducer: TimeSeriesReducers; + }; +} + +export function pushGroupByArgument(args: CommandArguments, groupBy?: TsMRangeOptions['GROUPBY']) { + if (groupBy) { + args.push( + 'GROUPBY', + groupBy.label, + 'REDUCE', + groupBy.reducer ); + } + + return args; +} + +export function transformMRangeArguments( + command: RedisArgument, + fromTimestamp: Timestamp, + toTimestamp: Timestamp, + filter: RedisVariadicArgument, + options?: TsMRangeOptions +) { + let args = pushRangeArguments( + [command], + fromTimestamp, + toTimestamp, + options + ); + + args = pushFilterArgument(args, filter); + + return pushGroupByArgument(args, options?.GROUPBY); } -export { transformMRangeReply as transformReply } from '.'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments: transformMRangeArguments.bind(undefined, 'TS.MRANGE'), + // TODO + // export { transformMRangeReply as transformReply } from '.'; + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts index 729e32f19af..4997634958e 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts @@ -1,52 +1,53 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MRANGE_WITHLABELS'; -import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; +import MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; +import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; +import { TIME_SERIES_REDUCERS } from './MRANGE'; describe('TS.MRANGE_WITHLABELS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('-', '+', 'label=value', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 0, - max: 1 - }, - SELECTED_LABELS: ['label'], - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - }, - GROUPBY: { - label: 'label', - reducer: TimeSeriesReducers.SUM - }, - }), - ['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', - 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label', - 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 0, + max: 1 + }, + SELECTED_LABELS: ['label'], + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TIME_SERIES_AGGREGATION_TYPE.AVG, + timeBucket: 1 + }, + GROUPBY: { + label: 'label', + reducer: TIME_SERIES_REDUCERS.SUM + }, + }), + ['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', + 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label', + 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM'] + ); + }); - testUtils.testWithClient('client.ts.mRangeWithLabels', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value'} - }); + testUtils.testWithClient('client.ts.mRangeWithLabels', async client => { + await client.ts.add('key', 0, 0, { + LABELS: { label: 'value' } + }); - assert.deepEqual( - await client.ts.mRangeWithLabels('-', '+', 'label=value', { - COUNT: 1 - }), - [{ - key: 'key', - labels: { label: 'value' }, - samples: [{ - timestamp: 0, - value: 0 - }] - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + await client.ts.mRangeWithLabels('-', '+', 'label=value', { + COUNT: 1 + }), + [{ + key: 'key', + labels: { label: 'value' }, + samples: [{ + timestamp: 0, + value: 0 + }] + }] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts index 16b7920e82c..06885738786 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts @@ -1,21 +1,32 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments } from '.'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { TsMRangeOptions, pushGroupByArgument } from './MRANGE'; +import { Timestamp, pushWithLabelsArgument } from '.'; +import { pushFilterArgument } from './MGET'; +import { pushRangeArguments } from './RANGE'; -export const IS_READ_ONLY = true; +export interface TsMRangeWithLabelsOptions extends TsMRangeOptions { + SELECTED_LABELS?: RedisVariadicArgument; +} -export function transformArguments( - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filters: string | Array, - options?: MRangeWithLabelsOptions -): RedisCommandArguments { - return pushMRangeWithLabelsArguments( - ['TS.MRANGE'], - fromTimestamp, - toTimestamp, - filters, - options - ); +export function transformMRangeWithLabelsArguments( + command: RedisArgument, + fromTimestamp: Timestamp, + toTimestamp: Timestamp, + filter: RedisVariadicArgument, + options?: TsMRangeWithLabelsOptions +) { + let args = pushRangeArguments([command], fromTimestamp, toTimestamp, options); + args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); + args = pushFilterArgument(args, filter); + return pushGroupByArgument(args, options?.GROUPBY); } -export { transformMRangeWithLabelsReply as transformReply } from '.'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MRANGE'), + // TODO + // export { transformMRangeWithLabelsReply as transformReply } from '.'; + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/MREVRANGE.spec.ts b/packages/time-series/lib/commands/MREVRANGE.spec.ts index e5dcf5f5f77..69937fe4d53 100644 --- a/packages/time-series/lib/commands/MREVRANGE.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE.spec.ts @@ -4,47 +4,49 @@ import { transformArguments } from './MREVRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; describe('TS.MREVRANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('-', '+', 'label=value', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 0, - max: 1 - }, - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - }, - GROUPBY: { - label: 'label', - reducer: TimeSeriesReducers.SUM - }, - }), - ['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', - 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value', - 'GROUPBY', 'label', 'REDUCE', 'SUM'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + transformArguments('-', '+', 'label=value', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 0, + max: 1 + }, + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 1 + }, + GROUPBY: { + label: 'label', + reducer: TimeSeriesReducers.SUM + }, + }), + [ + 'TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', + 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value', + 'GROUPBY', 'label', 'REDUCE', 'SUM' + ] + ); + }); - testUtils.testWithClient('client.ts.mRevRange', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value'} - }); + testUtils.testWithClient('client.ts.mRevRange', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 0, { + LABELS: { label: 'value' } + }), + client.ts.mRevRange('-', '+', 'label=value', { + COUNT: 1 + }) + ]); - assert.deepEqual( - await client.ts.mRevRange('-', '+', 'label=value', { - COUNT: 1 - }), - [{ - key: 'key', - samples: [{ - timestamp: 0, - value: 0 - }] - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + key: 'key', + samples: [{ + timestamp: 0, + value: 0 + }] + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MREVRANGE.ts b/packages/time-series/lib/commands/MREVRANGE.ts index 127c052ffe0..c64c37118e2 100644 --- a/packages/time-series/lib/commands/MREVRANGE.ts +++ b/packages/time-series/lib/commands/MREVRANGE.ts @@ -1,21 +1,9 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import MRANGE, { transformMRangeArguments } from './MRANGE'; -export const IS_READ_ONLY = true; - -export function transformArguments( - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filters: Filter, - options?: MRangeOptions -): RedisCommandArguments { - return pushMRangeArguments( - ['TS.MREVRANGE'], - fromTimestamp, - toTimestamp, - filters, - options - ); -} - -export { transformMRangeReply as transformReply } from '.'; +export default { + FIRST_KEY_INDEX: MRANGE.FIRST_KEY_INDEX, + IS_READ_ONLY: MRANGE.IS_READ_ONLY, + transformArguments: transformMRangeArguments.bind(undefined, 'TS.MREVRANGE'), + transformReply: MRANGE.transformReply +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts index a3e50b7f26c..5371a009837 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts @@ -1,52 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MREVRANGE_WITHLABELS'; +import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; describe('TS.MREVRANGE_WITHLABELS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('-', '+', 'label=value', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 0, - max: 1 - }, - SELECTED_LABELS: ['label'], - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - }, - GROUPBY: { - label: 'label', - reducer: TimeSeriesReducers.SUM - }, - }), - ['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', - 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label', - 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MREVRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 0, + max: 1 + }, + SELECTED_LABELS: ['label'], + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 1 + }, + GROUPBY: { + label: 'label', + reducer: TimeSeriesReducers.SUM + }, + }), + [ + 'TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1', + 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label', + 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM' + ] + ); + }); - testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => { - await client.ts.add('key', 0, 0, { - LABELS: { label: 'value'} - }); + testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 0, 0, { + LABELS: { label: 'value' } + }), + client.ts.mRevRangeWithLabels('-', '+', 'label=value', { + COUNT: 1 + }) + ]); - assert.deepEqual( - await client.ts.mRevRangeWithLabels('-', '+', 'label=value', { - COUNT: 1 - }), - [{ - key: 'key', - labels: { label: 'value' }, - samples: [{ - timestamp: 0, - value: 0 - }] - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + key: 'key', + labels: { label: 'value' }, + samples: [{ + timestamp: 0, + value: 0 + }] + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts index 21a0ebc69c3..281b3235d83 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts @@ -1,21 +1,11 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments, Filter } from '.'; +import { Command } from '@redis/client/dist/lib/RESP/types'; +import { transformMRangeWithLabelsArguments } from './MRANGE_WITHLABELS'; -export const IS_READ_ONLY = true; - -export function transformArguments( - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - filters: Filter, - options?: MRangeWithLabelsOptions -): RedisCommandArguments { - return pushMRangeWithLabelsArguments( - ['TS.MREVRANGE'], - fromTimestamp, - toTimestamp, - filters, - options - ); -} - -export { transformMRangeWithLabelsReply as transformReply } from '.'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MREVRANGE'), + // TODO + // export { transformMRangeWithLabelsReply as transformReply } from '.'; + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/QUERYINDEX.spec.ts b/packages/time-series/lib/commands/QUERYINDEX.spec.ts index 68e473918a5..86160ebd7d5 100644 --- a/packages/time-series/lib/commands/QUERYINDEX.spec.ts +++ b/packages/time-series/lib/commands/QUERYINDEX.spec.ts @@ -1,34 +1,34 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './QUERYINDEX'; +import QUERYINDEX from './QUERYINDEX'; describe('TS.QUERYINDEX', () => { - describe('transformArguments', () => { - it('single filter', () => { - assert.deepEqual( - transformArguments('*'), - ['TS.QUERYINDEX', '*'] - ); - }); - - it('multiple filters', () => { - assert.deepEqual( - transformArguments(['a=1', 'b=2']), - ['TS.QUERYINDEX', 'a=1', 'b=2'] - ); - }); + describe('transformArguments', () => { + it('single filter', () => { + assert.deepEqual( + QUERYINDEX.transformArguments('*'), + ['TS.QUERYINDEX', '*'] + ); }); - testUtils.testWithClient('client.ts.queryIndex', async client => { - await client.ts.create('key', { - LABELS: { - label: 'value' - } - }); + it('multiple filters', () => { + assert.deepEqual( + QUERYINDEX.transformArguments(['a=1', 'b=2']), + ['TS.QUERYINDEX', 'a=1', 'b=2'] + ); + }); + }); + + testUtils.testWithClient('client.ts.queryIndex', async client => { + const [, reply] = await Promise.all([ + client.ts.create('key', { + LABELS: { + label: 'value' + } + }), + client.ts.queryIndex('label=value') + ]); - assert.deepEqual( - await client.ts.queryIndex('label=value'), - ['key'] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, ['key']); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/QUERYINDEX.ts b/packages/time-series/lib/commands/QUERYINDEX.ts index b2285789185..86c2a3c5a7e 100644 --- a/packages/time-series/lib/commands/QUERYINDEX.ts +++ b/packages/time-series/lib/commands/QUERYINDEX.ts @@ -1,11 +1,14 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { Filter } from '.'; +import { ArrayReply, BlobStringReply, SetReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments(filter: Filter): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(filter: RedisVariadicArgument) { return pushVariadicArguments(['TS.QUERYINDEX'], filter); -} - -export declare function transformReply(): Array; + }, + transformReply: { + 2: undefined as unknown as () => ArrayReply, + 3: undefined as unknown as () => SetReply + } +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/RANGE.spec.ts b/packages/time-series/lib/commands/RANGE.spec.ts index bc3c5498031..2c6c27f7a21 100644 --- a/packages/time-series/lib/commands/RANGE.spec.ts +++ b/packages/time-series/lib/commands/RANGE.spec.ts @@ -1,38 +1,40 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RANGE'; -import { TimeSeriesAggregationType } from '.'; +import RANGE from './RANGE'; +import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; describe('TS.RANGE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 1, - max: 2 - }, - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - } - }), - ['TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', - '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + RANGE.transformArguments('key', '-', '+', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 1, + max: 2 + }, + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TIME_SERIES_AGGREGATION_TYPE.AVG, + timeBucket: 1 + } + }), + [ + 'TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', + '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1' + ] + ); + }); - testUtils.testWithClient('client.ts.range', async client => { - await client.ts.add('key', 1, 2); + testUtils.testWithClient('client.ts.range', async client => { + const [, reply] = await Promise.all([ + client.ts.add('key', 1, 2), + client.ts.range('key', '-', '+') + ]); - assert.deepEqual( - await client.ts.range('key', '-', '+'), - [{ - timestamp: 1, - value: 2 - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + timestamp: 1, + value: 2 + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/RANGE.ts b/packages/time-series/lib/commands/RANGE.ts index e6ce256bbe6..0bbe55aebaf 100644 --- a/packages/time-series/lib/commands/RANGE.ts +++ b/packages/time-series/lib/commands/RANGE.ts @@ -1,24 +1,117 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - options?: RangeOptions -): RedisCommandArguments { - return pushRangeArguments( - ['TS.RANGE', key], - fromTimestamp, - toTimestamp, - options +import { CommandArguments, RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { Timestamp, transformTimestampArgument } from '.'; +import { TimeSeriesAggregationType } from './CREATERULE'; + +export const TIME_SERIES_BUCKET_TIMESTAMP = { + LOW: '-', + MIDDLE: '~', + END: '+' +}; + +export type TimeSeriesBucketTimestamp = typeof TIME_SERIES_BUCKET_TIMESTAMP[keyof typeof TIME_SERIES_BUCKET_TIMESTAMP]; + +export interface TsRangeOptions { + LATEST?: boolean; + FILTER_BY_TS?: Array; + FILTER_BY_VALUE?: { + min: number; + max: number; + }; + COUNT?: number; + ALIGN?: Timestamp; + AGGREGATION?: { + ALIGN?: Timestamp; + type: TimeSeriesAggregationType; + timeBucket: Timestamp; + BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp; + EMPTY?: boolean; + }; +} + +export function pushRangeArguments( + args: CommandArguments, + fromTimestamp: Timestamp, + toTimestamp: Timestamp, + options?: TsRangeOptions +) { + args.push( + transformTimestampArgument(fromTimestamp), + transformTimestampArgument(toTimestamp) + ); + + if (options?.LATEST) { + args.push('LATEST'); + } + + if (options?.FILTER_BY_TS) { + args.push('FILTER_BY_TS'); + for (const timestamp of options.FILTER_BY_TS) { + args.push(transformTimestampArgument(timestamp)); + } + } + + if (options?.FILTER_BY_VALUE) { + args.push( + 'FILTER_BY_VALUE', + options.FILTER_BY_VALUE.min.toString(), + options.FILTER_BY_VALUE.max.toString() ); + } + + if (options?.COUNT !== undefined) { + args.push('COUNT', options.COUNT.toString()); + } + + if (options?.AGGREGATION) { + if (options?.ALIGN !== undefined) { + args.push('ALIGN', transformTimestampArgument(options.ALIGN)); + } + + args.push( + 'AGGREGATION', + options.AGGREGATION.type, + transformTimestampArgument(options.AGGREGATION.timeBucket) + ); + + if (options.AGGREGATION.BUCKETTIMESTAMP) { + args.push( + 'BUCKETTIMESTAMP', + options.AGGREGATION.BUCKETTIMESTAMP + ); + } + + if (options.AGGREGATION.EMPTY) { + args.push('EMPTY'); + } + } + + return args; } -export function transformReply(reply: Array): Array { - return transformRangeReply(reply); +export function transformRangeArguments( + command: RedisArgument, + key: RedisArgument, + fromTimestamp: Timestamp, + toTimestamp: Timestamp, + options?: TsRangeOptions +) { + return pushRangeArguments( + [command, key], + fromTimestamp, + toTimestamp, + options + ); } + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments: transformRangeArguments.bind(undefined, 'TS.RANGE'), + // TODO + // import { SampleReply, transformRangeReply } from '.'; + // export function transformReply(reply: Array): Array { + // return transformRangeReply(reply); + // } + transformReply: undefined as unknown as () => any +} as const satisfies Command; + diff --git a/packages/time-series/lib/commands/REVRANGE.spec.ts b/packages/time-series/lib/commands/REVRANGE.spec.ts index 6fd0f6a45a4..3138e9327eb 100644 --- a/packages/time-series/lib/commands/REVRANGE.spec.ts +++ b/packages/time-series/lib/commands/REVRANGE.spec.ts @@ -4,103 +4,101 @@ import { transformArguments } from './REVRANGE'; import { TimeSeriesAggregationType } from '.'; describe('TS.REVRANGE', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', '-', '+'), - ['TS.REVRANGE', 'key', '-', '+'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('key', '-', '+'), + ['TS.REVRANGE', 'key', '-', '+'] + ); + }); - it('with FILTER_BY_TS', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_TS: [0] - }), - ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0'] - ); - }); + it('with FILTER_BY_TS', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + FILTER_BY_TS: [0] + }), + ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0'] + ); + }); - it('with FILTER_BY_VALUE', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_VALUE: { - min: 1, - max: 2 - } - }), - ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2'] - ); - }); + it('with FILTER_BY_VALUE', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + FILTER_BY_VALUE: { + min: 1, + max: 2 + } + }), + ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - COUNT: 1 - }), - ['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1'] - ); - }); + it('with COUNT', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + COUNT: 1 + }), + ['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1'] + ); + }); - it('with ALIGN', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - ALIGN: '-' - }), - ['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-'] - ); - }); + it('with ALIGN', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + ALIGN: '-' + }), + ['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-'] + ); + }); - it('with AGGREGATION', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - } - }), - ['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1'] - ); - }); + it('with AGGREGATION', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 1 + } + }), + ['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1'] + ); + }); - it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 1, - max: 2 - }, - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - } - }), - [ - 'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', - '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1' - ] - ); - }); + it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { + assert.deepEqual( + transformArguments('key', '-', '+', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 1, + max: 2 + }, + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 1 + } + }), + [ + 'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', + '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1' + ] + ); }); + }); - testUtils.testWithClient('client.ts.revRange', async client => { - await Promise.all([ - client.ts.add('key', 0, 1), - client.ts.add('key', 1, 2) - ]); + testUtils.testWithClient('client.ts.revRange', async client => { + const [, , reply] = await Promise.all([ + client.ts.add('key', 0, 1), + client.ts.add('key', 1, 2), + client.ts.revRange('key', '-', '+') + ]); - assert.deepEqual( - await client.ts.revRange('key', '-', '+'), - [{ - timestamp: 1, - value: 2 - }, { - timestamp: 0, - value: 1 - }] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, [{ + timestamp: 1, + value: 2 + }, { + timestamp: 0, + value: 1 + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/REVRANGE.ts b/packages/time-series/lib/commands/REVRANGE.ts index 9179756b5de..1097223080b 100644 --- a/packages/time-series/lib/commands/REVRANGE.ts +++ b/packages/time-series/lib/commands/REVRANGE.ts @@ -1,24 +1,9 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - key: string, - fromTimestamp: Timestamp, - toTimestamp: Timestamp, - options?: RangeOptions -): RedisCommandArguments { - return pushRangeArguments( - ['TS.REVRANGE', key], - fromTimestamp, - toTimestamp, - options - ); -} - -export function transformReply(reply: Array): Array { - return transformRangeReply(reply); -} +import { Command } from '@redis/client/dist/lib/RESP/types'; +import RANGE, { transformRangeArguments } from './RANGE'; + +export default { + FIRST_KEY_INDEX: RANGE.FIRST_KEY_INDEX, + IS_READ_ONLY: RANGE.IS_READ_ONLY, + transformArguments: transformRangeArguments.bind(undefined, 'TS.REVRANGE'), + transformReply: RANGE.transformReply +} as const satisfies Command; diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index 2c8fb48ce64..ff82cb893e9 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -1,4 +1,4 @@ -import type { RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types'; +import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import ALTER from './ALTER'; import CREATE from './CREATE'; @@ -11,15 +11,16 @@ import INCRBY from './INCRBY'; // import INFO_DEBUG from './INFO_DEBUG'; // import INFO from './INFO'; import MADD from './MADD'; -// import MGET from './MGET'; -// import MGET_WITHLABELS from './MGET_WITHLABELS'; -// import QUERYINDEX from './QUERYINDEX'; -// import RANGE from './RANGE'; -// import REVRANGE from './REVRANGE'; -// import MRANGE from './MRANGE'; -// import MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; -// import MREVRANGE from './MREVRANGE'; -// import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; +import MGET_WITHLABELS from './MGET_WITHLABELS'; +import MGET from './MGET'; +import MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; +import MRANGE from './MRANGE'; +import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; +import MREVRANGE from './MREVRANGE'; +import QUERYINDEX from './QUERYINDEX'; +import RANGE from './RANGE'; +import REVRANGE from './REVRANGE'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export default { ADD, @@ -46,24 +47,24 @@ export default { // info: INFO, MADD, mAdd: MADD, - // MGET, - // mGet: MGET, - // MGET_WITHLABELS, - // mGetWithLabels: MGET_WITHLABELS, - // QUERYINDEX, - // queryIndex: QUERYINDEX, - // RANGE, - // range: RANGE, - // REVRANGE, - // revRange: REVRANGE, - // MRANGE, - // mRange: MRANGE, - // MRANGE_WITHLABELS, - // mRangeWithLabels: MRANGE_WITHLABELS, - // MREVRANGE, - // mRevRange: MREVRANGE, - // MREVRANGE_WITHLABELS, - // mRevRangeWithLabels: MREVRANGE_WITHLABELS + MGET_WITHLABELS, + mGetWithLabels: MGET_WITHLABELS, + MGET, + mGet: MGET, + MRANGE_WITHLABELS, + mRangeWithLabels: MRANGE_WITHLABELS, + MRANGE, + mRange: MRANGE, + MREVRANGE_WITHLABELS, + mRevRangeWithLabels: MREVRANGE_WITHLABELS, + MREVRANGE, + mRevRange: MREVRANGE, + QUERYINDEX, + queryIndex: QUERYINDEX, + RANGE, + range: RANGE, + REVRANGE, + revRange: REVRANGE } as const satisfies RedisCommands; export function pushRetentionArgument(args: Array, retention?: number) { @@ -148,20 +149,22 @@ export function pushLabelsArgument(args: Array, labels?: Labels) // return labels // } - -// export type SampleRawReply = [timestamp: number, value: string]; - -// export interface SampleReply { -// timestamp: number; -// value: number; -// } - -// export function transformSampleReply(reply: SampleRawReply): SampleReply { -// return { -// timestamp: reply[0], -// value: Number(reply[1]) -// }; -// } +export const transformSampleReply = { + 2(reply: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>) { + const [timestamp, value] = reply as unknown as UnwrapReply; + return { + timestamp, + value: Number(value) + }; + }, + 3(reply: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>) { + const [timestamp, value] = reply as unknown as UnwrapReply; + return { + timestamp, + value + }; + } +}; // export enum TimeSeriesBucketTimestamp { // LOW = '-', @@ -293,16 +296,15 @@ export function pushLabelsArgument(args: Array, labels?: Labels) // export type SelectedLabels = string | Array; -// export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments { -// if (!selectedLabels) { -// args.push('WITHLABELS'); -// } else { -// args.push('SELECTED_LABELS'); -// args = pushVariadicArguments(args, selectedLabels); -// } - -// return args; -// } +export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: RedisVariadicArgument) { + if (!selectedLabels) { + args.push('WITHLABELS'); + return args; + } else { + args.push('SELECTED_LABELS'); + return pushVariadicArguments(args, selectedLabels); + } +} // export interface MRangeWithLabelsOptions extends MRangeOptions { // SELECTED_LABELS?: SelectedLabels; diff --git a/packages/time-series/lib/index.ts b/packages/time-series/lib/index.ts index e0b3c967057..9372621b009 100644 --- a/packages/time-series/lib/index.ts +++ b/packages/time-series/lib/index.ts @@ -4,8 +4,8 @@ export { TIME_SERIES_ENCODING, TimeSeriesEncoding, TIME_SERIES_DUPLICATE_POLICIES, - TimeSeriesDuplicatePolicies, - // TimeSeriesBucketTimestamp + TimeSeriesDuplicatePolicies } from './commands'; export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE'; +export { TIME_SERIES_BUCKET_TIMESTAMP, TimeSeriesBucketTimestamp } from './commands/RANGE'; diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 20e666efe42..03a3293463c 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -5,7 +5,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" From bfe5a8c8814bb3ec5ff173107a982fb3f1d81dfd Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Jul 2023 11:32:10 -0400 Subject: [PATCH 200/325] fix GRAPH.DELETE --- packages/graph/lib/commands/DELETE.spec.ts | 2 +- packages/graph/lib/commands/DELETE.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/graph/lib/commands/DELETE.spec.ts b/packages/graph/lib/commands/DELETE.spec.ts index 86cec5c8d28..45d5ddaa50c 100644 --- a/packages/graph/lib/commands/DELETE.spec.ts +++ b/packages/graph/lib/commands/DELETE.spec.ts @@ -16,6 +16,6 @@ describe('GRAPH.DELETE', () => { client.graph.delete('key') ]); - assert.equal(reply, 'OK'); + assert.equal(typeof reply, 'string'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/graph/lib/commands/DELETE.ts b/packages/graph/lib/commands/DELETE.ts index f5772a5f6e6..f5f99fb92cc 100644 --- a/packages/graph/lib/commands/DELETE.ts +++ b/packages/graph/lib/commands/DELETE.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -6,5 +6,5 @@ export default { transformArguments(key: RedisArgument) { return ['GRAPH.DELETE', key]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'> + transformReply: undefined as unknown as () => BlobStringReply } as const satisfies Command; From 7ce9e9bf25800520861ee1303b02d61ce8e9acd8 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Jul 2023 12:58:07 -0400 Subject: [PATCH 201/325] FT.CREATE --- packages/search/lib/commands/CREATE.spec.ts | 757 +++++++------ packages/search/lib/commands/CREATE.ts | 313 +++++- packages/search/lib/commands/index.ts | 1117 ++++++++++--------- 3 files changed, 1212 insertions(+), 975 deletions(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 1a0a4f244bd..021d8fa4291 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -1,418 +1,415 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CREATE'; -import { SchemaFieldTypes, SchemaTextFieldPhonetics, RedisSearchLanguages, VectorAlgorithms } from '.'; +import CREATE, { SCHEMA_FIELD_TYPE, SCHEMA_TEXT_FIELD_PHONETIC, SCHEMA_VECTOR_FIELD_ALGORITHM, REDISEARCH_LANGUAGE } from './CREATE'; + +describe.only('FT.CREATE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}), + ['FT.CREATE', 'index', 'SCHEMA'] + ); + }); -describe('CREATE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('index', {}), - ['FT.CREATE', 'index', 'SCHEMA'] - ); + describe('with fields', () => { + describe('TEXT', () => { + it('without options', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT'] + ); }); - 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('with WITHSUFFIXTRIE', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - WITHSUFFIXTRIE: true - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'WITHSUFFIXTRIE'] - ); - }); - }); - - 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 SEPARATOR', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TAG, - SEPARATOR: 'separator' - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'SEPARATOR', 'separator'] - ); - }); - - it('with CASESENSITIVE', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TAG, - CASESENSITIVE: true - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'CASESENSITIVE'] - ); - }); - - it('with WITHSUFFIXTRIE', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TAG, - WITHSUFFIXTRIE: true - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'WITHSUFFIXTRIE'] - ); - }); - }); - - describe('VECTOR', () => { - it('Flat algorithm', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.VECTOR, - ALGORITHM: VectorAlgorithms.FLAT, - TYPE: 'FLOAT32', - DIM: 2, - DISTANCE_METRIC: 'L2', - INITIAL_CAP: 1000000, - BLOCK_SIZE: 1000 - } - }), - [ - 'FT.CREATE', 'index', 'SCHEMA', 'field', 'VECTOR', 'FLAT', '10', 'TYPE', - 'FLOAT32', 'DIM', '2', 'DISTANCE_METRIC', 'L2', 'INITIAL_CAP', '1000000', - 'BLOCK_SIZE', '1000' - ] - ); - }); - - it('HNSW algorithm', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.VECTOR, - ALGORITHM: VectorAlgorithms.HNSW, - TYPE: 'FLOAT32', - DIM: 2, - DISTANCE_METRIC: 'L2', - INITIAL_CAP: 1000000, - M: 40, - EF_CONSTRUCTION: 250, - EF_RUNTIME: 20 - } - }), - [ - 'FT.CREATE', 'index', 'SCHEMA', 'field', 'VECTOR', 'HNSW', '14', 'TYPE', - 'FLOAT32', 'DIM', '2', 'DISTANCE_METRIC', 'L2', 'INITIAL_CAP', '1000000', - 'M', '40', 'EF_CONSTRUCTION', '250', 'EF_RUNTIME', '20' - ] - ); - }); - }); - - describe('with generic options', () => { - it('with AS', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - AS: 'as' - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'AS', 'as', 'TEXT'] - ); - }); - - describe('with SORTABLE', () => { - it('true', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - SORTABLE: true - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE'] - ); - }); - - it('UNF', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - SORTABLE: 'UNF' - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE', 'UNF'] - ); - }); - }); - - it('with NOINDEX', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - NOINDEX: true - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOINDEX'] - ); - }); - }); + it('with NOSTEM', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + NOSTEM: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOSTEM'] + ); }); - it('with ON', () => { - assert.deepEqual( - transformArguments('index', {}, { - ON: 'HASH' - }), - ['FT.CREATE', 'index', 'ON', 'HASH', 'SCHEMA'] - ); + it('with WEIGHT', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + WEIGHT: 1 + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'WEIGHT', '1'] + ); }); - 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 PHONETIC', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + PHONETIC: SCHEMA_TEXT_FIELD_PHONETIC.DM_EN + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'PHONETIC', SCHEMA_TEXT_FIELD_PHONETIC.DM_EN] + ); }); - it('with FILTER', () => { - assert.deepEqual( - transformArguments('index', {}, { - FILTER: '@field != ""' - }), - ['FT.CREATE', 'index', 'FILTER', '@field != ""', 'SCHEMA'] - ); + it('with WITHSUFFIXTRIE', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + WITHSUFFIXTRIE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'WITHSUFFIXTRIE'] + ); }); + }); + + it('NUMERIC', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: SCHEMA_FIELD_TYPE.NUMERIC + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'NUMERIC'] + ); + }); + + it('GEO', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: SCHEMA_FIELD_TYPE.GEO + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEO'] + ); + }); - it('with LANGUAGE', () => { + describe('TAG', () => { + describe('without options', () => { + it('SCHEMA_FIELD_TYPE.TAG', () => { assert.deepEqual( - transformArguments('index', {}, { - LANGUAGE: RedisSearchLanguages.ARABIC - }), - ['FT.CREATE', 'index', 'LANGUAGE', RedisSearchLanguages.ARABIC, 'SCHEMA'] + CREATE.transformArguments('index', { + field: SCHEMA_FIELD_TYPE.TAG + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG'] ); - }); + }); - it('with LANGUAGE_FIELD', () => { + it('{ type: SCHEMA_FIELD_TYPE.TAG }', () => { assert.deepEqual( - transformArguments('index', {}, { - LANGUAGE_FIELD: '@field' - }), - ['FT.CREATE', 'index', 'LANGUAGE_FIELD', '@field', 'SCHEMA'] + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TAG + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG'] ); + }); }); - it('with SCORE', () => { - assert.deepEqual( - transformArguments('index', {}, { - SCORE: 1 - }), - ['FT.CREATE', 'index', 'SCORE', '1', 'SCHEMA'] - ); + it('with SEPARATOR', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TAG, + SEPARATOR: 'separator' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'SEPARATOR', 'separator'] + ); }); - it('with SCORE_FIELD', () => { - assert.deepEqual( - transformArguments('index', {}, { - SCORE_FIELD: '@field' - }), - ['FT.CREATE', 'index', 'SCORE_FIELD', '@field', 'SCHEMA'] - ); + it('with CASESENSITIVE', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TAG, + CASESENSITIVE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'CASESENSITIVE'] + ); }); - it('with MAXTEXTFIELDS', () => { - assert.deepEqual( - transformArguments('index', {}, { - MAXTEXTFIELDS: true - }), - ['FT.CREATE', 'index', 'MAXTEXTFIELDS', 'SCHEMA'] - ); + it('with WITHSUFFIXTRIE', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TAG, + WITHSUFFIXTRIE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'WITHSUFFIXTRIE'] + ); }); - - it('with TEMPORARY', () => { - assert.deepEqual( - transformArguments('index', {}, { - TEMPORARY: 1 - }), - ['FT.CREATE', 'index', 'TEMPORARY', '1', 'SCHEMA'] - ); + }); + + describe('VECTOR', () => { + it('Flat algorithm', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.VECTOR, + ALGORITHM: SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT, + TYPE: 'FLOAT32', + DIM: 2, + DISTANCE_METRIC: 'L2', + INITIAL_CAP: 1000000, + BLOCK_SIZE: 1000 + } + }), + [ + 'FT.CREATE', 'index', 'SCHEMA', 'field', 'VECTOR', 'FLAT', '10', 'TYPE', + 'FLOAT32', 'DIM', '2', 'DISTANCE_METRIC', 'L2', 'INITIAL_CAP', '1000000', + 'BLOCK_SIZE', '1000' + ] + ); }); - it('with NOOFFSETS', () => { - assert.deepEqual( - transformArguments('index', {}, { - NOOFFSETS: true - }), - ['FT.CREATE', 'index', 'NOOFFSETS', 'SCHEMA'] - ); + it('HNSW algorithm', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.VECTOR, + ALGORITHM: SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW, + TYPE: 'FLOAT32', + DIM: 2, + DISTANCE_METRIC: 'L2', + INITIAL_CAP: 1000000, + M: 40, + EF_CONSTRUCTION: 250, + EF_RUNTIME: 20 + } + }), + [ + 'FT.CREATE', 'index', 'SCHEMA', 'field', 'VECTOR', 'HNSW', '14', 'TYPE', + 'FLOAT32', 'DIM', '2', 'DISTANCE_METRIC', 'L2', 'INITIAL_CAP', '1000000', + 'M', '40', 'EF_CONSTRUCTION', '250', 'EF_RUNTIME', '20' + ] + ); }); - - it('with NOHL', () => { - assert.deepEqual( - transformArguments('index', {}, { - NOHL: true - }), - ['FT.CREATE', 'index', 'NOHL', 'SCHEMA'] - ); + }); + + it('with AS', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + AS: 'as' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'AS', 'as', 'TEXT'] + ); + }); + + describe('with SORTABLE', () => { + it('true', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + SORTABLE: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE'] + ); }); - it('with NOFIELDS', () => { - assert.deepEqual( - transformArguments('index', {}, { - NOFIELDS: true - }), - ['FT.CREATE', 'index', 'NOFIELDS', 'SCHEMA'] - ); + it('UNF', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + SORTABLE: 'UNF' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'SORTABLE', 'UNF'] + ); }); + }); + + it('with NOINDEX', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + NOINDEX: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOINDEX'] + ); + }); + }); - it('with NOFREQS', () => { - assert.deepEqual( - transformArguments('index', {}, { - NOFREQS: true - }), - ['FT.CREATE', 'index', 'NOFREQS', 'SCHEMA'] - ); - }); + it('with ON', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + ON: 'HASH' + }), + ['FT.CREATE', 'index', 'ON', 'HASH', 'SCHEMA'] + ); + }); - it('with SKIPINITIALSCAN', () => { - assert.deepEqual( - transformArguments('index', {}, { - SKIPINITIALSCAN: true - }), - ['FT.CREATE', 'index', 'SKIPINITIALSCAN', 'SCHEMA'] - ); - }); + describe('with PREFIX', () => { + it('string', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + PREFIX: 'prefix' + }), + ['FT.CREATE', 'index', 'PREFIX', '1', 'prefix', 'SCHEMA'] + ); + }); + + it('Array', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + PREFIX: ['1', '2'] + }), + ['FT.CREATE', 'index', 'PREFIX', '2', '1', '2', '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'] - ); - }); - }); + it('with FILTER', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + FILTER: '@field != ""' + }), + ['FT.CREATE', 'index', 'FILTER', '@field != ""', 'SCHEMA'] + ); }); - testUtils.testWithClient('client.ft.create', async client => { - assert.equal( - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }), - 'OK' + it('with LANGUAGE', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + LANGUAGE: REDISEARCH_LANGUAGE.ARABIC + }), + ['FT.CREATE', 'index', 'LANGUAGE', REDISEARCH_LANGUAGE.ARABIC, 'SCHEMA'] + ); + }); + + it('with LANGUAGE_FIELD', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + LANGUAGE_FIELD: '@field' + }), + ['FT.CREATE', 'index', 'LANGUAGE_FIELD', '@field', 'SCHEMA'] + ); + }); + + it('with SCORE', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + SCORE: 1 + }), + ['FT.CREATE', 'index', 'SCORE', '1', 'SCHEMA'] + ); + }); + + it('with SCORE_FIELD', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + SCORE_FIELD: '@field' + }), + ['FT.CREATE', 'index', 'SCORE_FIELD', '@field', 'SCHEMA'] + ); + }); + + it('with MAXTEXTFIELDS', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + MAXTEXTFIELDS: true + }), + ['FT.CREATE', 'index', 'MAXTEXTFIELDS', 'SCHEMA'] + ); + }); + + it('with TEMPORARY', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + TEMPORARY: 1 + }), + ['FT.CREATE', 'index', 'TEMPORARY', '1', 'SCHEMA'] + ); + }); + + it('with NOOFFSETS', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + NOOFFSETS: true + }), + ['FT.CREATE', 'index', 'NOOFFSETS', 'SCHEMA'] + ); + }); + + it('with NOHL', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + NOHL: true + }), + ['FT.CREATE', 'index', 'NOHL', 'SCHEMA'] + ); + }); + + it('with NOFIELDS', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + NOFIELDS: true + }), + ['FT.CREATE', 'index', 'NOFIELDS', 'SCHEMA'] + ); + }); + + it('with NOFREQS', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + NOFREQS: true + }), + ['FT.CREATE', 'index', 'NOFREQS', 'SCHEMA'] + ); + }); + + it('with SKIPINITIALSCAN', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + SKIPINITIALSCAN: true + }), + ['FT.CREATE', 'index', 'SKIPINITIALSCAN', 'SCHEMA'] + ); + }); + + describe('with STOPWORDS', () => { + it('string', () => { + assert.deepEqual( + CREATE.transformArguments('index', {}, { + STOPWORDS: 'stopword' + }), + ['FT.CREATE', 'index', 'STOPWORDS', '1', 'stopword', 'SCHEMA'] ); - }, GLOBAL.SERVERS.OPEN); + }); + + it('Array', () => { + assert.deepEqual( + CREATE.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: SCHEMA_FIELD_TYPE.TEXT + }), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index 32440ede38e..bc7603fe70f 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -1,52 +1,291 @@ -import { pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisSearchLanguages, PropertyName, RediSearchSchema, pushSchema } from '.'; - -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; +import { RedisArgument, SimpleStringReply, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { PropertyName } from '.'; + +export const SCHEMA_FIELD_TYPE = { + TEXT: 'TEXT', + NUMERIC: 'NUMERIC', + GEO: 'GEO', + TAG: 'TAG', + VECTOR: 'VECTOR' +} as const; + +export type SchemaFieldType = typeof SCHEMA_FIELD_TYPE[keyof typeof SCHEMA_FIELD_TYPE]; + +type SchemaField< + T extends SchemaFieldType, + E = Record +> = T | ({ + type: T; + AS?: RedisArgument; +} & E); + +type SchemaCommonField< + T extends SchemaFieldType, + E = Record +> = SchemaField< + T, + ({ + SORTABLE?: boolean | 'UNF'; + NOINDEX?: boolean; + } & E) +>; + +export const SCHEMA_TEXT_FIELD_PHONETIC = { + DM_EN: 'dm:en', + DM_FR: 'dm:fr', + FM_PT: 'dm:pt', + DM_ES: 'dm:es' +} as const; + +export type SchemaTextFieldPhonetic = typeof SCHEMA_TEXT_FIELD_PHONETIC[keyof typeof SCHEMA_TEXT_FIELD_PHONETIC]; + +type SchemaTextField = SchemaCommonField; + +type SchemaNumericField = SchemaCommonField; + +type SchemaGeoField = SchemaCommonField; + +type SchemaTagField = SchemaCommonField; + +export const SCHEMA_VECTOR_FIELD_ALGORITHM = { + FLAT: 'FLAT', + HNSW: 'HNSW' +} as const; + +export type SchemaVectorFieldAlgorithm = typeof SCHEMA_VECTOR_FIELD_ALGORITHM[keyof typeof SCHEMA_VECTOR_FIELD_ALGORITHM]; + +type SchemaVectorField< + T extends SchemaVectorFieldAlgorithm, + A extends Record +> = SchemaField; + +type SchemaFlatVectorField = SchemaVectorField; + +type SchemaHNSWVectorField = SchemaVectorField; + +export interface RediSearchSchema { + [field: string]:( + SchemaTextField | + SchemaNumericField | + SchemaGeoField | + SchemaTagField | + SchemaFlatVectorField | + SchemaHNSWVectorField + ); +} + +export function pushSchema(args: CommandArguments, schema: RediSearchSchema) { + 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 SCHEMA_FIELD_TYPE.TEXT: + if (fieldOptions.NOSTEM) { + args.push('NOSTEM'); + } + + if (fieldOptions.WEIGHT) { + args.push('WEIGHT', fieldOptions.WEIGHT.toString()); + } + + if (fieldOptions.PHONETIC) { + args.push('PHONETIC', fieldOptions.PHONETIC); + } + + if (fieldOptions.WITHSUFFIXTRIE) { + args.push('WITHSUFFIXTRIE'); + } + + break; + + // case SchemaFieldTypes.NUMERIC: + // case SchemaFieldTypes.GEO: + // break; + + case SCHEMA_FIELD_TYPE.TAG: + if (fieldOptions.SEPARATOR) { + args.push('SEPARATOR', fieldOptions.SEPARATOR); + } + + if (fieldOptions.CASESENSITIVE) { + args.push('CASESENSITIVE'); + } + + if (fieldOptions.WITHSUFFIXTRIE) { + args.push('WITHSUFFIXTRIE'); + } + + break; + + case SCHEMA_FIELD_TYPE.VECTOR: + args.push(fieldOptions.ALGORITHM); + + const lengthIndex = args.push('') - 1; + + args.push( + 'TYPE', fieldOptions.TYPE, + 'DIM', fieldOptions.DIM.toString(), + 'DISTANCE_METRIC', fieldOptions.DISTANCE_METRIC + ); + + if (fieldOptions.INITIAL_CAP) { + args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString()); + } + + switch (fieldOptions.ALGORITHM) { + case SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT: + if (fieldOptions.BLOCK_SIZE) { + args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString()); + } + + break; + + case SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW: + if (fieldOptions.M) { + args.push('M', fieldOptions.M.toString()); + } + + if (fieldOptions.EF_CONSTRUCTION) { + args.push('EF_CONSTRUCTION', fieldOptions.EF_CONSTRUCTION.toString()); + } + + if (fieldOptions.EF_RUNTIME) { + args.push('EF_RUNTIME', fieldOptions.EF_RUNTIME.toString()); + } + + break; + } + args[lengthIndex] = (args.length - lengthIndex - 1).toString(); + + continue; // vector fields do not contain SORTABLE and NOINDEX options + } + + if (fieldOptions.SORTABLE) { + args.push('SORTABLE'); + + if (fieldOptions.SORTABLE === 'UNF') { + args.push('UNF'); + } + } + + if (fieldOptions.NOINDEX) { + args.push('NOINDEX'); + } + } } -export function transformArguments(index: string, schema: RediSearchSchema, options?: CreateOptions): Array { +export const REDISEARCH_LANGUAGE = { + 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' +} as const; + +export type RediSearchLanguage = typeof REDISEARCH_LANGUAGE[keyof typeof REDISEARCH_LANGUAGE]; + +export interface CreateOptions { + ON?: 'HASH' | 'JSON'; + PREFIX?: RedisVariadicArgument; + FILTER?: RedisArgument; + LANGUAGE?: RediSearchLanguage; + LANGUAGE_FIELD?: PropertyName; + SCORE?: number; + SCORE_FIELD?: PropertyName; + // PAYLOAD_FIELD?: string; + MAXTEXTFIELDS?: boolean; + TEMPORARY?: number; + NOOFFSETS?: boolean; + NOHL?: boolean; + NOFIELDS?: boolean; + NOFREQS?: boolean; + SKIPINITIALSCAN?: boolean; + STOPWORDS?: RedisVariadicArgument; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) { const args = ['FT.CREATE', index]; if (options?.ON) { - args.push('ON', options.ON); + args.push('ON', options.ON); } pushOptionalVariadicArgument(args, 'PREFIX', options?.PREFIX); if (options?.FILTER) { - args.push('FILTER', options.FILTER); + args.push('FILTER', options.FILTER); } if (options?.LANGUAGE) { - args.push('LANGUAGE', options.LANGUAGE); + args.push('LANGUAGE', options.LANGUAGE); } if (options?.LANGUAGE_FIELD) { - args.push('LANGUAGE_FIELD', options.LANGUAGE_FIELD); + args.push('LANGUAGE_FIELD', options.LANGUAGE_FIELD); } if (options?.SCORE) { - args.push('SCORE', options.SCORE.toString()); + args.push('SCORE', options.SCORE.toString()); } if (options?.SCORE_FIELD) { - args.push('SCORE_FIELD', options.SCORE_FIELD); + args.push('SCORE_FIELD', options.SCORE_FIELD); } // if (options?.PAYLOAD_FIELD) { @@ -54,31 +293,31 @@ export function transformArguments(index: string, schema: RediSearchSchema, opti // } if (options?.MAXTEXTFIELDS) { - args.push('MAXTEXTFIELDS'); + args.push('MAXTEXTFIELDS'); } if (options?.TEMPORARY) { - args.push('TEMPORARY', options.TEMPORARY.toString()); + args.push('TEMPORARY', options.TEMPORARY.toString()); } if (options?.NOOFFSETS) { - args.push('NOOFFSETS'); + args.push('NOOFFSETS'); } if (options?.NOHL) { - args.push('NOHL'); + args.push('NOHL'); } if (options?.NOFIELDS) { - args.push('NOFIELDS'); + args.push('NOFIELDS'); } if (options?.NOFREQS) { - args.push('NOFREQS'); + args.push('NOFREQS'); } if (options?.SKIPINITIALSCAN) { - args.push('SKIPINITIALSCAN'); + args.push('SKIPINITIALSCAN'); } pushOptionalVariadicArgument(args, 'STOPWORDS', options?.STOPWORDS); @@ -86,6 +325,6 @@ export function transformArguments(index: string, schema: RediSearchSchema, opti pushSchema(args, schema); return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 82808605deb..17fb67e0478 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -1,641 +1,642 @@ -import * as _LIST from './_LIST'; -import * as ALTER from './ALTER'; -import * as AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; -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 CURSOR_DEL from './CURSOR_DEL'; -import * as CURSOR_READ from './CURSOR_READ'; -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 PROFILESEARCH from './PROFILE_SEARCH'; -import * as PROFILEAGGREGATE from './PROFILE_AGGREGATE'; -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 { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import _LIST from './_LIST'; +// import ALTER from './ALTER'; +// import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; +// import AGGREGATE from './AGGREGATE'; +// import ALIASADD from './ALIASADD'; +// import ALIASDEL from './ALIASDEL'; +// import ALIASUPDATE from './ALIASUPDATE'; +// import CONFIG_GET from './CONFIG_GET'; +// import CONFIG_SET from './CONFIG_SET'; +import CREATE from './CREATE'; +// import CURSOR_DEL from './CURSOR_DEL'; +// import CURSOR_READ from './CURSOR_READ'; +import DICTADD from './DICTADD'; +import DICTDEL from './DICTDEL'; +import DICTDUMP from './DICTDUMP'; +import DROPINDEX from './DROPINDEX'; +import EXPLAIN from './EXPLAIN'; +import EXPLAINCLI from './EXPLAINCLI'; +// import INFO from './INFO'; +// import PROFILESEARCH from './PROFILE_SEARCH'; +// import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; +// import SEARCH from './SEARCH'; +// import SPELLCHECK from './SPELLCHECK'; +import SUGADD from './SUGADD'; +import SUGDEL from './SUGDEL'; +// import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; +// import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; +// import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; +// import SUGGET from './SUGGET'; +import SUGLEN from './SUGLEN'; +// import SYNDUMP from './SYNDUMP'; +// import SYNUPDATE from './SYNUPDATE'; +import TAGVALS from './TAGVALS'; +// import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { SearchOptions } from './SEARCH'; +import { CommandArguments } from '@redis/client/dist/lib/RESP/types'; export default { - _LIST, - _list: _LIST, - ALTER, - alter: ALTER, - AGGREGATE_WITHCURSOR, - aggregateWithCursor: AGGREGATE_WITHCURSOR, - 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, - CURSOR_DEL, - cursorDel: CURSOR_DEL, - CURSOR_READ, - cursorRead: CURSOR_READ, - DICTADD, - dictAdd: DICTADD, - DICTDEL, - dictDel: DICTDEL, - DICTDUMP, - dictDump: DICTDUMP, - DROPINDEX, - dropIndex: DROPINDEX, - EXPLAIN, - explain: EXPLAIN, - EXPLAINCLI, - explainCli: EXPLAINCLI, - INFO, - info: INFO, - PROFILESEARCH, - profileSearch: PROFILESEARCH, - PROFILEAGGREGATE, - profileAggregate: PROFILEAGGREGATE, - 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 + _LIST, + _list: _LIST, + // ALTER, + // alter: ALTER, + // AGGREGATE_WITHCURSOR, + // aggregateWithCursor: AGGREGATE_WITHCURSOR, + // 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, + // CURSOR_DEL, + // cursorDel: CURSOR_DEL, + // CURSOR_READ, + // cursorRead: CURSOR_READ, + DICTADD, + dictAdd: DICTADD, + DICTDEL, + dictDel: DICTDEL, + DICTDUMP, + dictDump: DICTDUMP, + DROPINDEX, + dropIndex: DROPINDEX, + EXPLAIN, + explain: EXPLAIN, + EXPLAINCLI, + explainCli: EXPLAINCLI, + // INFO, + // info: INFO, + // PROFILESEARCH, + // profileSearch: PROFILESEARCH, + // PROFILEAGGREGATE, + // profileAggregate: PROFILEAGGREGATE, + // SEARCH, + // search: SEARCH, + // SPELLCHECK, + // spellCheck: SPELLCHECK, + SUGADD, + sugAdd: SUGADD, + SUGDEL, + sugDel: SUGDEL, + // SUGGET_WITHPAYLOADS, + // sugGetWithPayloads: SUGGET_WITHPAYLOADS, + // SUGGET_WITHSCORES_WITHPAYLOADS, + // sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, + // SUGGET_WITHSCORES, + // sugGetWithScores: SUGGET_WITHSCORES, + // SUGGET, + // sugGet: SUGGET, + SUGLEN, + sugLen: SUGLEN, + // SYNDUMP, + // synDump: SYNDUMP, + // SYNUPDATE, + // synUpdate: SYNUPDATE, + TAGVALS, + tagVals: TAGVALS }; -export enum RedisSearchLanguages { - ARABIC = 'Arabic', - BASQUE = 'Basque', - CATALANA = 'Catalan', - DANISH = 'Danish', - DUTCH = 'Dutch', - ENGLISH = 'English', - FINNISH = 'Finnish', - FRENCH = 'French', - GERMAN = 'German', - GREEK = 'Greek', - HUNGARIAN = 'Hungarian', - INDONESAIN = 'Indonesian', - IRISH = 'Irish', - ITALIAN = 'Italian', - LITHUANIAN = 'Lithuanian', - NEPALI = 'Nepali', - NORWEIGAN = 'Norwegian', - PORTUGUESE = 'Portuguese', - ROMANIAN = 'Romanian', - RUSSIAN = 'Russian', - SPANISH = 'Spanish', - SWEDISH = 'Swedish', - TAMIL = 'Tamil', - TURKISH = 'Turkish', - CHINESE = 'Chinese' -} +// export enum RedisSearchLanguages { +// ARABIC = 'Arabic', +// BASQUE = 'Basque', +// CATALANA = 'Catalan', +// DANISH = 'Danish', +// DUTCH = 'Dutch', +// ENGLISH = 'English', +// FINNISH = 'Finnish', +// FRENCH = 'French', +// GERMAN = 'German', +// GREEK = 'Greek', +// HUNGARIAN = 'Hungarian', +// INDONESAIN = 'Indonesian', +// IRISH = 'Irish', +// ITALIAN = 'Italian', +// LITHUANIAN = 'Lithuanian', +// NEPALI = 'Nepali', +// NORWEIGAN = 'Norwegian', +// PORTUGUESE = 'Portuguese', +// ROMANIAN = 'Romanian', +// RUSSIAN = 'Russian', +// SPANISH = 'Spanish', +// SWEDISH = 'Swedish', +// TAMIL = 'Tamil', +// TURKISH = 'Turkish', +// CHINESE = 'Chinese' +// } export type PropertyName = `${'@' | '$.'}${string}`; export type SortByProperty = string | { - BY: string; - DIRECTION?: 'ASC' | 'DESC'; + BY: string; + DIRECTION?: 'ASC' | 'DESC'; }; export function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByProperty): void { - if (typeof sortBy === 'string') { - args.push(sortBy); - } else { - args.push(sortBy.BY); - - if (sortBy.DIRECTION) { - args.push(sortBy.DIRECTION); - } + 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: SortByProperty | 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); + 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; -} - -export enum SchemaFieldTypes { - TEXT = 'TEXT', - NUMERIC = 'NUMERIC', - GEO = 'GEO', - TAG = 'TAG', - VECTOR = 'VECTOR' -} + args[lengthBefore - 1] = (args.length - lengthBefore).toString(); -type CreateSchemaField< - T extends SchemaFieldTypes, - E = Record -> = T | ({ - type: T; - AS?: string; -} & E); - -type CreateSchemaCommonField< - T extends SchemaFieldTypes, - E = Record -> = CreateSchemaField< - T, - ({ - 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' + return args; } -type CreateSchemaTextField = CreateSchemaCommonField; - -type CreateSchemaNumericField = CreateSchemaCommonField; - -type CreateSchemaGeoField = CreateSchemaCommonField; - -type CreateSchemaTagField = CreateSchemaCommonField; - -export enum VectorAlgorithms { - FLAT = 'FLAT', - HNSW = 'HNSW' -} - -type CreateSchemaVectorField< - T extends VectorAlgorithms, - A extends Record -> = CreateSchemaField; - -type CreateSchemaFlatVectorField = CreateSchemaVectorField; - -type CreateSchemaHNSWVectorField = CreateSchemaVectorField; - -export interface RediSearchSchema { - [field: string]: - CreateSchemaTextField | - CreateSchemaNumericField | - CreateSchemaGeoField | - CreateSchemaTagField | - CreateSchemaFlatVectorField | - CreateSchemaHNSWVectorField; -} - -export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { - 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 SchemaFieldTypes.TEXT: - if (fieldOptions.NOSTEM) { - args.push('NOSTEM'); - } - - if (fieldOptions.WEIGHT) { - args.push('WEIGHT', fieldOptions.WEIGHT.toString()); - } - - if (fieldOptions.PHONETIC) { - args.push('PHONETIC', fieldOptions.PHONETIC); - } - - if (fieldOptions.WITHSUFFIXTRIE) { - args.push('WITHSUFFIXTRIE'); - } - - break; - - // case SchemaFieldTypes.NUMERIC: - // case SchemaFieldTypes.GEO: - // break; - - case SchemaFieldTypes.TAG: - if (fieldOptions.SEPARATOR) { - args.push('SEPARATOR', fieldOptions.SEPARATOR); - } - - if (fieldOptions.CASESENSITIVE) { - args.push('CASESENSITIVE'); - } - - if (fieldOptions.WITHSUFFIXTRIE) { - args.push('WITHSUFFIXTRIE'); - } - - break; - - case SchemaFieldTypes.VECTOR: - args.push(fieldOptions.ALGORITHM); - - pushArgumentsWithLength(args, () => { - args.push( - 'TYPE', fieldOptions.TYPE, - 'DIM', fieldOptions.DIM.toString(), - 'DISTANCE_METRIC', fieldOptions.DISTANCE_METRIC - ); - - if (fieldOptions.INITIAL_CAP) { - args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString()); - } - - switch (fieldOptions.ALGORITHM) { - case VectorAlgorithms.FLAT: - if (fieldOptions.BLOCK_SIZE) { - args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString()); - } - - break; - - case VectorAlgorithms.HNSW: - if (fieldOptions.M) { - args.push('M', fieldOptions.M.toString()); - } - - if (fieldOptions.EF_CONSTRUCTION) { - args.push('EF_CONSTRUCTION', fieldOptions.EF_CONSTRUCTION.toString()); - } +// export function pushArgumentsWithLength(args: CommandArguments, fn: (args: CommandArguments) => void) { +// const lengthIndex = args.push('') - 1; +// fn(args); +// args[lengthIndex] = (args.length - lengthIndex - 1).toString(); +// return args; +// } + +// export enum SchemaFieldTypes { +// TEXT = 'TEXT', +// NUMERIC = 'NUMERIC', +// GEO = 'GEO', +// TAG = 'TAG', +// VECTOR = 'VECTOR' +// } + +// type CreateSchemaField< +// T extends SchemaFieldTypes, +// E = Record +// > = T | ({ +// type: T; +// AS?: string; +// } & E); + +// type CreateSchemaCommonField< +// T extends SchemaFieldTypes, +// E = Record +// > = CreateSchemaField< +// T, +// ({ +// 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 = CreateSchemaCommonField; + +// type CreateSchemaNumericField = CreateSchemaCommonField; + +// type CreateSchemaGeoField = CreateSchemaCommonField; + +// type CreateSchemaTagField = CreateSchemaCommonField; + +// export enum VectorAlgorithms { +// FLAT = 'FLAT', +// HNSW = 'HNSW' +// } + +// type CreateSchemaVectorField< +// T extends VectorAlgorithms, +// A extends Record +// > = CreateSchemaField; + +// type CreateSchemaFlatVectorField = CreateSchemaVectorField; + +// type CreateSchemaHNSWVectorField = CreateSchemaVectorField; + +// export interface RediSearchSchema { +// [field: string]: +// CreateSchemaTextField | +// CreateSchemaNumericField | +// CreateSchemaGeoField | +// CreateSchemaTagField | +// CreateSchemaFlatVectorField | +// CreateSchemaHNSWVectorField; +// } + +// export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { +// 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 SchemaFieldTypes.TEXT: +// if (fieldOptions.NOSTEM) { +// args.push('NOSTEM'); +// } + +// if (fieldOptions.WEIGHT) { +// args.push('WEIGHT', fieldOptions.WEIGHT.toString()); +// } + +// if (fieldOptions.PHONETIC) { +// args.push('PHONETIC', fieldOptions.PHONETIC); +// } + +// if (fieldOptions.WITHSUFFIXTRIE) { +// args.push('WITHSUFFIXTRIE'); +// } + +// break; + +// // case SchemaFieldTypes.NUMERIC: +// // case SchemaFieldTypes.GEO: +// // break; + +// case SchemaFieldTypes.TAG: +// if (fieldOptions.SEPARATOR) { +// args.push('SEPARATOR', fieldOptions.SEPARATOR); +// } + +// if (fieldOptions.CASESENSITIVE) { +// args.push('CASESENSITIVE'); +// } + +// if (fieldOptions.WITHSUFFIXTRIE) { +// args.push('WITHSUFFIXTRIE'); +// } + +// break; + +// case SchemaFieldTypes.VECTOR: +// args.push(fieldOptions.ALGORITHM); + +// pushArgumentsWithLength(args, () => { +// args.push( +// 'TYPE', fieldOptions.TYPE, +// 'DIM', fieldOptions.DIM.toString(), +// 'DISTANCE_METRIC', fieldOptions.DISTANCE_METRIC +// ); + +// if (fieldOptions.INITIAL_CAP) { +// args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString()); +// } + +// switch (fieldOptions.ALGORITHM) { +// case VectorAlgorithms.FLAT: +// if (fieldOptions.BLOCK_SIZE) { +// args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString()); +// } + +// break; + +// case VectorAlgorithms.HNSW: +// if (fieldOptions.M) { +// args.push('M', fieldOptions.M.toString()); +// } + +// if (fieldOptions.EF_CONSTRUCTION) { +// args.push('EF_CONSTRUCTION', fieldOptions.EF_CONSTRUCTION.toString()); +// } + +// if (fieldOptions.EF_RUNTIME) { +// args.push('EF_RUNTIME', fieldOptions.EF_RUNTIME.toString()); +// } + +// break; +// } +// }); + +// continue; // vector fields do not contain SORTABLE and NOINDEX options +// } - if (fieldOptions.EF_RUNTIME) { - args.push('EF_RUNTIME', fieldOptions.EF_RUNTIME.toString()); - } +// if (fieldOptions.SORTABLE) { +// args.push('SORTABLE'); - break; - } - }); +// if (fieldOptions.SORTABLE === 'UNF') { +// args.push('UNF'); +// } +// } - continue; // vector fields do not contain SORTABLE and NOINDEX options - } - - if (fieldOptions.SORTABLE) { - args.push('SORTABLE'); - - if (fieldOptions.SORTABLE === 'UNF') { - args.push('UNF'); - } - } - - if (fieldOptions.NOINDEX) { - args.push('NOINDEX'); - } - } -} +// if (fieldOptions.NOINDEX) { +// args.push('NOINDEX'); +// } +// } +// } export type Params = Record; export function pushParamsArgs( - args: RedisCommandArguments, - params?: Params + args: RedisCommandArguments, + params?: Params ): RedisCommandArguments { - if (params) { - const enrties = Object.entries(params); - args.push('PARAMS', (enrties.length * 2).toString()); - for (const [key, value] of enrties) { - args.push(key, typeof value === 'number' ? value.toString() : value); - } + if (params) { + const enrties = Object.entries(params); + args.push('PARAMS', (enrties.length * 2).toString()); + for (const [key, value] of enrties) { + args.push(key, typeof value === 'number' ? value.toString() : value); } + } - return args; + return args; } export function pushSearchOptions( - args: RedisCommandArguments, - options?: SearchOptions + args: RedisCommandArguments, + options?: SearchOptions ): RedisCommandArguments { - if (options?.VERBATIM) { - args.push('VERBATIM'); - } - - if (options?.NOSTOPWORDS) { - args.push('NOSTOPWORDS'); - } - - // if (options?.WITHSCORES) { - // args.push('WITHSCORES'); - // } - - // if (options?.WITHPAYLOADS) { - // args.push('WITHPAYLOADS'); - // } - - pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); - pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); - pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); - - if (options?.SUMMARIZE) { - args.push('SUMMARIZE'); - - if (typeof options.SUMMARIZE === 'object') { - if (options.SUMMARIZE.FIELDS) { - args.push('FIELDS'); - pushVariadicArgument(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'); - pushVariadicArgument(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?.VERBATIM) { + args.push('VERBATIM'); + } + + if (options?.NOSTOPWORDS) { + args.push('NOSTOPWORDS'); + } + + // if (options?.WITHSCORES) { + // args.push('WITHSCORES'); + // } + + // if (options?.WITHPAYLOADS) { + // args.push('WITHPAYLOADS'); + // } + + pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); + pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); + pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); + + if (options?.SUMMARIZE) { + args.push('SUMMARIZE'); + + if (typeof options.SUMMARIZE === 'object') { + if (options.SUMMARIZE.FIELDS) { + args.push('FIELDS'); + pushVariadicArgument(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?.LANGUAGE) { - args.push('LANGUAGE', options.LANGUAGE); - } + if (options?.HIGHLIGHT) { + args.push('HIGHLIGHT'); - if (options?.EXPANDER) { - args.push('EXPANDER', options.EXPANDER); - } + if (typeof options.HIGHLIGHT === 'object') { + if (options.HIGHLIGHT.FIELDS) { + args.push('FIELDS'); + pushVariadicArgument(args, options.HIGHLIGHT.FIELDS); + } - 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'); - pushSortByProperty(args, options.SORTBY); + 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'); + pushSortByProperty(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() + ); + } - // if (options?.MSORTBY) { - // pushSortByArguments(args, 'MSORTBY', options.MSORTBY); - // } + if (options?.PARAMS) { + pushParamsArgs(args, options.PARAMS); + } - if (options?.LIMIT) { - args.push( - 'LIMIT', - options.LIMIT.from.toString(), - options.LIMIT.size.toString() - ); - } + if (options?.DIALECT) { + args.push('DIALECT', options.DIALECT.toString()); + } - if (options?.PARAMS) { - pushParamsArgs(args, options.PARAMS); - } + if (options?.RETURN?.length === 0) { + args.preserve = true; + } - if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); - } - - if (options?.RETURN?.length === 0) { - args.preserve = true; - } - - if (options?.TIMEOUT !== undefined) { - args.push('TIMEOUT', options.TIMEOUT.toString()); - } + if (options?.TIMEOUT !== undefined) { + args.push('TIMEOUT', options.TIMEOUT.toString()); + } - return args; + return args; } interface SearchDocumentValue { - [key: string]: string | number | null | Array | SearchDocumentValue; + [key: string]: string | number | null | Array | SearchDocumentValue; } export interface SearchReply { - total: number; - documents: Array<{ - id: string; - value: SearchDocumentValue; - }>; + total: number; + documents: Array<{ + id: string; + value: SearchDocumentValue; + }>; } export interface ProfileOptions { - LIMITED?: true; + LIMITED?: true; } export type ProfileRawReply = [ - results: T, - profile: [ - _: string, - TotalProfileTime: string, - _: string, - ParsingTime: string, - _: string, - PipelineCreationTime: string, - _: string, - IteratorsProfile: Array - ] + results: T, + profile: [ + _: string, + TotalProfileTime: string, + _: string, + ParsingTime: string, + _: string, + PipelineCreationTime: string, + _: string, + IteratorsProfile: Array + ] ]; export interface ProfileReply { - results: SearchReply | AGGREGATE.AggregateReply; - profile: ProfileData; + results: SearchReply | AGGREGATE.AggregateReply; + profile: ProfileData; } interface ChildIterator { - type?: string, - counter?: number, - term?: string, - size?: number, - time?: string, - childIterators?: Array + type?: string, + counter?: number, + term?: string, + size?: number, + time?: string, + childIterators?: Array } interface IteratorsProfile { - type?: string, - counter?: number, - queryType?: string, - time?: string, - childIterators?: Array + type?: string, + counter?: number, + queryType?: string, + time?: string, + childIterators?: Array } interface ProfileData { - totalProfileTime: string, - parsingTime: string, - pipelineCreationTime: string, - iteratorsProfile: IteratorsProfile + totalProfileTime: string, + parsingTime: string, + pipelineCreationTime: string, + iteratorsProfile: IteratorsProfile } -export function transformProfile(reply: Array): ProfileData{ - return { - totalProfileTime: reply[0][1], - parsingTime: reply[1][1], - pipelineCreationTime: reply[2][1], - iteratorsProfile: transformIterators(reply[3][1]) - }; +export function transformProfile(reply: Array): ProfileData { + return { + totalProfileTime: reply[0][1], + parsingTime: reply[1][1], + pipelineCreationTime: reply[2][1], + iteratorsProfile: transformIterators(reply[3][1]) + }; } function transformIterators(IteratorsProfile: Array): IteratorsProfile { - var res: IteratorsProfile = {}; - for (let i = 0; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i+1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Query type': - res.queryType = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } + var res: IteratorsProfile = {}; + for (let i = 0; i < IteratorsProfile.length; i += 2) { + const value = IteratorsProfile[i + 1]; + switch (IteratorsProfile[i]) { + case 'Type': + res.type = value; + break; + case 'Counter': + res.counter = value; + break; + case 'Time': + res.time = value; + break; + case 'Query type': + res.queryType = value; + break; + case 'Child iterators': + res.childIterators = value.map(transformChildIterators); + break; } + } - return res; + return res; } function transformChildIterators(IteratorsProfile: Array): ChildIterator { - var res: ChildIterator = {}; - for (let i = 1; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i+1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Size': - res.size = value; - break; - case 'Term': - res.term = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } + var res: ChildIterator = {}; + for (let i = 1; i < IteratorsProfile.length; i += 2) { + const value = IteratorsProfile[i + 1]; + switch (IteratorsProfile[i]) { + case 'Type': + res.type = value; + break; + case 'Counter': + res.counter = value; + break; + case 'Time': + res.time = value; + break; + case 'Size': + res.size = value; + break; + case 'Term': + res.term = value; + break; + case 'Child iterators': + res.childIterators = value.map(transformChildIterators); + break; } + } - return res; + return res; } From 689c6a576c325237ae0e50cdb9108608fb23c4a9 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 27 Jul 2023 12:59:25 -0400 Subject: [PATCH 202/325] remove .only --- packages/search/lib/commands/CREATE.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 021d8fa4291..37aa06011bf 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import CREATE, { SCHEMA_FIELD_TYPE, SCHEMA_TEXT_FIELD_PHONETIC, SCHEMA_VECTOR_FIELD_ALGORITHM, REDISEARCH_LANGUAGE } from './CREATE'; -describe.only('FT.CREATE', () => { +describe('FT.CREATE', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( From cf38f512b8ea6c5bca9739c404fb5949eb357d94 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 31 Jul 2023 17:34:45 -0400 Subject: [PATCH 203/325] some RediSearch commands --- docs/v4-to-v5.md | 1 + packages/search/lib/commands/ALIASADD.spec.ts | 29 ++-- packages/search/lib/commands/ALIASADD.ts | 13 +- packages/search/lib/commands/ALIASDEL.spec.ts | 30 ++-- packages/search/lib/commands/ALIASDEL.ts | 13 +- .../search/lib/commands/ALIASUPDATE.spec.ts | 29 ++-- packages/search/lib/commands/ALIASUPDATE.ts | 13 +- packages/search/lib/commands/CREATE.ts | 4 +- .../search/lib/commands/CURSOR_DEL.spec.ts | 53 ++++--- packages/search/lib/commands/CURSOR_DEL.ts | 22 ++- packages/search/lib/commands/DICTADD.spec.ts | 2 +- packages/search/lib/commands/DICTADD.ts | 2 +- packages/search/lib/commands/DICTDEL.spec.ts | 2 +- packages/search/lib/commands/DICTDEL.ts | 2 +- packages/search/lib/commands/DICTDUMP.spec.ts | 12 +- .../search/lib/commands/DROPINDEX.spec.ts | 18 +-- packages/search/lib/commands/DROPINDEX.ts | 2 +- .../search/lib/commands/SPELLCHECK.spec.ts | 136 +++++++++--------- packages/search/lib/commands/SPELLCHECK.ts | 91 ++++++------ packages/search/lib/commands/SUGADD.spec.ts | 2 +- packages/search/lib/commands/SUGADD.ts | 2 +- packages/search/lib/commands/SUGDEL.spec.ts | 4 +- packages/search/lib/commands/SUGDEL.ts | 2 +- packages/search/lib/commands/SUGGET.spec.ts | 72 +++++----- packages/search/lib/commands/SUGGET.ts | 25 ++-- packages/search/lib/commands/SUGLEN.spec.ts | 2 +- packages/search/lib/commands/SYNDUMP.spec.ts | 36 ++--- packages/search/lib/commands/SYNDUMP.ts | 25 +++- .../search/lib/commands/SYNUPDATE.spec.ts | 64 +++++---- packages/search/lib/commands/SYNUPDATE.ts | 31 ++-- packages/search/lib/commands/TAGVALS.spec.ts | 18 +-- packages/search/lib/commands/TAGVALS.ts | 2 +- packages/search/lib/commands/index.ts | 48 +++---- packages/search/package.json | 3 +- 34 files changed, 447 insertions(+), 363 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index c500815cd66..ffb95cef1f8 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -182,6 +182,7 @@ Some command arguments/replies have changed to align more closely to data types - `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing] - `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` +- `TS.SYNUPDATE`: `Array>` -> `Record>` [^enum-to-constants]: TODO diff --git a/packages/search/lib/commands/ALIASADD.spec.ts b/packages/search/lib/commands/ALIASADD.spec.ts index 7bb2452838b..22a895cae68 100644 --- a/packages/search/lib/commands/ALIASADD.spec.ts +++ b/packages/search/lib/commands/ALIASADD.spec.ts @@ -1,11 +1,24 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASADD'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASADD from './ALIASADD'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASADD', 'alias', 'index'] - ); - }); +describe('FT.ALIASADD', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASADD.transformArguments('alias', 'index'), + ['FT.ALIASADD', 'alias', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.aliasAdd', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasAdd('alias', 'index') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASADD.ts b/packages/search/lib/commands/ALIASADD.ts index 552c1add695..648e1fef97e 100644 --- a/packages/search/lib/commands/ALIASADD.ts +++ b/packages/search/lib/commands/ALIASADD.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASADD', name, index]; -} +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument, index: RedisArgument) { + return ['FT.ALIASADD', alias, index]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASDEL.spec.ts b/packages/search/lib/commands/ALIASDEL.spec.ts index 5255ba835db..0a308bd7691 100644 --- a/packages/search/lib/commands/ALIASDEL.spec.ts +++ b/packages/search/lib/commands/ALIASDEL.spec.ts @@ -1,11 +1,25 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASDEL'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASDEL from './ALIASDEL'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASDEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASDEL', 'alias', 'index'] - ); - }); +describe('FT.ALIASDEL', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASDEL.transformArguments('alias'), + ['FT.ALIASDEL', 'alias'] + ); + }); + + testUtils.testWithClient('client.ft.aliasAdd', async client => { + const [, , reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasAdd('alias', 'index'), + client.ft.aliasDel('alias') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASDEL.ts b/packages/search/lib/commands/ALIASDEL.ts index 434b4df3dea..40cc45a19de 100644 --- a/packages/search/lib/commands/ALIASDEL.ts +++ b/packages/search/lib/commands/ALIASDEL.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASDEL', name, index]; -} +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument) { + return ['FT.ALIASDEL', alias]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASUPDATE.spec.ts b/packages/search/lib/commands/ALIASUPDATE.spec.ts index 79421b1a20d..cc0d1439ac9 100644 --- a/packages/search/lib/commands/ALIASUPDATE.spec.ts +++ b/packages/search/lib/commands/ALIASUPDATE.spec.ts @@ -1,11 +1,24 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASUPDATE'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASUPDATE from './ALIASUPDATE'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASUPDATE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASUPDATE', 'alias', 'index'] - ); - }); +describe('FT.ALIASUPDATE', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASUPDATE.transformArguments('alias', 'index'), + ['FT.ALIASUPDATE', 'alias', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.aliasUpdate', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasUpdate('alias', 'index') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASUPDATE.ts b/packages/search/lib/commands/ALIASUPDATE.ts index ac64ef57c3f..e2b72cfe649 100644 --- a/packages/search/lib/commands/ALIASUPDATE.ts +++ b/packages/search/lib/commands/ALIASUPDATE.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASUPDATE', name, index]; -} +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument, index: RedisArgument) { + return ['FT.ALIASUPDATE', alias, index]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index bc7603fe70f..98a616f04ef 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -257,8 +257,8 @@ export interface CreateOptions { } export default { - FIRST_KEY_INDEX: 1, - IS_READ_ONLY: false, + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) { const args = ['FT.CREATE', index]; diff --git a/packages/search/lib/commands/CURSOR_DEL.spec.ts b/packages/search/lib/commands/CURSOR_DEL.spec.ts index d89725ef80d..c5fad7e8e89 100644 --- a/packages/search/lib/commands/CURSOR_DEL.spec.ts +++ b/packages/search/lib/commands/CURSOR_DEL.spec.ts @@ -1,33 +1,32 @@ import { strict as assert } from 'assert'; -import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CURSOR_DEL'; +import CURSOR_DEL from './CURSOR_DEL'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('CURSOR DEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index', 0), - ['FT.CURSOR', 'DEL', 'index', '0'] - ); - }); +describe('FT.CURSOR DEL', () => { + it('transformArguments', () => { + assert.deepEqual( + CURSOR_DEL.transformArguments('index', '0'), + ['FT.CURSOR', 'DEL', 'index', '0'] + ); + }); - testUtils.testWithClient('client.ft.cursorDel', async client => { - const [ ,, { cursor } ] = await Promise.all([ - client.ft.create('idx', { - field: { - type: SchemaFieldTypes.TEXT - } - }), - client.hSet('key', 'field', 'value'), - client.ft.aggregateWithCursor('idx', '*', { - COUNT: 1 - }) - ]); + testUtils.testWithClient('client.ft.cursorDel', async client => { + const [, , { cursor }] = await Promise.all([ + client.ft.create('idx', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT + } + }), + client.hSet('key', 'field', 'value'), + client.ft.aggregateWithCursor('idx', '*', { + COUNT: 1 + }) + ]); - - assert.equal( - await client.ft.cursorDel('idx', cursor), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ft.cursorDel('idx', cursor), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/CURSOR_DEL.ts b/packages/search/lib/commands/CURSOR_DEL.ts index 22c850f2a89..7c134454bef 100644 --- a/packages/search/lib/commands/CURSOR_DEL.ts +++ b/packages/search/lib/commands/CURSOR_DEL.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(index: RedisCommandArgument, cursorId: number) { - return [ - 'FT.CURSOR', - 'DEL', - index, - cursorId.toString() - ]; -} - -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, cursorId: RedisArgument) { + return ['FT.CURSOR', 'DEL', index, cursorId]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/DICTADD.spec.ts b/packages/search/lib/commands/DICTADD.spec.ts index 6aa3c862f2f..6baeb6299a6 100644 --- a/packages/search/lib/commands/DICTADD.spec.ts +++ b/packages/search/lib/commands/DICTADD.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTADD from './DICTADD'; -describe('DICTADD', () => { +describe('FT.DICTADD', () => { describe('transformArguments', () => { it('string', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/DICTADD.ts b/packages/search/lib/commands/DICTADD.ts index a90e87dcf70..f633d58b1f3 100644 --- a/packages/search/lib/commands/DICTADD.ts +++ b/packages/search/lib/commands/DICTADD.ts @@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTADD', dictionary], term); }, diff --git a/packages/search/lib/commands/DICTDEL.spec.ts b/packages/search/lib/commands/DICTDEL.spec.ts index 9d42944d62b..328cc98a34e 100644 --- a/packages/search/lib/commands/DICTDEL.spec.ts +++ b/packages/search/lib/commands/DICTDEL.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDEL from './DICTDEL'; -describe('DICTDEL', () => { +describe('FT.DICTDEL', () => { describe('transformArguments', () => { it('string', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/DICTDEL.ts b/packages/search/lib/commands/DICTDEL.ts index e639d3427b0..087211751ee 100644 --- a/packages/search/lib/commands/DICTDEL.ts +++ b/packages/search/lib/commands/DICTDEL.ts @@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTDEL', dictionary], term); }, diff --git a/packages/search/lib/commands/DICTDUMP.spec.ts b/packages/search/lib/commands/DICTDUMP.spec.ts index 0e50a4a373f..bb7eb3db313 100644 --- a/packages/search/lib/commands/DICTDUMP.spec.ts +++ b/packages/search/lib/commands/DICTDUMP.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDUMP from './DICTDUMP'; -describe('DICTDUMP', () => { +describe('FT.DICTDUMP', () => { it('transformArguments', () => { assert.deepEqual( DICTDUMP.transformArguments('dictionary'), @@ -11,11 +11,11 @@ describe('DICTDUMP', () => { }); testUtils.testWithClient('client.ft.dictDump', async client => { - await client.ft.dictAdd('dictionary', 'string') + const [, reply] = await Promise.all([ + client.ft.dictAdd('dictionary', 'string'), + client.ft.dictDump('dictionary') + ]); - assert.deepEqual( - await client.ft.dictDump('dictionary'), - ['string'] - ); + assert.deepEqual(reply, ['string']); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/DROPINDEX.spec.ts b/packages/search/lib/commands/DROPINDEX.spec.ts index cb6ca192cd4..67742c16a1a 100644 --- a/packages/search/lib/commands/DROPINDEX.spec.ts +++ b/packages/search/lib/commands/DROPINDEX.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { SchemaFieldTypes } from '.'; import DROPINDEX from './DROPINDEX'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('DROPINDEX', () => { +describe('FT.DROPINDEX', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -21,13 +21,13 @@ describe('DROPINDEX', () => { }); testUtils.testWithClient('client.ft.dropIndex', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.dropIndex('index') + ]); - assert.equal( - await client.ft.dropIndex('index'), - 'OK' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/DROPINDEX.ts b/packages/search/lib/commands/DROPINDEX.ts index fe25a79e97b..64fe9711e7f 100644 --- a/packages/search/lib/commands/DROPINDEX.ts +++ b/packages/search/lib/commands/DROPINDEX.ts @@ -6,7 +6,7 @@ export interface FtDropIndexOptions { export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, options?: FtDropIndexOptions) { const args = ['FT.DROPINDEX', index]; diff --git a/packages/search/lib/commands/SPELLCHECK.spec.ts b/packages/search/lib/commands/SPELLCHECK.spec.ts index acabbe8a87c..a2261004dc8 100644 --- a/packages/search/lib/commands/SPELLCHECK.spec.ts +++ b/packages/search/lib/commands/SPELLCHECK.spec.ts @@ -1,80 +1,80 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; -import { transformArguments } from './SPELLCHECK'; +import SPELLCHECK 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'] - ); - }); - }); +describe('FT.SPELLCHECK', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query'), + ['FT.SPELLCHECK', 'index', 'query'] + ); + }); - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - DIALECT: 1 - }), - ['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1'] - ); - }); + it('with DISTANCE', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + DISTANCE: 2 + }), + ['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2'] + ); }); - testUtils.testWithClient('client.ft.spellCheck', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }), - client.hSet('key', 'field', 'query') - ]); + describe('with TERMS', () => { + it('single', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + TERMS: { + mode: 'INCLUDE', + dictionary: 'dictionary' + } + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary'] + ); + }); + it('multiple', () => { assert.deepEqual( - await client.ft.spellCheck('index', 'quer'), - [{ - term: 'quer', - suggestions: [{ - score: 1, - suggestion: 'query' - }] + SPELLCHECK.transformArguments('index', 'query', { + TERMS: [{ + mode: 'INCLUDE', + dictionary: 'include' + }, { + mode: 'EXCLUDE', + dictionary: 'exclude' }] + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude'] ); - }, GLOBAL.SERVERS.OPEN); + }); + }); + + it('with DIALECT', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + DIALECT: 1 + }), + ['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1'] + ); + }); + }); + + testUtils.testWithClient('client.ft.spellCheck', async client => { + const [,, reply] = await Promise.all([ + client.ft.create('index', { + field: SchemaFieldTypes.TEXT + }), + client.hSet('key', 'field', 'query'), + client.ft.spellCheck('index', 'quer') + ]); + + assert.deepEqual(reply, [{ + 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 index c9317a8b4fe..720ed02547f 100644 --- a/packages/search/lib/commands/SPELLCHECK.ts +++ b/packages/search/lib/commands/SPELLCHECK.ts @@ -1,62 +1,69 @@ -interface SpellCheckTerms { - mode: 'INCLUDE' | 'EXCLUDE'; - dictionary: string; +import { RedisArgument, CommandArguments, Command } from '@redis/client/dist/lib/RESP/types'; + +export interface Terms { + mode: 'INCLUDE' | 'EXCLUDE'; + dictionary: RedisArgument; } -interface SpellCheckOptions { - DISTANCE?: number; - TERMS?: SpellCheckTerms | Array; - DIALECT?: number; +export interface FtSpellCheckOptions { + DISTANCE?: number; + TERMS?: Terms | Array; + DIALECT?: number; } -export function transformArguments(index: string, query: string, options?: SpellCheckOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSpellCheckOptions) { const args = ['FT.SPELLCHECK', index, query]; if (options?.DISTANCE) { - args.push('DISTANCE', options.DISTANCE.toString()); + 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); + if (Array.isArray(options.TERMS)) { + for (const term of options.TERMS) { + pushTerms(args, term); } + } else { + pushTerms(args, options.TERMS); + } } if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); + args.push('DIALECT', options.DIALECT.toString()); } return args; -} + }, + // TODO + // type SpellCheckRawReply = Array<[ + // _: string, + // term: string, + // suggestions: Array<[score: string, suggestion: string]> + // ]>; -function pushTerms(args: Array, { mode, dictionary }: SpellCheckTerms): void { - args.push('TERMS', mode, dictionary); -} + // 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 + // })) + // })); + // } + transformReply: undefined as unknown as () => any +} as const satisfies Command; -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 - })) - })); +function pushTerms(args: CommandArguments, { mode, dictionary }: Terms) { + args.push('TERMS', mode, dictionary); } diff --git a/packages/search/lib/commands/SUGADD.spec.ts b/packages/search/lib/commands/SUGADD.spec.ts index 391fa51d615..2196ce89e79 100644 --- a/packages/search/lib/commands/SUGADD.spec.ts +++ b/packages/search/lib/commands/SUGADD.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGADD from './SUGADD'; -describe('SUGADD', () => { +describe('FT.SUGADD', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/SUGADD.ts b/packages/search/lib/commands/SUGADD.ts index 490dd6d1b35..c4cc1fb53e8 100644 --- a/packages/search/lib/commands/SUGADD.ts +++ b/packages/search/lib/commands/SUGADD.ts @@ -7,7 +7,7 @@ export interface FtSugAddOptions { export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) { const args = ['FT.SUGADD', key, string, score.toString()]; diff --git a/packages/search/lib/commands/SUGDEL.spec.ts b/packages/search/lib/commands/SUGDEL.spec.ts index 4d0b72b6d9c..5f86ea80b63 100644 --- a/packages/search/lib/commands/SUGDEL.spec.ts +++ b/packages/search/lib/commands/SUGDEL.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGDEL from './SUGDEL'; -describe('SUGDEL', () => { +describe('FT.SUGDEL', () => { it('transformArguments', () => { assert.deepEqual( SUGDEL.transformArguments('key', 'string'), @@ -13,7 +13,7 @@ describe('SUGDEL', () => { testUtils.testWithClient('client.ft.sugDel', async client => { assert.equal( await client.ft.sugDel('key', 'string'), - false + 0 ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SUGDEL.ts b/packages/search/lib/commands/SUGDEL.ts index 9311e14c026..ed9a8aef24f 100644 --- a/packages/search/lib/commands/SUGDEL.ts +++ b/packages/search/lib/commands/SUGDEL.ts @@ -2,7 +2,7 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument) { return ['FT.SUGDEL', key, string]; }, diff --git a/packages/search/lib/commands/SUGGET.spec.ts b/packages/search/lib/commands/SUGGET.spec.ts index c24c2ff0863..2553077dc6c 100644 --- a/packages/search/lib/commands/SUGGET.spec.ts +++ b/packages/search/lib/commands/SUGGET.spec.ts @@ -1,46 +1,46 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGGET'; +import SUGGET from './SUGGET'; -describe('SUGGET', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', 'prefix'), - ['FT.SUGGET', 'key', 'prefix'] - ); - }); +describe('FT.SUGGET', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SUGGET.transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix'] + ); + }); - it('with FUZZY', () => { - assert.deepEqual( - transformArguments('key', 'prefix', { FUZZY: true }), - ['FT.SUGGET', 'key', 'prefix', 'FUZZY'] - ); - }); + it('with FUZZY', () => { + assert.deepEqual( + SUGGET.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'] - ); - }); + it('with MAX', () => { + assert.deepEqual( + SUGGET.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); + 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); + testUtils.testWithClient('with suggestions', async client => { + const [, reply] = await Promise.all([ + client.ft.sugAdd('key', 'string', 1), + client.ft.sugGet('key', 's') + ]); - assert.deepEqual( - await client.ft.sugGet('key', 'string'), - ['string'] - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.deepEqual(reply, ['string']); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts index 558cedeaa08..2dc360da3e7 100644 --- a/packages/search/lib/commands/SUGGET.ts +++ b/packages/search/lib/commands/SUGGET.ts @@ -1,22 +1,25 @@ -export const IS_READ_ONLY = true; +import { ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export interface SugGetOptions { - FUZZY?: true; - MAX?: number; +export interface FtSugGetOptions { + FUZZY?: boolean; + MAX?: number; } -export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) { const args = ['FT.SUGGET', key, prefix]; if (options?.FUZZY) { - args.push('FUZZY'); + args.push('FUZZY'); } - if (options?.MAX) { - args.push('MAX', options.MAX.toString()); + if (options?.MAX !== undefined) { + args.push('MAX', options.MAX.toString()); } return args; -} - -export declare function transformReply(): null | Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGLEN.spec.ts b/packages/search/lib/commands/SUGLEN.spec.ts index 88a140b770c..6238b7a3241 100644 --- a/packages/search/lib/commands/SUGLEN.spec.ts +++ b/packages/search/lib/commands/SUGLEN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGLEN from './SUGLEN'; -describe('SUGLEN', () => { +describe('FT.SUGLEN', () => { it('transformArguments', () => { assert.deepEqual( SUGLEN.transformArguments('key'), diff --git a/packages/search/lib/commands/SYNDUMP.spec.ts b/packages/search/lib/commands/SYNDUMP.spec.ts index 472db54bcf8..4b9a3dfae02 100644 --- a/packages/search/lib/commands/SYNDUMP.spec.ts +++ b/packages/search/lib/commands/SYNDUMP.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SYNDUMP'; -import { SchemaFieldTypes } from '.'; +import SYNDUMP from './SYNDUMP'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('SYNDUMP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index'), - ['FT.SYNDUMP', 'index'] - ); - }); +describe('FT.SYNDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + SYNDUMP.transformArguments('index'), + ['FT.SYNDUMP', 'index'] + ); + }); - testUtils.testWithClient('client.ft.synDump', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + testUtils.testWithClient('client.ft.synDump', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.synDump('index') + ]); - assert.deepEqual( - await client.ft.synDump('index'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, []); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SYNDUMP.ts b/packages/search/lib/commands/SYNDUMP.ts index 5f1e71aaf78..2fe7540fda5 100644 --- a/packages/search/lib/commands/SYNDUMP.ts +++ b/packages/search/lib/commands/SYNDUMP.ts @@ -1,5 +1,22 @@ -export function transformArguments(index: string): Array { - return ['FT.SYNDUMP', index]; -} +import { RedisArgument, MapReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument) { + return ['FT.SYNDUMP', index]; + }, + transformReply: { + 2: (reply: UnwrapReply>>) => { + const result: Record> = {}; + let i = 0; + while (i < reply.length) { + const key = (reply[i++] as unknown as UnwrapReply).toString(), + value = reply[i++] as unknown as ArrayReply; + result[key] = value; + } + return result; + }, + 3: undefined as unknown as () => MapReply> + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/SYNUPDATE.spec.ts b/packages/search/lib/commands/SYNUPDATE.spec.ts index 19ac9b85e54..1dfde97521f 100644 --- a/packages/search/lib/commands/SYNUPDATE.spec.ts +++ b/packages/search/lib/commands/SYNUPDATE.spec.ts @@ -1,40 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SYNUPDATE'; -import { SchemaFieldTypes } from '.'; +import SYNUPDATE from './SYNUPDATE'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('SYNUPDATE', () => { - describe('transformArguments', () => { - it('single term', () => { - assert.deepEqual( - transformArguments('index', 'groupId', 'term'), - ['FT.SYNUPDATE', 'index', 'groupId', 'term'] - ); - }); +describe('FT.SYNUPDATE', () => { + describe('transformArguments', () => { + it('single term', () => { + assert.deepEqual( + SYNUPDATE.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('multiple terms', () => { + assert.deepEqual( + SYNUPDATE.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'] - ); - }); + it('with SKIPINITIALSCAN', () => { + assert.deepEqual( + SYNUPDATE.transformArguments('index', 'groupId', 'term', { + SKIPINITIALSCAN: true + }), + ['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term'] + ); }); + }); - testUtils.testWithClient('client.ft.synUpdate', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + testUtils.testWithClient('client.ft.synUpdate', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.synUpdate('index', 'groupId', 'term') + ]); - assert.equal( - await client.ft.synUpdate('index', 'groupId', 'term'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SYNUPDATE.ts b/packages/search/lib/commands/SYNUPDATE.ts index 80582759c47..926d8e58e1c 100644 --- a/packages/search/lib/commands/SYNUPDATE.ts +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -1,23 +1,26 @@ -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -interface SynUpdateOptions { - SKIPINITIALSCAN?: true; +export interface FtSynUpdateOptions { + SKIPINITIALSCAN?: boolean; } -export function transformArguments( - index: string, - groupId: string, - terms: string | Array, - options?: SynUpdateOptions -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments( + index: RedisArgument, + groupId: RedisArgument, + terms: RedisVariadicArgument, + options?: FtSynUpdateOptions + ) { const args = ['FT.SYNUPDATE', index, groupId]; if (options?.SKIPINITIALSCAN) { - args.push('SKIPINITIALSCAN'); + args.push('SKIPINITIALSCAN'); } return pushVariadicArguments(args, terms); -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/TAGVALS.spec.ts b/packages/search/lib/commands/TAGVALS.spec.ts index 52bb66c1ce7..5962beecfeb 100644 --- a/packages/search/lib/commands/TAGVALS.spec.ts +++ b/packages/search/lib/commands/TAGVALS.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { SchemaFieldTypes } from '.'; import TAGVALS from './TAGVALS'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('TAGVALS', () => { +describe('FT.TAGVALS', () => { it('transformArguments', () => { assert.deepEqual( TAGVALS.transformArguments('index', '@field'), @@ -12,13 +12,13 @@ describe('TAGVALS', () => { }); testUtils.testWithClient('client.ft.tagVals', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TAG - }); + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TAG + }), + client.ft.tagVals('index', 'field') + ]); - assert.deepEqual( - await client.ft.tagVals('index', 'field'), - [] - ); + assert.deepEqual(reply, []); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/TAGVALS.ts b/packages/search/lib/commands/TAGVALS.ts index 7c58a1f9d11..8a6e73c97b8 100644 --- a/packages/search/lib/commands/TAGVALS.ts +++ b/packages/search/lib/commands/TAGVALS.ts @@ -2,7 +2,7 @@ import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@ export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, fieldName: RedisArgument) { return ['FT.TAGVALS', index, fieldName]; }, diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 17fb67e0478..d4a5c28da78 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -2,13 +2,13 @@ import _LIST from './_LIST'; // import ALTER from './ALTER'; // import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; // import AGGREGATE from './AGGREGATE'; -// import ALIASADD from './ALIASADD'; -// import ALIASDEL from './ALIASDEL'; -// import ALIASUPDATE from './ALIASUPDATE'; +import ALIASADD from './ALIASADD'; +import ALIASDEL from './ALIASDEL'; +import ALIASUPDATE from './ALIASUPDATE'; // import CONFIG_GET from './CONFIG_GET'; // import CONFIG_SET from './CONFIG_SET'; import CREATE from './CREATE'; -// import CURSOR_DEL from './CURSOR_DEL'; +import CURSOR_DEL from './CURSOR_DEL'; // import CURSOR_READ from './CURSOR_READ'; import DICTADD from './DICTADD'; import DICTDEL from './DICTDEL'; @@ -20,16 +20,16 @@ import EXPLAINCLI from './EXPLAINCLI'; // import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; // import SEARCH from './SEARCH'; -// import SPELLCHECK from './SPELLCHECK'; +import SPELLCHECK from './SPELLCHECK'; import SUGADD from './SUGADD'; import SUGDEL from './SUGDEL'; // import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; // import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; // import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; -// import SUGGET from './SUGGET'; +import SUGGET from './SUGGET'; import SUGLEN from './SUGLEN'; -// import SYNDUMP from './SYNDUMP'; -// import SYNUPDATE from './SYNUPDATE'; +import SYNDUMP from './SYNDUMP'; +import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; @@ -45,20 +45,20 @@ export default { // aggregateWithCursor: AGGREGATE_WITHCURSOR, // AGGREGATE, // aggregate: AGGREGATE, - // ALIASADD, - // aliasAdd: ALIASADD, - // ALIASDEL, - // aliasDel: ALIASDEL, - // ALIASUPDATE, - // aliasUpdate: ALIASUPDATE, + ALIASADD, + aliasAdd: ALIASADD, + ALIASDEL, + aliasDel: ALIASDEL, + ALIASUPDATE, + aliasUpdate: ALIASUPDATE, // CONFIG_GET, // configGet: CONFIG_GET, // CONFIG_SET, // configSet: CONFIG_SET, CREATE, create: CREATE, - // CURSOR_DEL, - // cursorDel: CURSOR_DEL, + CURSOR_DEL, + cursorDel: CURSOR_DEL, // CURSOR_READ, // cursorRead: CURSOR_READ, DICTADD, @@ -81,8 +81,8 @@ export default { // profileAggregate: PROFILEAGGREGATE, // SEARCH, // search: SEARCH, - // SPELLCHECK, - // spellCheck: SPELLCHECK, + SPELLCHECK, + spellCheck: SPELLCHECK, SUGADD, sugAdd: SUGADD, SUGDEL, @@ -93,14 +93,14 @@ export default { // sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, // SUGGET_WITHSCORES, // sugGetWithScores: SUGGET_WITHSCORES, - // SUGGET, - // sugGet: SUGGET, + SUGGET, + sugGet: SUGGET, SUGLEN, sugLen: SUGLEN, - // SYNDUMP, - // synDump: SYNDUMP, - // SYNUPDATE, - // synUpdate: SYNUPDATE, + SYNDUMP, + synDump: SYNDUMP, + SYNUPDATE, + synUpdate: SYNUPDATE, TAGVALS, tagVals: TAGVALS }; diff --git a/packages/search/package.json b/packages/search/package.json index 29cb9fc8c44..18a2fc8b48c 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -5,7 +5,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" From 2136418f1a2d2ba267ef7218785f2f58fa52a78b Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 31 Jul 2023 17:35:51 -0400 Subject: [PATCH 204/325] wip --- packages/json/test.js | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 packages/json/test.js diff --git a/packages/json/test.js b/packages/json/test.js deleted file mode 100644 index f9845cc4304..00000000000 --- a/packages/json/test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { createClient } from '@redis/client'; -import RedisJSON from '.'; - -const client = createClient({ - modules: { - json: RedisJSON, - JSON: RedisJSON - } -}); - -client.JSON. \ No newline at end of file From fd016ee1b2e8cc55556da31958bf7c37ac438ff0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 1 Aug 2023 14:29:34 -0400 Subject: [PATCH 205/325] some json and search commands --- docs/v4-to-v5.md | 5 +- packages/client/lib/commands/SET.ts | 4 +- .../json/lib/commands/DEBUG_MEMORY.spec.ts | 8 ++- packages/json/lib/commands/DEBUG_MEMORY.ts | 10 +++- packages/json/lib/commands/OBJKEYS.spec.ts | 8 ++- packages/json/lib/commands/OBJKEYS.ts | 10 +++- packages/json/lib/commands/OBJLEN.spec.ts | 10 ++-- packages/json/lib/commands/OBJLEN.ts | 10 +++- packages/json/lib/commands/SET.ts | 29 +++++++--- packages/json/lib/commands/STRLEN.spec.ts | 10 ++-- packages/json/lib/commands/STRLEN.ts | 12 ++-- packages/json/lib/commands/TOGGLE.spec.ts | 19 ++---- packages/json/lib/commands/TOGGLE.ts | 10 +--- packages/json/lib/commands/TYPE.spec.ts | 44 +++++++------- packages/json/lib/commands/TYPE.ts | 24 ++++++-- packages/json/lib/commands/index.ts | 6 +- packages/search/lib/commands/ALTER.spec.ts | 58 +++++++++---------- packages/search/lib/commands/ALTER.ts | 15 +++-- .../search/lib/commands/CONFIG_SET.spec.ts | 23 +++++--- packages/search/lib/commands/CONFIG_SET.ts | 17 ++++-- packages/search/lib/commands/index.ts | 12 ++-- 21 files changed, 198 insertions(+), 146 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index ffb95cef1f8..6c77ca2684f 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -178,9 +178,8 @@ Some command arguments/replies have changed to align more closely to data types - `TOPK.QUERY`: `Array` -> `Array` - `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` - `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] -- `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing] -- `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing] -- `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing] +- `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] +- : `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` - `TS.SYNUPDATE`: `Array>` -> `Record>` diff --git a/packages/client/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts index f0b1efd4f0b..cede62e7055 100644 --- a/packages/client/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -30,11 +30,11 @@ export interface SetOptions { condition?: 'NX' | 'XX'; /** - * @deprecated Use `condition` 'NX' instead + * @deprecated Use `{ condition: 'NX' }` instead. */ NX?: boolean; /** - * @deprecated Use `condition` 'XX' instead + * @deprecated Use `{ condition: 'XX' }` instead. */ XX?: boolean; diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts index b0e969ab172..8cdd2bdef99 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -4,7 +4,7 @@ import DEBUG_MEMORY from './DEBUG_MEMORY'; describe('JSON.DEBUG MEMORY', () => { describe('transformArguments', () => { - it('without path', () => { + it('simple', () => { assert.deepEqual( DEBUG_MEMORY.transformArguments('key'), ['JSON.DEBUG', 'MEMORY', 'key'] @@ -13,7 +13,9 @@ describe('JSON.DEBUG MEMORY', () => { it('with path', () => { assert.deepEqual( - DEBUG_MEMORY.transformArguments('key', '$'), + DEBUG_MEMORY.transformArguments('key', { + path: '$' + }), ['JSON.DEBUG', 'MEMORY', 'key', '$'] ); }); @@ -21,7 +23,7 @@ describe('JSON.DEBUG MEMORY', () => { testUtils.testWithClient('client.json.debugMemory', async client => { assert.deepEqual( - await client.json.debugMemory('key', '$'), + await client.json.debugMemory('key'), 0 ); }, GLOBAL.SERVERS.OPEN); diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts index 765d2da3579..17c202ff40a 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -1,13 +1,17 @@ import { RedisArgument, NumberReply, ArrayReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonDebugMemoryOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 2, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonDebugMemoryOptions) { const args = ['JSON.DEBUG', 'MEMORY', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/OBJKEYS.spec.ts b/packages/json/lib/commands/OBJKEYS.spec.ts index 17417098eca..ccdb7f97f6a 100644 --- a/packages/json/lib/commands/OBJKEYS.spec.ts +++ b/packages/json/lib/commands/OBJKEYS.spec.ts @@ -4,7 +4,7 @@ import OBJKEYS from './OBJKEYS'; describe('JSON.OBJKEYS', () => { describe('transformArguments', () => { - it('without path', () => { + it('simple', () => { assert.deepEqual( OBJKEYS.transformArguments('key'), ['JSON.OBJKEYS', 'key'] @@ -13,7 +13,9 @@ describe('JSON.OBJKEYS', () => { it('with path', () => { assert.deepEqual( - OBJKEYS.transformArguments('key', '$'), + OBJKEYS.transformArguments('key', { + path: '$' + }), ['JSON.OBJKEYS', 'key', '$'] ); }); @@ -21,7 +23,7 @@ describe('JSON.OBJKEYS', () => { testUtils.testWithClient('client.json.objKeys', async client => { assert.deepEqual( - await client.json.objKeys('key', '$'), + 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 index 7b4d9d963d2..6973d6b1f95 100644 --- a/packages/json/lib/commands/OBJKEYS.ts +++ b/packages/json/lib/commands/OBJKEYS.ts @@ -1,13 +1,17 @@ import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonObjKeysOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonObjKeysOptions) { const args = ['JSON.OBJKEYS', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts index edea703aa11..c646d3a4f0d 100644 --- a/packages/json/lib/commands/OBJLEN.spec.ts +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -4,7 +4,7 @@ import OBJLEN from './OBJLEN'; describe('JSON.OBJLEN', () => { describe('transformArguments', () => { - it('without path', () => { + it('simple', () => { assert.deepEqual( OBJLEN.transformArguments('key'), ['JSON.OBJLEN', 'key'] @@ -13,7 +13,9 @@ describe('JSON.OBJLEN', () => { it('with path', () => { assert.deepEqual( - OBJLEN.transformArguments('key', '$'), + OBJLEN.transformArguments('key', { + path: '$' + }), ['JSON.OBJLEN', 'key', '$'] ); }); @@ -21,8 +23,8 @@ describe('JSON.OBJLEN', () => { testUtils.testWithClient('client.json.objLen', async client => { assert.equal( - await client.json.objLen('key', '$'), - [null] + 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 index 45b8855561f..756651bde90 100644 --- a/packages/json/lib/commands/OBJLEN.ts +++ b/packages/json/lib/commands/OBJLEN.ts @@ -1,13 +1,17 @@ import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonObjLenOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, - transformArguments(key: RedisArgument, path?: RedisArgument) { + transformArguments(key: RedisArgument, options?: JsonObjLenOptions) { const args = ['JSON.OBJLEN', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/SET.ts b/packages/json/lib/commands/SET.ts index 9edebaa4308..78aea4b3545 100644 --- a/packages/json/lib/commands/SET.ts +++ b/packages/json/lib/commands/SET.ts @@ -1,23 +1,34 @@ import { RedisArgument, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; -export interface NX { - NX: true; -} - -export interface XX { - XX: true; +export interface JsonSetOptions { + condition?: 'NX' | 'XX'; + /** + * @deprecated Use `{ condition: 'NX' }` instead. + */ + NX?: boolean; + /** + * @deprecated Use `{ condition: 'XX' }` instead. + */ + XX?: boolean; } export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path: RedisArgument, json: RedisJSON, options?: NX | XX) { + transformArguments( + key: RedisArgument, + path: RedisArgument, + json: RedisJSON, + options?: JsonSetOptions + ) { const args = ['JSON.SET', key, path, transformRedisJsonArgument(json)]; - if ((options)?.NX) { + if (options?.condition) { + args.push(options?.condition); + } else if (options?.NX) { args.push('NX'); - } else if ((options)?.XX) { + } else if (options?.XX) { args.push('XX'); } diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts index 687a55553e9..5bb0548ffaf 100644 --- a/packages/json/lib/commands/STRLEN.spec.ts +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -4,7 +4,7 @@ import STRLEN from './STRLEN'; describe('JSON.STRLEN', () => { describe('transformArguments', () => { - it('without path', () => { + it('simple', () => { assert.deepEqual( STRLEN.transformArguments('key'), ['JSON.STRLEN', 'key'] @@ -13,7 +13,9 @@ describe('JSON.STRLEN', () => { it('with path', () => { assert.deepEqual( - STRLEN.transformArguments('key', '$'), + STRLEN.transformArguments('key', { + path: '$' + }), ['JSON.STRLEN', 'key', '$'] ); }); @@ -22,9 +24,9 @@ describe('JSON.STRLEN', () => { testUtils.testWithClient('client.json.strLen', async client => { const [, reply] = await Promise.all([ client.json.set('key', '$', ''), - client.json.strLen('key', '$') + client.json.strLen('key') ]); - assert.deepEqual(reply, [0]); + assert.deepEqual(reply, 0); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/STRLEN.ts b/packages/json/lib/commands/STRLEN.ts index 256414fb912..3b514d9caba 100644 --- a/packages/json/lib/commands/STRLEN.ts +++ b/packages/json/lib/commands/STRLEN.ts @@ -1,13 +1,17 @@ import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonStrLenOptions { + path?: RedisArgument; +} + export default { FIRST_KEY_INDEX: 1, - IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, options?: JsonStrLenOptions) { const args = ['JSON.STRLEN', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts index 3ce922a7b82..1c785d97b17 100644 --- a/packages/json/lib/commands/TOGGLE.spec.ts +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -3,20 +3,11 @@ import testUtils, { GLOBAL } from '../test-utils'; import TOGGLE from './TOGGLE'; describe('JSON.TOGGLE', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - TOGGLE.transformArguments('key'), - ['JSON.TOGGLE', 'key'] - ); - }); - - it('with path', () => { - assert.deepEqual( - TOGGLE.transformArguments('key', '$'), - ['JSON.TOGGLE', 'key', '$'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + TOGGLE.transformArguments('key', '$'), + ['JSON.TOGGLE', 'key', '$'] + ); }); testUtils.testWithClient('client.json.toggle', async client => { diff --git a/packages/json/lib/commands/TOGGLE.ts b/packages/json/lib/commands/TOGGLE.ts index 85e5e479aae..2a8df3eba36 100644 --- a/packages/json/lib/commands/TOGGLE.ts +++ b/packages/json/lib/commands/TOGGLE.ts @@ -3,14 +3,8 @@ import { RedisArgument, ArrayReply, NumberReply, NullReply, Command, } from '@re export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path?: RedisArgument) { - const args = ['JSON.TOGGLE', key] - - if (path) { - args.push(path); - } - - return args; + transformArguments(key: RedisArgument, path: RedisArgument) { + return ['JSON.TOGGLE', key, path]; }, transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply } as const satisfies Command; diff --git a/packages/json/lib/commands/TYPE.spec.ts b/packages/json/lib/commands/TYPE.spec.ts index 5cecfb827a7..2a90a3bf9ee 100644 --- a/packages/json/lib/commands/TYPE.spec.ts +++ b/packages/json/lib/commands/TYPE.spec.ts @@ -1,28 +1,32 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './TYPE'; +import TYPE from './TYPE'; describe('TYPE', () => { - describe('transformArguments', () => { - it('without path', () => { - assert.deepEqual( - transformArguments('key'), - ['JSON.TYPE', 'key'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key'), + ['JSON.TYPE', 'key'] + ); + }); - it('with path', () => { - assert.deepEqual( - transformArguments('key', '$'), - ['JSON.TYPE', 'key', '$'] - ); - }); + it('with path', () => { + assert.deepEqual( + transformArguments('key', { + path: '$' + }), + ['JSON.TYPE', 'key', '$'] + ); }); + }); - // testUtils.testWithClient('client.json.type', async client => { - // assert.deepEqual( - // await client.json.type('key', '$'), - // [null] - // ); - // }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.json.type', async client => { + assert.deepEqual( + await client.json.type('key', { + path: '$' + }), + [null] + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/TYPE.ts b/packages/json/lib/commands/TYPE.ts index 7fd55f625dc..68c5d850ebf 100644 --- a/packages/json/lib/commands/TYPE.ts +++ b/packages/json/lib/commands/TYPE.ts @@ -1,13 +1,25 @@ -export const FIRST_KEY_INDEX = 1; +import { NullReply, BlobStringReply, ArrayReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(key: string, path?: string): Array { +export interface JsonTypeOptions { + path?: RedisArgument; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, options?: JsonTypeOptions) { const args = ['JSON.TYPE', key]; - if (path) { - args.push(path); + if (options?.path) { + args.push(options.path); } return args; -} + }, + transformReply: { + 2: undefined as unknown as () => NullReply | BlobStringReply | ArrayReply, + // TODO: ?!??! + 3: undefined as unknown as () => any + } +} as const satisfies Command; -export declare function transformReply(): string | null | Array; diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index 4405f1b423c..6769594ad52 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -19,7 +19,7 @@ import SET from './SET'; import STRAPPEND from './STRAPPEND'; import STRLEN from './STRLEN'; import TOGGLE from './TOGGLE'; -// import TYPE from './TYPE'; +import TYPE from './TYPE'; export default { ARRAPPEND, @@ -64,8 +64,8 @@ export default { strLen: STRLEN, TOGGLE, toggle: TOGGLE, - // TYPE, - // type: TYPE + TYPE, + type: TYPE }; // https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 diff --git a/packages/search/lib/commands/ALTER.spec.ts b/packages/search/lib/commands/ALTER.spec.ts index e9724757ad7..26f5d48de1c 100644 --- a/packages/search/lib/commands/ALTER.spec.ts +++ b/packages/search/lib/commands/ALTER.spec.ts @@ -1,37 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './ALTER'; -import { SchemaFieldTypes } from '.'; +import ALTER from './ALTER'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALTER', () => { - describe('transformArguments', () => { - it('with NOINDEX', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - NOINDEX: true, - SORTABLE: 'UNF', - AS: 'text' - } - }), - ['FT.ALTER', 'index', 'SCHEMA', 'ADD', 'field', 'AS', 'text', 'TEXT', 'SORTABLE', 'UNF', 'NOINDEX'] - ); - }); +describe('FT.ALTER', () => { + describe('transformArguments', () => { + it('with NOINDEX', () => { + assert.deepEqual( + ALTER.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT, + NOINDEX: true, + SORTABLE: 'UNF', + AS: 'text' + } + }), + ['FT.ALTER', 'index', 'SCHEMA', 'ADD', 'field', 'AS', 'text', 'TEXT', 'SORTABLE', 'UNF', 'NOINDEX'] + ); }); + }); - testUtils.testWithClient('client.ft.create', async client => { - await Promise.all([ - client.ft.create('index', { - title: SchemaFieldTypes.TEXT - }), - ]); + testUtils.testWithClient('client.ft.create', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + title: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.alter('index', { + body: SCHEMA_FIELD_TYPE.TEXT + }) + ]); - assert.equal( - await client.ft.alter('index', { - body: SchemaFieldTypes.TEXT - }), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALTER.ts b/packages/search/lib/commands/ALTER.ts index bb4c5202c65..d5587b2397c 100644 --- a/packages/search/lib/commands/ALTER.ts +++ b/packages/search/lib/commands/ALTER.ts @@ -1,10 +1,13 @@ -import { RediSearchSchema, pushSchema } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RediSearchSchema, pushSchema } from './CREATE'; -export function transformArguments(index: string, schema: RediSearchSchema): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, schema: RediSearchSchema) { const args = ['FT.ALTER', index, 'SCHEMA', 'ADD']; pushSchema(args, schema); - return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/CONFIG_SET.spec.ts b/packages/search/lib/commands/CONFIG_SET.spec.ts index 59cb63a3d8e..263c99c2327 100644 --- a/packages/search/lib/commands/CONFIG_SET.spec.ts +++ b/packages/search/lib/commands/CONFIG_SET.spec.ts @@ -1,12 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CONFIG_SET'; +import CONFIG_SET from './CONFIG_SET'; -describe('CONFIG SET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('TIMEOUT', '500'), - ['FT.CONFIG', 'SET', 'TIMEOUT', '500'] - ); - }); +describe('FT.CONFIG SET', () => { + it('transformArguments', () => { + assert.deepEqual( + CONFIG_SET.transformArguments('TIMEOUT', '500'), + ['FT.CONFIG', 'SET', 'TIMEOUT', '500'] + ); + }); + + testUtils.testWithClient('client.ft.configSet', async client => { + assert.deepEqual( + await client.ft.configSet('TIMEOUT', '500'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/CONFIG_SET.ts b/packages/search/lib/commands/CONFIG_SET.ts index 93b76d79edf..ac001bf68a6 100644 --- a/packages/search/lib/commands/CONFIG_SET.ts +++ b/packages/search/lib/commands/CONFIG_SET.ts @@ -1,5 +1,14 @@ -export function transformArguments(option: string, value: string): Array { - return ['FT.CONFIG', 'SET', option, value]; -} +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +// using `string & {}` to avoid TS widening the type to `string` +// TODO +type FtConfigProperties = 'a' | 'b' | (string & {}) | Buffer; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(property: FtConfigProperties, value: RedisArgument) { + return ['FT.CONFIG', 'SET', property, value]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index d4a5c28da78..27bd3dfb224 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -1,12 +1,12 @@ import _LIST from './_LIST'; -// import ALTER from './ALTER'; +import ALTER from './ALTER'; // import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; // import AGGREGATE from './AGGREGATE'; import ALIASADD from './ALIASADD'; import ALIASDEL from './ALIASDEL'; import ALIASUPDATE from './ALIASUPDATE'; // import CONFIG_GET from './CONFIG_GET'; -// import CONFIG_SET from './CONFIG_SET'; +import CONFIG_SET from './CONFIG_SET'; import CREATE from './CREATE'; import CURSOR_DEL from './CURSOR_DEL'; // import CURSOR_READ from './CURSOR_READ'; @@ -39,8 +39,8 @@ import { CommandArguments } from '@redis/client/dist/lib/RESP/types'; export default { _LIST, _list: _LIST, - // ALTER, - // alter: ALTER, + ALTER, + alter: ALTER, // AGGREGATE_WITHCURSOR, // aggregateWithCursor: AGGREGATE_WITHCURSOR, // AGGREGATE, @@ -53,8 +53,8 @@ export default { aliasUpdate: ALIASUPDATE, // CONFIG_GET, // configGet: CONFIG_GET, - // CONFIG_SET, - // configSet: CONFIG_SET, + CONFIG_SET, + configSet: CONFIG_SET, CREATE, create: CREATE, CURSOR_DEL, From d0801921e726c691131607d4d35c1397d90e26eb Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 1 Aug 2023 14:52:08 -0400 Subject: [PATCH 206/325] JSON.STRAPPEND --- docs/v4-to-v5.md | 2 +- packages/json/lib/commands/STRAPPEND.spec.ts | 54 ++++++++++---------- packages/json/lib/commands/STRAPPEND.ts | 39 +++++--------- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 6c77ca2684f..e1d67a9d0f8 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -178,7 +178,7 @@ Some command arguments/replies have changed to align more closely to data types - `TOPK.QUERY`: `Array` -> `Array` - `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` - `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] -- `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] +- `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRAPPEND`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] - : `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` - `TS.SYNUPDATE`: `Array>` -> `Record>` diff --git a/packages/json/lib/commands/STRAPPEND.spec.ts b/packages/json/lib/commands/STRAPPEND.spec.ts index 06e6b60b10c..8927ce84613 100644 --- a/packages/json/lib/commands/STRAPPEND.spec.ts +++ b/packages/json/lib/commands/STRAPPEND.spec.ts @@ -1,30 +1,32 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './STRAPPEND'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import STRAPPEND from './STRAPPEND'; -// describe('STRAPPEND', () => { -// describe('transformArguments', () => { -// it('without path', () => { -// assert.deepEqual( -// transformArguments('key', 'append'), -// ['JSON.STRAPPEND', 'key', '"append"'] -// ); -// }); +describe('JSON.STRAPPEND', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + STRAPPEND.transformArguments('key', 'append'), + ['JSON.STRAPPEND', 'key', '"append"'] + ); + }); -// it('with path', () => { -// assert.deepEqual( -// transformArguments('key', '$', 'append'), -// ['JSON.STRAPPEND', 'key', '$', '"append"'] -// ); -// }); -// }); + it('with path', () => { + assert.deepEqual( + STRAPPEND.transformArguments('key', 'append', { + path: '$' + }), + ['JSON.STRAPPEND', 'key', '$', '"append"'] + ); + }); + }); -// testUtils.testWithClient('client.json.strAppend', async client => { -// await client.json.set('key', '$', ''); + testUtils.testWithClient('client.json.strAppend', async client => { + const [, reply] = await Promise.all([ + client.json.set('key', '$', ''), + client.json.strAppend('key', 'append') + ]); -// assert.deepEqual( -// await client.json.strAppend('key', '$', 'append'), -// [6] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.deepEqual(reply, 6); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/STRAPPEND.ts b/packages/json/lib/commands/STRAPPEND.ts index 3f8e98e6bc1..ad3cd377c9d 100644 --- a/packages/json/lib/commands/STRAPPEND.ts +++ b/packages/json/lib/commands/STRAPPEND.ts @@ -1,32 +1,21 @@ -// import { transformRedisJsonArgument } from '.'; +import { RedisArgument, Command, NullReply, NumberReply, ArrayReply } from '@redis/client/dist/lib/RESP/types'; -// 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; - -import { SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +export interface JsonStrAppendOptions { + path?: RedisArgument; +} export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments() { - return ['JSON.STRAPPEND']; + transformArguments(key: RedisArgument, append: RedisArgument, options?: JsonStrAppendOptions) { + const args = ['JSON.STRAPPEND', key]; + + if (options?.path) { + args.push(options.path); + } + + args.push(append); + return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => NumberReply | ArrayReply } as const satisfies Command; From 7b3c393b50b5809af2bc4e3a8666e9c93cce4087 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 1 Aug 2023 15:32:37 -0400 Subject: [PATCH 207/325] GRAPH.QUERY --- packages/graph/lib/commands/QUERY.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index c77406ff4f8..8a052354610 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -2,8 +2,7 @@ import { RedisArgument, ArrayReply, BlobStringReply, NumberReply, NullReply, Tup type Headers = ArrayReply; -// TODO: cannot use `ArrayReply` due to circular reference -type Data = Array; +type Data = ArrayReply; type Metadata = ArrayReply; From c7a03acfd3cd9534119e9bda59788da374ae53ad Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 1 Aug 2023 16:24:13 -0400 Subject: [PATCH 208/325] todo.md --- docs/todo.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/todo.md b/docs/todo.md index c6abedcf413..5c64a699430 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,4 +1,6 @@ - Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie? +- "Isolation Pool" -> pool +- Cluster request response policies (either implement, or block "server" commands in cluster) Docs: - [v4 to v5](./v4-to-v5.md) - Legacy mode From 132599332faf4444bf6e57d2913232d65cab5128 Mon Sep 17 00:00:00 2001 From: Rowan Trollope Date: Tue, 29 Aug 2023 10:31:34 -0700 Subject: [PATCH 209/325] Added MSET command MSET command added. Requires all keys to have the same JSON Path, which might fit most use cases, but is a limitation. Optionally we could make the path an array as well to support all use cases. --- packages/json/lib/commands/MSET.spec.ts | 19 +++++++++++++++++++ packages/json/lib/commands/MSET.ts | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 packages/json/lib/commands/MSET.spec.ts create mode 100644 packages/json/lib/commands/MSET.ts diff --git a/packages/json/lib/commands/MSET.spec.ts b/packages/json/lib/commands/MSET.spec.ts new file mode 100644 index 00000000000..a8ecf9eabd9 --- /dev/null +++ b/packages/json/lib/commands/MSET.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './MSET'; + +describe('MSET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments(['1', '2'], '$', [{ a: 1 }, { b: 2 }]), + ['JSON.MSET', '1', '$', '{ "a":"1" } ', '2', '$', '{ "b":"2"} '] + ); + }); + + testUtils.testWithClient('client.json.mGet', async client => { + assert.deepEqual( + await client.json.mGet(["1", "2"], "$", [{ a: 1 }, { b: 2 }]), + [null, null] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts new file mode 100644 index 00000000000..ea553f4e88a --- /dev/null +++ b/packages/json/lib/commands/MSET.ts @@ -0,0 +1,24 @@ +import { RedisJSON, transformRedisJsonArgument } from "."; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + keys: Array, + path: string, + json: Array +): Array { + + if (keys.length != json.length) + throw new Error("Number of keys and json objects must be equal"); + + let args: Array = ["JSON.SET"]; + + // walk through the key array, adding the key, the path and the json objects, calling transformRedisJsonArgument for each + for (let i = 0; i < keys.length; i++) { + args.push(keys[i], path, transformRedisJsonArgument(json[i])); + } + + return args; +} + +export declare function transformReply(): "OK" | null; From f476c389711d34889bcbc90897085ee7e80a62f0 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Tue, 29 Aug 2023 11:21:34 -0700 Subject: [PATCH 210/325] change JSON.MSET signature, add to json command object, fix tests --- packages/json/lib/commands/MSET.spec.ts | 26 +++++++++++++++++---- packages/json/lib/commands/MSET.ts | 31 ++++++++++++++----------- packages/json/lib/commands/index.ts | 3 +++ 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/packages/json/lib/commands/MSET.spec.ts b/packages/json/lib/commands/MSET.spec.ts index a8ecf9eabd9..53d4d822505 100644 --- a/packages/json/lib/commands/MSET.spec.ts +++ b/packages/json/lib/commands/MSET.spec.ts @@ -5,15 +5,31 @@ import { transformArguments } from './MSET'; describe('MSET', () => { it('transformArguments', () => { assert.deepEqual( - transformArguments(['1', '2'], '$', [{ a: 1 }, { b: 2 }]), - ['JSON.MSET', '1', '$', '{ "a":"1" } ', '2', '$', '{ "b":"2"} '] + transformArguments([{ + key: '1', + path: '$', + value: 1 + }, { + key: '2', + path: '$', + value: '2' + }]), + ['JSON.MSET', '1', '$', '1', '2', '$', '"2"'] ); }); - testUtils.testWithClient('client.json.mGet', async client => { + testUtils.testWithClient('client.json.mSet', async client => { assert.deepEqual( - await client.json.mGet(["1", "2"], "$", [{ a: 1 }, { b: 2 }]), - [null, null] + await client.json.mSet([{ + key: '1', + path: '$', + value: 1 + }, { + key: '2', + path: '$', + value: '2' + }]), + 'OK' ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts index ea553f4e88a..79af2b3c0fd 100644 --- a/packages/json/lib/commands/MSET.ts +++ b/packages/json/lib/commands/MSET.ts @@ -1,24 +1,27 @@ -import { RedisJSON, transformRedisJsonArgument } from "."; +import { RedisJSON, transformRedisJsonArgument } from '.'; +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; export const FIRST_KEY_INDEX = 1; -export function transformArguments( - keys: Array, - path: string, - json: Array -): Array { - - if (keys.length != json.length) - throw new Error("Number of keys and json objects must be equal"); +interface JsonMSetItem { + key: RedisCommandArgument; + path: RedisCommandArgument; + value: RedisJSON; +} - let args: Array = ["JSON.SET"]; +export function transformArguments(items: Array): Array { + const args = new Array(1 + items.length * 3); + args[0] = 'JSON.MSET'; - // walk through the key array, adding the key, the path and the json objects, calling transformRedisJsonArgument for each - for (let i = 0; i < keys.length; i++) { - args.push(keys[i], path, transformRedisJsonArgument(json[i])); + let argsIndex = 1; + for (let i = 0; i < items.length; i++) { + const item = items[i]; + args[argsIndex++] = item.key; + args[argsIndex++] = item.path; + args[argsIndex++] = transformRedisJsonArgument(item.json); } return args; } -export declare function transformReply(): "OK" | null; +export declare function transformReply(): 'OK'; diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index efcf156b84d..a42ece5f277 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -9,6 +9,7 @@ import * as DEL from './DEL'; import * as FORGET from './FORGET'; import * as GET from './GET'; import * as MGET from './MGET'; +import * as MSET from './MSET'; import * as NUMINCRBY from './NUMINCRBY'; import * as NUMMULTBY from './NUMMULTBY'; import * as OBJKEYS from './OBJKEYS'; @@ -42,6 +43,8 @@ export default { get: GET, MGET, mGet: MGET, + MSET, + mSet: MSET, NUMINCRBY, numIncrBy: NUMINCRBY, NUMMULTBY, From 43969a3f389c7dcd920bfe3014ca800c6e3b8f5e Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Tue, 29 Aug 2023 12:29:30 -0700 Subject: [PATCH 211/325] its `item.value`, not `item.json`.. --- packages/json/lib/commands/MSET.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts index 79af2b3c0fd..9790a2602a9 100644 --- a/packages/json/lib/commands/MSET.ts +++ b/packages/json/lib/commands/MSET.ts @@ -18,7 +18,7 @@ export function transformArguments(items: Array): Array { const item = items[i]; args[argsIndex++] = item.key; args[argsIndex++] = item.path; - args[argsIndex++] = transformRedisJsonArgument(item.json); + args[argsIndex++] = transformRedisJsonArgument(item.value); } return args; From 0093eb007f09b03fc15fb152c976762dad5ddcb7 Mon Sep 17 00:00:00 2001 From: Rowan Trollope Date: Tue, 29 Aug 2023 19:51:06 -0700 Subject: [PATCH 212/325] Update MSET.ts Removed unused RedisCommandArguments --- packages/json/lib/commands/MSET.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts index 9790a2602a9..67228f264d2 100644 --- a/packages/json/lib/commands/MSET.ts +++ b/packages/json/lib/commands/MSET.ts @@ -1,5 +1,5 @@ import { RedisJSON, transformRedisJsonArgument } from '.'; -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; export const FIRST_KEY_INDEX = 1; @@ -10,6 +10,7 @@ interface JsonMSetItem { } export function transformArguments(items: Array): Array { + const args = new Array(1 + items.length * 3); args[0] = 'JSON.MSET'; From 3895eb59269321f934ff3bc7b19c5de46267cfb7 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 4 Sep 2023 17:26:48 -0400 Subject: [PATCH 213/325] client pool --- docs/programmability.md | 2 +- packages/client/index.ts | 10 +- packages/client/lib/RESP/decoder.ts | 13 +- packages/client/lib/client/commands-queue.ts | 2 +- packages/client/lib/client/index.ts | 61 +- packages/client/lib/client/legacy-mode.ts | 2 +- packages/client/lib/client/linked-list.ts | 21 +- packages/client/lib/client/multi-command.ts | 4 +- packages/client/lib/client/pool.ts | 711 ++++++++++++------- packages/client/lib/cluster/index.ts | 65 +- packages/client/lib/cluster/multi-command.ts | 4 +- packages/client/lib/errors.ts | 2 + test/package-lock.json | 44 -- test/package.json | 15 - test/test.js | 21 - 15 files changed, 595 insertions(+), 382 deletions(-) delete mode 100644 test/package-lock.json delete mode 100644 test/package.json delete mode 100644 test/test.js diff --git a/docs/programmability.md b/docs/programmability.md index 803ac689a60..f6ae42033c6 100644 --- a/docs/programmability.md +++ b/docs/programmability.md @@ -19,7 +19,7 @@ redis.register_function { Here is the same example, but in a format that can be pasted into the `redis-cli`. ``` -FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" +FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name='add', callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={'no-writes'}}" ``` Load the prior redis function on the _redis server_ before running the example below. diff --git a/packages/client/index.ts b/packages/client/index.ts index 09874984de1..06392e970ef 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -4,11 +4,15 @@ export { VerbatimString } from './lib/RESP/verbatim-string'; export { defineScript } from './lib/lua-script'; // export * from './lib/errors'; -import RedisClient, { RedisClientType, RedisClientOptions } from './lib/client'; -export { RedisClientType, RedisClientOptions }; +import RedisClient, { RedisClientOptions, RedisClientType } from './lib/client'; +export { RedisClientOptions, RedisClientType }; export const createClient = RedisClient.create; -import RedisCluster, { RedisClusterType, RedisClusterOptions } from './lib/cluster'; +import { RedisClientPool, RedisPoolOptions, RedisClientPoolType } from './lib/client/pool'; +export { RedisClientPoolType, RedisPoolOptions }; +export const createClientPool = RedisClientPool.create; + +import RedisCluster, { RedisClusterOptions, RedisClusterType } from './lib/cluster'; export { RedisClusterType, RedisClusterOptions }; export const createCluster = RedisCluster.create; diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index c4e1296fc23..2fbadd0f5ee 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -111,7 +111,10 @@ export class Decoder { case RESP_TYPES.NUMBER: return this._handleDecodedValue( this._config.onReply, - this._decodeNumber(chunk) + this._decodeNumber( + this._config.getTypeMapping()[RESP_TYPES.NUMBER], + chunk + ) ); case RESP_TYPES.BIG_NUMBER: @@ -226,7 +229,11 @@ export class Decoder { return boolean; } - private _decodeNumber(chunk) { + private _decodeNumber(type, chunk) { + if (type === String) { + return this._decodeSimpleString(String, chunk); + } + switch (chunk[this._cursor]) { case ASCII['+']: return this._maybeDecodeNumberValue(false, chunk); @@ -675,7 +682,7 @@ export class Decoder { return this._decodeBoolean(chunk); case RESP_TYPES.NUMBER: - return this._decodeNumber(chunk); + return this._decodeNumber(typeMapping[RESP_TYPES.NUMBER], chunk); case RESP_TYPES.BIG_NUMBER: return this._decodeBigNumber(typeMapping[RESP_TYPES.BIG_NUMBER], chunk); diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 8caa2f178a9..1adc1a76925 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -11,7 +11,7 @@ export interface CommandOptions { asap?: boolean; abortSignal?: AbortSignal; /** - * Maps bettween RESP and JavaScript types + * Maps between RESP and JavaScript types */ typeMapping?: T; } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index dbf8b85b034..2ba12ac0f36 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -7,13 +7,13 @@ import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchErr import { URL } from 'url'; import { TcpSocketConnectOpts } from 'net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; -import { Command, CommandArguments, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; +import { Command, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; import { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; -// import { RedisClientPool } from './pool'; +import { RedisPoolOptions, RedisClientPool } from './pool'; interface ClientCommander< M extends RedisModules, @@ -21,7 +21,7 @@ interface ClientCommander< S extends RedisScripts, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping -> extends CommanderConfig{ +> extends CommanderConfig { commandOptions?: CommandOptions; } @@ -72,7 +72,7 @@ export interface RedisClientOptions< readonly?: boolean; /** * Send `PING` command at interval (in ms). - * Useful with Redis deployments that do not use TCP Keep-Alive. + * Useful with Redis deployments that do not honor TCP Keep-Alive. */ pingInterval?: number; } @@ -194,13 +194,7 @@ export default class RedisClient< return async function (this: ProxyClient, ...args: Array) { const scriptArgs = script.transformArguments(...args), redisArgs = prefix.concat(scriptArgs), - reply = await this.sendCommand(redisArgs, this._commandOptions).catch((err: unknown) => { - if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; - - redisArgs[0] = 'EVAL'; - redisArgs[1] = script.SCRIPT; - return this.sendCommand(redisArgs, this._commandOptions); - }); + reply = await this.executeScript(script, redisArgs, this._commandOptions); return transformReply ? transformReply(reply, scriptArgs.preserve) : reply; @@ -218,8 +212,8 @@ export default class RedisClient< BaseClass: RedisClient, commands: COMMANDS, createCommand: RedisClient._createCommand, - createFunctionCommand: RedisClient._createFunctionCommand, createModuleCommand: RedisClient._createModuleCommand, + createFunctionCommand: RedisClient._createFunctionCommand, createScriptCommand: RedisClient._createScriptCommand, config }); @@ -227,8 +221,7 @@ export default class RedisClient< Client.prototype.Multi = RedisClientMultiCommand.extend(config); return (options?: Omit>) => { - // returning a proxy of the client to prevent the namespaces.self to leak between proxies - // namespaces will be bootstraped on first access per proxy + // returning a "proxy" to prevent the namespaces.self to leak between "proxies" return Object.create(new Client(options)) as RedisClientType; }; } @@ -527,13 +520,14 @@ export default class RedisClient< } /** - * Create `RedisClientPool` using this client as a prototype + * Create {@link RedisClientPool `RedisClientPool`} using this client as a prototype */ - // pool() { - // return RedisClientPool.fromClient( - // this as unknown as RedisClientType - // ); - // } + pool(options?: Partial) { + return RedisClientPool.create( + this._options, + options + ); + } duplicate< _M extends RedisModules = M, @@ -549,12 +543,13 @@ export default class RedisClient< }) as RedisClientType<_M, _F, _S, _RESP, _TYPE_MAPPING>; } - connect() { - return this._socket.connect(); + async connect() { + await this._socket.connect(); + return this as unknown as RedisClientType; } sendCommand( - args: CommandArguments, + args: Array, options?: CommandOptions ): Promise { if (!this._socket.isOpen) { @@ -568,6 +563,22 @@ export default class RedisClient< return promise; } + async executeScript( + script: RedisScript, + args: Array, + options?: CommandOptions + ) { + try { + return await this.sendCommand(args, options); + } catch (err) { + if (!(err as Error)?.message?.startsWith?.('NOSCRIPT')) throw err; + + args[0] = 'EVAL'; + args[1] = script.SCRIPT; + return await this.sendCommand(args, options); + } + } + async SELECT(db: number): Promise { await this.sendCommand(['SELECT', db.toString()]); this._selectedDB = db; @@ -728,7 +739,7 @@ export default class RedisClient< /** * @internal */ - executePipeline(commands: Array) { + _executePipeline(commands: Array) { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); } @@ -745,7 +756,7 @@ export default class RedisClient< /** * @internal */ - async executeMulti( + async _executeMulti( commands: Array, selectedDB?: number ) { diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 576d73be967..532c23fafb3 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -160,7 +160,7 @@ class LegacyMultiCommand { } exec(cb?: (err: ErrorReply | null, replies?: Array) => unknown) { - const promise = this._client.executeMulti(this._multi.queue); + const promise = this._client._executeMulti(this._multi.queue); if (!cb) { promise.catch(err => this._client.emit('error', err)); diff --git a/packages/client/lib/client/linked-list.ts b/packages/client/lib/client/linked-list.ts index 1a68e1c2f3a..c2f49527383 100644 --- a/packages/client/lib/client/linked-list.ts +++ b/packages/client/lib/client/linked-list.ts @@ -138,9 +138,26 @@ export class SinglyLinkedList { }; if (this._head === undefined) { - this._head = this._tail = node; + return this._head = this._tail = node; + } + + return this._tail!.next = this._tail = node; + } + + remove(node: SinglyLinkedNode, parent: SinglyLinkedNode | undefined) { + --this._length; + + if (this._head === node) { + if (this._tail === node) { + this._head = this._tail = undefined; + } else { + this._head = node.next; + } + } else if (this._tail === node) { + this._tail = parent; + parent!.next = undefined; } else { - this._tail!.next = this._tail = node; + parent!.next = node.next; } } diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index cacb5429a5c..267444ad31a 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -173,7 +173,7 @@ export default class RedisClientMultiCommand { if (execAsPipeline) return this.execAsPipeline(); return this._multi.transformReplies( - await this._client.executeMulti(this._multi.queue, this._selectedDB) + await this._client._executeMulti(this._multi.queue, this._selectedDB) ) as MultiReplyType; } @@ -187,7 +187,7 @@ export default class RedisClientMultiCommand { if (this._multi.queue.length === 0) return [] as MultiReplyType; return this._multi.transformReplies( - await this._client.executePipeline(this._multi.queue) + await this._client._executePipeline(this._multi.queue) ) as MultiReplyType; } diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 5f1a286cc2e..4cf7fc43de6 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -1,242 +1,469 @@ -// import COMMANDS from '../commands'; -// import { RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; -// import RedisClient, { RedisClientType, RedisClientOptions, RedisClientExtensions } from '.'; -// import { EventEmitter } from 'events'; -// import { DoublyLinkedNode, DoublyLinkedList, SinglyLinkedList } from './linked-list'; - -// export type RedisPoolOptions = typeof RedisClientPool['_DEFAULTS']; - -// export type PoolTask< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts, -// RESP extends RespVersions, -// TYPE_MAPPING extends TypeMapping, -// T = unknown -// > = (client: RedisClientType) => T; - -// export type RedisClientPoolType< -// M extends RedisModules = {}, -// F extends RedisFunctions = {}, -// S extends RedisScripts = {}, -// RESP extends RespVersions = 2, -// TYPE_MAPPING extends TypeMapping = {} -// > = ( -// RedisClientPool & -// RedisClientExtensions -// ); - -// export class RedisClientPool< -// M extends RedisModules = {}, -// F extends RedisFunctions = {}, -// S extends RedisScripts = {}, -// RESP extends RespVersions = 2, -// TYPE_MAPPING extends TypeMapping = {} -// > extends EventEmitter { -// static fromClient< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts, -// RESP extends RespVersions, -// TYPE_MAPPING extends TypeMapping = {} -// >( -// client: RedisClientType, -// poolOptions: Partial -// ) { -// return RedisClientPool.create( -// () => client.duplicate(), -// poolOptions -// ); -// } - -// static fromOptions< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts, -// RESP extends RespVersions, -// TYPE_MAPPING extends TypeMapping = {} -// >( -// options: RedisClientOptions, -// poolOptions: Partial -// ) { -// return RedisClientPool.create( -// RedisClient.factory(options), -// poolOptions -// ); -// } - -// static create< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts, -// RESP extends RespVersions, -// TYPE_MAPPING extends TypeMapping = {} -// >( -// clientFactory: () => RedisClientType, -// options?: Partial -// ) { -// return new RedisClientPool( -// clientFactory, -// options -// ) as RedisClientPoolType; -// } - -// private static _DEFAULTS = { -// /** -// * The minimum number of clients to keep in the pool. -// */ -// minimum: 0, -// /** -// * The maximum number of clients to keep in the pool. -// */ -// maximum: 1, -// /** -// * The maximum time a task can wait for a client to become available. -// */ -// acquireTimeout: 3000, -// /** -// * When there are `> minimum && < maximum` clients in the pool, the pool will wait for `cleanupDelay` milliseconds before closing the extra clients. -// */ -// cleanupDelay: 3000 -// }; - -// private readonly _clientFactory: () => RedisClientType; -// private readonly _options: Required; -// private readonly _idleClients = new SinglyLinkedList>(); -// private readonly _usedClients = new DoublyLinkedList>(); -// private readonly _tasksQueue = new SinglyLinkedList<{ -// resolve: (value: T | PromiseLike) => void; -// reject: (reason?: unknown) => void; -// fn: PoolTask; -// }>(); - -// constructor( -// clientFactory: () => RedisClientType, -// options?: Partial -// ) { -// super(); - -// this._clientFactory = clientFactory; -// this._options = { -// ...RedisClientPool._DEFAULTS, -// ...options -// }; -// this._initate(); -// } - -// private async _initate() { -// const promises = []; -// while (promises.length < this._options.minimum) { -// promises.push(this._create()); -// } - -// try { -// await Promise.all(promises); -// } catch (err) { -// this.destroy(); -// this.emit('error', err); -// } -// } - -// private async _create() { -// const client = this._clientFactory() -// // TODO: more events? -// .on('error', (err: Error) => this.emit('error', err)); - -// const node = this._usedClients.push(client); - -// await client.connect(); - -// this._usedClients.remove(node); - -// return client; -// } - -// execute(fn: PoolTask): Promise { -// return new Promise((resolve, reject) => { -// let client = this._idleClients.shift(); -// if (!client) { -// this._tasksQueue.push({ -// // @ts-ignore -// resolve, -// reject, -// fn -// }); - -// if (this._idleClients.length + this._usedClients.length < this._options.maximum) { -// this._create(); -// } - -// return; -// } - -// const node = this._usedClients.push(client); -// // @ts-ignore -// this._executeTask(node, resolve, reject, fn); -// }); -// } - -// private _executeTask( -// node: DoublyLinkedNode>, -// resolve: (value: T | PromiseLike) => void, -// reject: (reason?: unknown) => void, -// fn: PoolTask -// ) { -// const result = fn(node.value); -// if (result instanceof Promise) { -// result.then(resolve, reject); -// result.finally(() => this._returnClient(node)) -// } else { -// resolve(result); -// this._returnClient(node); -// } -// } - -// private _returnClient(node: DoublyLinkedListNode>) { -// const task = this._tasksQueue.shift(); -// if (task) { -// this._executeTask(node, task.resolve, task.reject, task.fn); -// return; -// } - -// if (this._idleClients.length >= this._options.minimum) { -// node.client.destroy(); -// return; -// } - -// this._usedClients.remove(node); -// this._idleClients.push(node.client); -// } - -// async close() { -// const promises = []; - -// for (const client of this._idleClients) { -// promises.push(client.close()); -// } - -// this._idleClients.reset(); - -// for (const client of this._usedClients) { -// promises.push(client.close()); -// } - -// this._usedClients.reset(); - -// await Promise.all(promises); -// } - -// destroy() { -// for (const client of this._idleClients) { -// client.destroy(); -// } - -// this._idleClients.reset(); - -// for (const client of this._usedClients) { -// client.destroy(); -// } - -// this._usedClients.reset(); -// } -// } +import COMMANDS from '../commands'; +import { Command, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; +import RedisClient, { RedisClientType, RedisClientOptions, RedisClientExtensions } from '.'; +import { EventEmitter } from 'events'; +import { DoublyLinkedNode, DoublyLinkedList, SinglyLinkedList } from './linked-list'; +import { TimeoutError } from '../errors'; +import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; +import { CommandOptions } from './commands-queue'; + +export interface RedisPoolOptions { + /** + * The minimum number of clients to keep in the pool (>= 1). + */ + minimum: number; + /** + * The maximum number of clients to keep in the pool (>= {@link RedisPoolOptions.minimum} >= 1). + */ + maximum: number; + /** + * The maximum time a task can wait for a client to become available (>= 0). + */ + acquireTimeout: number; + /** + * TODO + */ + cleanupDelay: number; +} + +export type PoolTask< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + T = unknown +> = (client: RedisClientType) => T; + +export type RedisClientPoolType< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} +> = ( + RedisClientPool & + RedisClientExtensions +); + +type ProxyPool = RedisClientPoolType; + +type NamespaceProxyPool = { self: ProxyPool }; + +export class RedisClientPool< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} +> extends EventEmitter { + private static _createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: ProxyPool, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this.sendCommand(redisArgs, this._commandOptions); + return transformReply ? + transformReply(reply, redisArgs.preserve) : + reply; + }; + } + + private static _createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: NamespaceProxyPool, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this.self.sendCommand(redisArgs, this.self._commandOptions); + return transformReply ? + transformReply(reply, redisArgs.preserve) : + reply; + }; + } + + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return async function (this: NamespaceProxyPool, ...args: Array) { + const fnArgs = fn.transformArguments(...args), + reply = await this.self.sendCommand( + prefix.concat(fnArgs), + this.self._commandOptions + ); + return transformReply ? + transformReply(reply, fnArgs.preserve) : + reply; + }; + } + + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + const prefix = scriptArgumentsPrefix(script), + transformReply = getTransformReply(script, resp); + return async function (this: ProxyPool, ...args: Array) { + const scriptArgs = script.transformArguments(...args), + redisArgs = prefix.concat(scriptArgs), + reply = await this.executeScript(script, redisArgs, this._commandOptions); + return transformReply ? + transformReply(reply, scriptArgs.preserve) : + reply; + }; + } + + static create< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping = {} + >( + // clientFactory: () => RedisClientType, + clientOptions?: RedisClientOptions, + options?: Partial + ) { + // @ts-ignore + const Pool = attachConfig({ + BaseClass: RedisClientPool, + commands: COMMANDS, + createCommand: RedisClientPool._createCommand, + createModuleCommand: RedisClientPool._createModuleCommand, + createFunctionCommand: RedisClientPool._createFunctionCommand, + createScriptCommand: RedisClientPool._createScriptCommand, + config: clientOptions + }); + + // returning a "proxy" to prevent the namespaces.self to leak between "proxies" + return Object.create( + new Pool( + RedisClient.factory(clientOptions).bind(undefined, clientOptions), + options + ) + ) as RedisClientPoolType; + } + + // TODO: defaults + private static _DEFAULTS = { + minimum: 1, + maximum: 100, + acquireTimeout: 3000, + cleanupDelay: 3000 + } satisfies RedisPoolOptions; + + private readonly _clientFactory: () => RedisClientType; + private readonly _options: RedisPoolOptions; + + private readonly _idleClients = new SinglyLinkedList>(); + + /** + * The number of idle clients. + */ + get idleClients() { + return this._idleClients.length; + } + + private readonly _clientsInUse = new DoublyLinkedList>(); + + /** + * The number of clients in use. + */ + get clientsInUse() { + return this._clientsInUse.length; + } + + private readonly _connectingClients = 0; + + /** + * The number of clients that are currently connecting. + */ + get connectingClients() { + return this._connectingClients; + } + + /** + * The total number of clients in the pool (including connecting, idle, and in use). + */ + get totalClients() { + return this._idleClients.length + this._clientsInUse.length; + } + + private readonly _tasksQueue = new SinglyLinkedList<{ + timeout: NodeJS.Timeout | undefined; + resolve: (value: unknown) => unknown; + reject: (reason?: unknown) => unknown; + fn: PoolTask; + }>(); + + /** + * The number of tasks waiting for a client to become available. + */ + get tasksQueueLength() { + return this._tasksQueue.length; + } + + private _isOpen = false; + + /** + * Whether the pool is open (either connecting or connected). + */ + get isOpen() { + return this._isOpen; + } + + private _isClosing = false; + + /** + * Whether the pool is closing (*not* closed). + */ + get isClosing() { + return this._isClosing; + } + + /** + * You are probably looking for {@link RedisClient.pool `RedisClient.pool`}, + * {@link RedisClientPool.fromClient `RedisClientPool.fromClient`}, + * or {@link RedisClientPool.fromOptions `RedisClientPool.fromOptions`}... + */ + constructor( + clientFactory: () => RedisClientType, + options?: Partial + ) { + super(); + + this._clientFactory = clientFactory; + this._options = { + ...RedisClientPool._DEFAULTS, + ...options + }; + } + + private _self = this; + private _commandOptions?: CommandOptions; + + withCommandOptions< + OPTIONS extends CommandOptions, + TYPE_MAPPING extends TypeMapping + >(options: OPTIONS) { + const proxy = Object.create(this._self); + proxy._commandOptions = options; + return proxy as RedisClientPoolType< + M, + F, + S, + RESP, + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {} + >; + } + + private _commandOptionsProxy< + K extends keyof CommandOptions, + V extends CommandOptions[K] + >( + key: K, + value: V + ) { + const proxy = Object.create(this._self); + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy as RedisClientPoolType< + M, + F, + S, + RESP, + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING + >; + } + + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping: TYPE_MAPPING) { + return this._commandOptionsProxy('typeMapping', typeMapping); + } + + /** + * Override the `abortSignal` command option + */ + withAbortSignal(abortSignal: AbortSignal) { + return this._commandOptionsProxy('abortSignal', abortSignal); + } + + /** + * Override the `asap` command option to `true` + * TODO: remove? + */ + asap() { + return this._commandOptionsProxy('asap', true); + } + + async connect() { + if (this._isOpen) return; // TODO: throw error? + + this._isOpen = true; + + const promises = []; + while (promises.length < this._options.minimum) { + promises.push(this._create()); + } + + try { + await Promise.all(promises); + return this as unknown as RedisClientPoolType; + } catch (err) { + this.destroy(); + throw err; + } + } + + private async _create() { + const node = this._clientsInUse.push( + this._clientFactory() + .on('error', (err: Error) => this.emit('error', err)) + ); + + try { + await node.value.connect(); + } catch (err) { + this._clientsInUse.remove(node); + throw err; + } + + this._returnClient(node); + } + + execute(fn: PoolTask): Promise { + return new Promise((resolve, reject) => { + const client = this._idleClients.shift(), + { tail } = this._tasksQueue; + if (!client) { + let timeout; + if (this._options.acquireTimeout > 0) { + timeout = setTimeout( + () => { + this._tasksQueue.remove(task, tail); + reject(new TimeoutError('Timeout waiting for a client')); // TODO: message + }, + this._options.acquireTimeout + ); + } + + const task = this._tasksQueue.push({ + timeout, + // @ts-ignore + resolve, + reject, + fn + }); + + if (this.totalClients < this._options.maximum) { + this._create(); + } + + return; + } + + const node = this._clientsInUse.push(client); + // @ts-ignore + this._executeTask(node, resolve, reject, fn); + }); + } + + private _executeTask( + node: DoublyLinkedNode>, + resolve: (value: T | PromiseLike) => void, + reject: (reason?: unknown) => void, + fn: PoolTask + ) { + const result = fn(node.value); + if (result instanceof Promise) { + result.then(resolve, reject); + result.finally(() => this._returnClient(node)) + } else { + resolve(result); + this._returnClient(node); + } + } + + private _returnClient(node: DoublyLinkedNode>) { + const task = this._tasksQueue.shift(); + if (task) { + this._executeTask(node, task.resolve, task.reject, task.fn); + return; + } + + this._clientsInUse.remove(node); + this._idleClients.push(node.value); + + this._scheduleCleanup(); + } + + cleanupTimeout?: NodeJS.Timeout; + + private _scheduleCleanup() { + if (this.totalClients <= this._options.minimum) return; + + clearTimeout(this.cleanupTimeout); + this.cleanupTimeout = setTimeout(() => this._cleanup(), this._options.cleanupDelay); + } + + private _cleanup() { + const toDestroy = Math.min(this._idleClients.length, this.totalClients - this._options.minimum); + for (let i = 0; i < toDestroy; i++) { + // TODO: shift vs pop + this._idleClients.shift()!.destroy(); + } + } + + sendCommand( + args: Array, + options?: CommandOptions + ) { + return this.execute(client => client.sendCommand(args, options)); + } + + executeScript( + script: RedisScript, + args: Array, + options?: CommandOptions + ) { + return this.execute(client => client.executeScript(script, args, options)); + } + + async close() { + if (this._isClosing) return; // TODO: throw err? + if (!this._isOpen) return; // TODO: throw err? + + this._isClosing = true; + + try { + const promises = []; + + for (const client of this._idleClients) { + promises.push(client.close()); + } + + for (const client of this._clientsInUse) { + promises.push(client.close()); + } + + await Promise.all(promises); + + this._idleClients.reset(); + this._clientsInUse.reset(); + } catch (err) { + + } finally { + this._isClosing = false; + } + } + + destroy() { + for (const client of this._idleClients) { + client.destroy(); + } + this._idleClients.reset(); + + for (const client of this._clientsInUse) { + client.destroy(); + } + this._clientsInUse.reset(); + + this._isOpen = false; + } +} diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index e0386e74c58..718e1198728 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,4 +1,4 @@ -import { RedisClientOptions } from '../client'; +import { RedisClientOptions, RedisClientType } from '../client'; import { CommandOptions } from '../client/commands-queue'; import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; @@ -224,8 +224,8 @@ export default class RedisCluster< BaseClass: RedisCluster, commands: COMMANDS, createCommand: RedisCluster._createCommand, - createFunctionCommand: RedisCluster._createFunctionCommand, createModuleCommand: RedisCluster._createModuleCommand, + createFunctionCommand: RedisCluster._createFunctionCommand, createScriptCommand: RedisCluster._createScriptCommand, config }); @@ -233,8 +233,7 @@ export default class RedisCluster< Cluster.prototype.Multi = RedisClusterMultiCommand.extend(config); return (options?: Omit>) => { - // returning a proxy of the client to prevent the namespaces.self to leak between proxies - // namespaces will be bootstraped on first access per proxy + // returning a "proxy" to prevent the namespaces.self to leak between "proxies" return Object.create(new Cluster(options)) as RedisClusterType; }; } @@ -388,21 +387,17 @@ export default class RedisCluster< return this._commandOptionsProxy('policies', policies); } - async sendCommand( + async #execute( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, - args: CommandArguments, - options?: ClusterCommandOptions, - deafultPolicies?: CommandPolicies + fn: (client: RedisClientType) => Promise ): Promise { - // const requestPolicy = options?.policies?.request ?? deafultPolicies?.request, - // responsePolicy = options?.policies?.response ?? deafultPolicies?.response; - const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; - let client = await this._slots.getClient(firstKey, isReadonly); - for (let i = 0; ; i++) { + let client = await this._slots.getClient(firstKey, isReadonly), + i = 0; + while (true) { try { - return await client.sendCommand(args, options); + return await fn(client); } catch (err) { // TODO: error class if (++i > maxCommandRedirections || !(err instanceof Error)) { @@ -424,39 +419,69 @@ export default class RedisCluster< await redirectTo.asking(); client = redirectTo; continue; - } else if (err.message.startsWith('MOVED')) { + } + + if (err.message.startsWith('MOVED')) { await this._slots.rediscover(client); client = await this._slots.getClient(firstKey, isReadonly); continue; } throw err; - } + } } } + async sendCommand( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + args: CommandArguments, + options?: ClusterCommandOptions, + defaultPolicies?: CommandPolicies + ): Promise { + return this.#execute( + firstKey, + isReadonly, + client => client.sendCommand(args, options) + ); + } + + executeScript( + script: RedisScript, + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + args: Array, + options?: CommandOptions + ) { + return this.#execute( + firstKey, + isReadonly, + client => client.executeScript(script, args, options) + ); + } + /** * @internal */ - async executePipeline( + async _executePipeline( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, commands: Array ) { const client = await this._slots.getClient(firstKey, isReadonly); - return client.executePipeline(commands); + return client._executePipeline(commands); } /** * @internal */ - async executeMulti( + async _executeMulti( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, commands: Array ) { const client = await this._slots.getClient(firstKey, isReadonly); - return client.executeMulti(commands); + return client._executeMulti(commands); } MULTI(routing?: RedisArgument): RedisClusterMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index dc351d42fc4..a0292356dab 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -213,7 +213,7 @@ export default class RedisClusterMultiCommand { if (execAsPipeline) return this.execAsPipeline(); return this._multi.transformReplies( - await this._cluster.executeMulti( + await this._cluster._executeMulti( this._firstKey, this._isReadonly, this._multi.queue @@ -231,7 +231,7 @@ export default class RedisClusterMultiCommand { if (this._multi.queue.length === 0) return [] as MultiReplyType; return this._multi.transformReplies( - await this._cluster.executePipeline( + await this._cluster._executePipeline( this._firstKey, this._isReadonly, this._multi.queue diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index c0815ebde8a..33a2129b2b4 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -67,3 +67,5 @@ export class ErrorReply extends Error { export class SimpleError extends ErrorReply {} export class BlobError extends ErrorReply {} + +export class TimeoutError extends Error {} diff --git a/test/package-lock.json b/test/package-lock.json deleted file mode 100644 index 878a92a6ad2..00000000000 --- a/test/package-lock.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@redis/client": "next" - } - }, - "node_modules/@redis/client": { - "version": "2.0.0-next.2", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-2.0.0-next.2.tgz", - "integrity": "sha512-+sf9n+PBHac2xXSofSX0x79cYa5H4ighu80F993q4H1T109ZthFNGBmg33DfwfPrDMKc256qTXvsb0lCqzwMmg==", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "engines": { - "node": ">= 4" - } - } - } -} diff --git a/test/package.json b/test/package.json deleted file mode 100644 index 23ca20e0589..00000000000 --- a/test/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "test", - "version": "1.0.0", - "description": "", - "main": "index.js", - "type": "module", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "@redis/client": "next" - } -} diff --git a/test/test.js b/test/test.js deleted file mode 100644 index f9b83cae7aa..00000000000 --- a/test/test.js +++ /dev/null @@ -1,21 +0,0 @@ -import { RESP_TYPES, createClient } from '@redis/client'; - -const client = createClient({ - RESP: 3, - commandOptions: { - typeMapping: { - [RESP_TYPES.MAP]: Map - } - } -}); -client.on('error', err => console.error(err)); - -await client.connect(); - -console.log( - await client.flushAll(), - await client.hSet('key', 'field', 'value'), - await client.hGetAll('key') -) - -client.destroy(); From 228b1d97c604580a8fbf44295578475c89e439f7 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 14:47:38 -0400 Subject: [PATCH 214/325] fix MSET --- packages/json/lib/commands/MSET.spec.ts | 58 ++++++++++++------------- packages/json/lib/commands/MSET.ts | 24 +++++----- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/json/lib/commands/MSET.spec.ts b/packages/json/lib/commands/MSET.spec.ts index 53d4d822505..de2afa571b1 100644 --- a/packages/json/lib/commands/MSET.spec.ts +++ b/packages/json/lib/commands/MSET.spec.ts @@ -1,35 +1,35 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MSET'; +import MSET from './MSET'; describe('MSET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments([{ - key: '1', - path: '$', - value: 1 - }, { - key: '2', - path: '$', - value: '2' - }]), - ['JSON.MSET', '1', '$', '1', '2', '$', '"2"'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MSET.transformArguments([{ + key: '1', + path: '$', + value: 1 + }, { + key: '2', + path: '$', + value: '2' + }]), + ['JSON.MSET', '1', '$', '1', '2', '$', '"2"'] + ); + }); - testUtils.testWithClient('client.json.mSet', async client => { - assert.deepEqual( - await client.json.mSet([{ - key: '1', - path: '$', - value: 1 - }, { - key: '2', - path: '$', - value: '2' - }]), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.json.mSet', async client => { + assert.equal( + await client.json.mSet([{ + key: '1', + path: '$', + value: 1 + }, { + key: '2', + path: '$', + value: '2' + }]), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts index 67228f264d2..ac4105a85ab 100644 --- a/packages/json/lib/commands/MSET.ts +++ b/packages/json/lib/commands/MSET.ts @@ -1,16 +1,16 @@ +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisJSON, transformRedisJsonArgument } from '.'; -import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; -export const FIRST_KEY_INDEX = 1; - -interface JsonMSetItem { - key: RedisCommandArgument; - path: RedisCommandArgument; - value: RedisJSON; +export interface JsonMSetItem { + key: RedisArgument; + path: RedisArgument; + value: RedisJSON; } -export function transformArguments(items: Array): Array { - +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(items: Array) { const args = new Array(1 + items.length * 3); args[0] = 'JSON.MSET'; @@ -23,6 +23,6 @@ export function transformArguments(items: Array): Array { } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; From 823aba2c3c95f1d81a6c010e2550af581d51b9fd Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 14:48:14 -0400 Subject: [PATCH 215/325] JSON.MERGE --- packages/json/lib/commands/MERGE.spec.ts | 19 +++++++++++++++++++ packages/json/lib/commands/MERGE.ts | 16 ++++++++++++++++ packages/json/lib/commands/index.ts | 3 +++ 3 files changed, 38 insertions(+) create mode 100644 packages/json/lib/commands/MERGE.spec.ts create mode 100644 packages/json/lib/commands/MERGE.ts diff --git a/packages/json/lib/commands/MERGE.spec.ts b/packages/json/lib/commands/MERGE.spec.ts new file mode 100644 index 00000000000..fbb84aaaeba --- /dev/null +++ b/packages/json/lib/commands/MERGE.spec.ts @@ -0,0 +1,19 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import MERGE from './MERGE'; + +describe('MERGE', () => { + it('transformArguments', () => { + assert.deepEqual( + MERGE.transformArguments('key', '$', 'value'), + ['JSON.MERGE', 'key', '$', 'value'] + ); + }); + + testUtils.testWithClient('client.json.merge', async client => { + assert.equal( + await client.json.merge('key', '$', 'value'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/json/lib/commands/MERGE.ts b/packages/json/lib/commands/MERGE.ts new file mode 100644 index 00000000000..90cd080a06e --- /dev/null +++ b/packages/json/lib/commands/MERGE.ts @@ -0,0 +1,16 @@ +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisJSON, transformRedisJsonArgument } from '.'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, path: RedisArgument, value: RedisJSON) { + return [ + 'JSON.MERGE', + key, + path, + transformRedisJsonArgument(value) + ]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index 7fad5d17691..5404da74f70 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -9,6 +9,7 @@ import DEBUG_MEMORY from './DEBUG_MEMORY'; import DEL from './DEL'; import FORGET from './FORGET'; // import GET from './GET'; +import MERGE from './MERGE'; // import MGET from './MGET'; import MSET from './MSET'; import NUMINCRBY from './NUMINCRBY'; @@ -45,6 +46,8 @@ export default { forget: FORGET, // GET, // get: GET, + MERGE, + merge: MERGE, // MGET, // mGet: MGET, MSET, From 5bab7fa6fd707abd00570875bd4179c96349999e Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 14:52:23 -0400 Subject: [PATCH 216/325] mark NUMMULTBY as deprecated --- packages/json/lib/commands/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index 5404da74f70..66c0f5efe9f 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -54,7 +54,13 @@ export default { mSet: MSET, NUMINCRBY, numIncrBy: NUMINCRBY, + /** + * @deprecated since JSON version 2.0 + */ NUMMULTBY, + /** + * @deprecated since JSON version 2.0 + */ numMultBy: NUMMULTBY, OBJKEYS, objKeys: OBJKEYS, From c12dc79950823cdfccf730ee181cb225252e501d Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 18:19:31 -0400 Subject: [PATCH 217/325] RedisJSON --- docs/v4-to-v5.md | 1 + .../lib/commands/generic-transformers.ts | 4 + packages/json/lib/commands/ARRAPPEND.spec.ts | 10 +- packages/json/lib/commands/ARRAPPEND.ts | 18 ++- packages/json/lib/commands/ARRINDEX.spec.ts | 15 ++- packages/json/lib/commands/ARRINSERT.spec.ts | 10 +- packages/json/lib/commands/ARRINSERT.ts | 18 +-- packages/json/lib/commands/ARRLEN.spec.ts | 2 +- packages/json/lib/commands/ARRLEN.ts | 2 +- packages/json/lib/commands/ARRPOP.spec.ts | 111 ++++++++++-------- packages/json/lib/commands/ARRPOP.ts | 43 ++++--- packages/json/lib/commands/CLEAR.spec.ts | 10 +- packages/json/lib/commands/CLEAR.ts | 2 +- .../json/lib/commands/DEBUG_MEMORY.spec.ts | 2 +- packages/json/lib/commands/DEBUG_MEMORY.ts | 2 +- packages/json/lib/commands/DEL.spec.ts | 2 +- packages/json/lib/commands/DEL.ts | 2 +- packages/json/lib/commands/FORGET.spec.ts | 2 +- packages/json/lib/commands/FORGET.ts | 2 +- packages/json/lib/commands/GET.spec.ts | 103 +++++----------- packages/json/lib/commands/GET.ts | 64 ++++------ packages/json/lib/commands/MERGE.spec.ts | 2 +- packages/json/lib/commands/MGET.spec.ts | 26 ++-- packages/json/lib/commands/MGET.ts | 26 ++-- packages/json/lib/commands/MSET.ts | 10 +- packages/json/lib/commands/NUMINCRBY.spec.ts | 10 +- packages/json/lib/commands/NUMINCRBY.ts | 6 +- packages/json/lib/commands/NUMMULTBY.spec.ts | 10 +- packages/json/lib/commands/NUMMULTBY.ts | 5 +- packages/json/lib/commands/OBJKEYS.spec.ts | 4 +- packages/json/lib/commands/OBJKEYS.ts | 2 +- packages/json/lib/commands/OBJLEN.ts | 2 +- packages/json/lib/commands/STRAPPEND.ts | 7 +- packages/json/lib/commands/TOGGLE.spec.ts | 2 +- packages/json/lib/commands/TYPE.spec.ts | 12 +- packages/json/lib/commands/index.ts | 42 +++---- 36 files changed, 277 insertions(+), 314 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index e1d67a9d0f8..1ad3aab8dac 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -178,6 +178,7 @@ Some command arguments/replies have changed to align more closely to data types - `TOPK.QUERY`: `Array` -> `Array` - `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` - `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] +- `JSON.ARRPOP`: `path` and `index` arguments moved to `{ path: string; index: number; }` [^future-proofing] - `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRAPPEND`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] - : `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 789464fddb7..5b8aa12d7e5 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -4,6 +4,10 @@ export function isNullReply(reply: unknown): reply is NullReply { return reply === null; } +export function isArrayReply(reply: unknown): reply is ArrayReply { + return Array.isArray(reply); +} + export const transformBooleanReply = { 2: (reply: NumberReply<0 | 1>) => reply as unknown as UnwrapReply === 1, 3: undefined as unknown as () => BooleanReply diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts index 991185dd924..c5bc636f951 100644 --- a/packages/json/lib/commands/ARRAPPEND.spec.ts +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -4,14 +4,14 @@ import ARRAPPEND from './ARRAPPEND'; describe('ARRAPPEND', () => { describe('transformArguments', () => { - it('single JSON', () => { + it('single element', () => { assert.deepEqual( - ARRAPPEND.transformArguments('key', '$', 1), - ['JSON.ARRAPPEND', 'key', '$', '1'] + ARRAPPEND.transformArguments('key', '$', 'value'), + ['JSON.ARRAPPEND', 'key', '$', '"value"'] ); }); - it('multiple JSONs', () => { + it('multiple elements', () => { assert.deepEqual( ARRAPPEND.transformArguments('key', '$', 1, 2), ['JSON.ARRAPPEND', 'key', '$', '1', '2'] @@ -22,7 +22,7 @@ describe('ARRAPPEND', () => { testUtils.testWithClient('client.json.arrAppend', async client => { const [, reply] = await Promise.all([ client.json.set('key', '$', []), - client.json.arrAppend('key', '$', 1) + client.json.arrAppend('key', '$', 'value') ]); assert.deepEqual(reply, [1]); diff --git a/packages/json/lib/commands/ARRAPPEND.ts b/packages/json/lib/commands/ARRAPPEND.ts index 7f5b49eead2..6f486a301d7 100644 --- a/packages/json/lib/commands/ARRAPPEND.ts +++ b/packages/json/lib/commands/ARRAPPEND.ts @@ -4,11 +4,21 @@ import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@red export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, path: RedisArgument, ...jsons: Array) { - const args = ['JSON.ARRAPPEND', key, path]; + transformArguments( + key: RedisArgument, + path: RedisArgument, + json: RedisJSON, + ...jsons: Array + ) { + const args = new Array(4 + jsons.length); + args[0] = 'JSON.ARRAPPEND'; + args[1] = key; + args[2] = path; + args[3] = transformRedisJsonArgument(json); - for (const json of jsons) { - args.push(transformRedisJsonArgument(json)); + let argsIndex = 4; + for (let i = 0; i < jsons.length; i++) { + args[argsIndex++] = transformRedisJsonArgument(jsons[i]); } return args; diff --git a/packages/json/lib/commands/ARRINDEX.spec.ts b/packages/json/lib/commands/ARRINDEX.spec.ts index fc65dbdf0fa..42d98c15329 100644 --- a/packages/json/lib/commands/ARRINDEX.spec.ts +++ b/packages/json/lib/commands/ARRINDEX.spec.ts @@ -6,33 +6,32 @@ describe('JSON.ARRINDEX', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( - ARRINDEX.transformArguments('key', '$', 'json'), - ['JSON.ARRINDEX', 'key', '$', '"json"'] + ARRINDEX.transformArguments('key', '$', 'value'), + ['JSON.ARRINDEX', 'key', '$', '"value"'] ); }); - describe('with range', () => { it('start only', () => { assert.deepEqual( - ARRINDEX.transformArguments('key', '$', 'json', { + ARRINDEX.transformArguments('key', '$', 'value', { range: { start: 0 } }), - ['JSON.ARRINDEX', 'key', '$', '"json"', '0'] + ['JSON.ARRINDEX', 'key', '$', '"value"', '0'] ); }); it('with start and stop', () => { assert.deepEqual( - ARRINDEX.transformArguments('key', '$', 'json', { + ARRINDEX.transformArguments('key', '$', 'value', { range: { start: 0, stop: 1 } }), - ['JSON.ARRINDEX', 'key', '$', '"json"', '0', '1'] + ['JSON.ARRINDEX', 'key', '$', '"value"', '0', '1'] ); }); }); @@ -41,7 +40,7 @@ describe('JSON.ARRINDEX', () => { testUtils.testWithClient('client.json.arrIndex', async client => { const [, reply] = await Promise.all([ client.json.set('key', '$', []), - client.json.arrIndex('key', '$', 'json') + client.json.arrIndex('key', '$', 'value') ]); assert.deepEqual(reply, [-1]); diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts index e0815935396..c9f4c36a1ea 100644 --- a/packages/json/lib/commands/ARRINSERT.spec.ts +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -4,14 +4,14 @@ import ARRINSERT from './ARRINSERT'; describe('JSON.ARRINSERT', () => { describe('transformArguments', () => { - it('single JSON', () => { + it('single element', () => { assert.deepEqual( - ARRINSERT.transformArguments('key', '$', 0, 'json'), - ['JSON.ARRINSERT', 'key', '$', '0', '"json"'] + ARRINSERT.transformArguments('key', '$', 0, 'value'), + ['JSON.ARRINSERT', 'key', '$', '0', '"value"'] ); }); - it('multiple JSONs', () => { + it('multiple elements', () => { assert.deepEqual( ARRINSERT.transformArguments('key', '$', 0, '1', '2'), ['JSON.ARRINSERT', 'key', '$', '0', '"1"', '"2"'] @@ -22,7 +22,7 @@ describe('JSON.ARRINSERT', () => { testUtils.testWithClient('client.json.arrInsert', async client => { const [, reply] = await Promise.all([ client.json.set('key', '$', []), - client.json.arrInsert('key', '$', 0, 'json') + client.json.arrInsert('key', '$', 0, 'value') ]); assert.deepEqual(reply, [1]); diff --git a/packages/json/lib/commands/ARRINSERT.ts b/packages/json/lib/commands/ARRINSERT.ts index da2a3ed440a..c0891884725 100644 --- a/packages/json/lib/commands/ARRINSERT.ts +++ b/packages/json/lib/commands/ARRINSERT.ts @@ -11,16 +11,16 @@ export default { json: RedisJSON, ...jsons: Array ) { - const args = [ - 'JSON.ARRINSERT', - key, - path, - index.toString(), - transformRedisJsonArgument(json) - ]; + const args = new Array(4 + jsons.length); + args[0] = 'JSON.ARRINSERT'; + args[1] = key; + args[2] = path; + args[3] = index.toString(); + args[4] = transformRedisJsonArgument(json); - for (const json of jsons) { - args.push(transformRedisJsonArgument(json)); + let argsIndex = 5; + for (let i = 0; i < jsons.length; i++) { + args[argsIndex++] = transformRedisJsonArgument(jsons[i]); } return args; diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts index ec2e0e46f5e..743c6fa0bce 100644 --- a/packages/json/lib/commands/ARRLEN.spec.ts +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -27,6 +27,6 @@ describe('JSON.ARRLEN', () => { client.json.arrLen('key') ]); - assert.deepEqual(reply, 0); + assert.equal(reply, 0); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/ARRLEN.ts b/packages/json/lib/commands/ARRLEN.ts index 5763b893fa3..d30032c7d86 100644 --- a/packages/json/lib/commands/ARRLEN.ts +++ b/packages/json/lib/commands/ARRLEN.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonArrLenOptions) { const args = ['JSON.ARRLEN', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/ARRPOP.spec.ts b/packages/json/lib/commands/ARRPOP.spec.ts index 7c2ec365eb6..91d8c962816 100644 --- a/packages/json/lib/commands/ARRPOP.spec.ts +++ b/packages/json/lib/commands/ARRPOP.spec.ts @@ -1,57 +1,66 @@ 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'] - ); - }); +import ARRPOP from './ARRPOP'; + +describe('JSON.ARRPOP', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ARRPOP.transformArguments('key'), + ['JSON.ARRPOP', 'key'] + ); + }); + + it('with path', () => { + assert.deepEqual( + ARRPOP.transformArguments('key', { + path: '$' + }), + ['JSON.ARRPOP', 'key', '$'] + ); }); - describe('client.json.arrPop', () => { - testUtils.testWithClient('null', async client => { - await client.json.set('key', '.', []); - - assert.equal( - await client.json.arrPop('key', '.'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with value', async client => { - await client.json.set('key', '.', ['value']); - - assert.equal( - await client.json.arrPop('key', '.'), - 'value' - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('array', async client => { - await client.json.set('key', '$', ['value']); - - assert.deepEqual( - await client.json.arrPop('key', '$'), - ['value'] - ); - }, GLOBAL.SERVERS.OPEN); + it('with path and index', () => { + assert.deepEqual( + ARRPOP.transformArguments('key', { + path: '$', + index: 0 + }), + ['JSON.ARRPOP', 'key', '$', '0'] + ); }); + }); + + describe('client.json.arrPop', () => { + testUtils.testWithClient('without path and value', async client => { + const [, reply] = await Promise.all([ + client.json.set('key', '$', []), + client.json.arrPop('key') + ]); + + assert.equal(reply, null); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('. path with value', async client => { + const [, reply] = await Promise.all([ + client.json.set('key', '.', ['value']), + client.json.arrPop('key', { + path: '.' + }) + ]); + + assert.equal(reply, 'value'); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('$ path with value', async client => { + const [, reply] = await Promise.all([ + client.json.set('key', '$', ['value']), + client.json.arrPop('key', { + path: '$' + }) + ]); + + assert.deepEqual(reply, ['value']); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/json/lib/commands/ARRPOP.ts b/packages/json/lib/commands/ARRPOP.ts index 18830c0d314..4eafe9fdde4 100644 --- a/packages/json/lib/commands/ARRPOP.ts +++ b/packages/json/lib/commands/ARRPOP.ts @@ -1,27 +1,32 @@ -import { RedisJSON, transformRedisJsonNullReply } from '.'; +import { RedisArgument, ArrayReply, NullReply, BlobStringReply, Command, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; +import { isArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformRedisJsonNullReply } from '.'; -export const FIRST_KEY_INDEX = 1; +export interface RedisArrPopOptions { + path: RedisArgument; + index?: number; +} -export function transformArguments(key: string, path?: string, index?: number): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, options?: RedisArrPopOptions) { const args = ['JSON.ARRPOP', key]; - if (path) { - args.push(path); + if (options) { + args.push(options.path); - if (index !== undefined && index !== null) { - args.push(index.toString()); - } + if (options.index !== undefined) { + args.push(options.index.toString()); + } } - + return args; -} - -export function transformReply(reply: null | string | Array): null | RedisJSON | Array { - if (reply === null) return null; + }, + transformReply(reply: NullReply | BlobStringReply | ArrayReply) { + return isArrayReply(reply) ? + (reply as unknown as UnwrapReply).map(item => transformRedisJsonNullReply(item)) : + transformRedisJsonNullReply(reply); + } +} as const satisfies Command; - if (Array.isArray(reply)) { - return reply.map(transformRedisJsonNullReply); - } - - return transformRedisJsonNullReply(reply); -} diff --git a/packages/json/lib/commands/CLEAR.spec.ts b/packages/json/lib/commands/CLEAR.spec.ts index e9ada575a8e..a58e16868e7 100644 --- a/packages/json/lib/commands/CLEAR.spec.ts +++ b/packages/json/lib/commands/CLEAR.spec.ts @@ -22,9 +22,11 @@ describe('JSON.CLEAR', () => { }); testUtils.testWithClient('client.json.clear', async client => { - assert.deepEqual( - await client.json.clear('key'), - 0 - ); + const [, reply] = await Promise.all([ + client.json.set('key', '$', null), + client.json.clear('key') + ]); + + assert.equal(reply, 0); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/CLEAR.ts b/packages/json/lib/commands/CLEAR.ts index 186ce296bce..23e86d900e7 100644 --- a/packages/json/lib/commands/CLEAR.ts +++ b/packages/json/lib/commands/CLEAR.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonClearOptions) { const args = ['JSON.CLEAR', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts index 8cdd2bdef99..88e59e13293 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -22,7 +22,7 @@ describe('JSON.DEBUG MEMORY', () => { }); testUtils.testWithClient('client.json.debugMemory', async client => { - assert.deepEqual( + assert.equal( await client.json.debugMemory('key'), 0 ); diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts index 17c202ff40a..a96f05b8064 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonDebugMemoryOptions) { const args = ['JSON.DEBUG', 'MEMORY', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/DEL.spec.ts b/packages/json/lib/commands/DEL.spec.ts index 590f70d7889..11e817af182 100644 --- a/packages/json/lib/commands/DEL.spec.ts +++ b/packages/json/lib/commands/DEL.spec.ts @@ -22,7 +22,7 @@ describe('JSON.DEL', () => { }); testUtils.testWithClient('client.json.del', async client => { - assert.deepEqual( + assert.equal( await client.json.del('key'), 0 ); diff --git a/packages/json/lib/commands/DEL.ts b/packages/json/lib/commands/DEL.ts index 13632840c6a..f6952a8dc63 100644 --- a/packages/json/lib/commands/DEL.ts +++ b/packages/json/lib/commands/DEL.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonDelOptions) { const args = ['JSON.DEL', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/FORGET.spec.ts b/packages/json/lib/commands/FORGET.spec.ts index ec9f2221eb7..e60e5355ad3 100644 --- a/packages/json/lib/commands/FORGET.spec.ts +++ b/packages/json/lib/commands/FORGET.spec.ts @@ -22,7 +22,7 @@ describe('JSON.FORGET', () => { }); testUtils.testWithClient('client.json.forget', async client => { - assert.deepEqual( + assert.equal( await client.json.forget('key'), 0 ); diff --git a/packages/json/lib/commands/FORGET.ts b/packages/json/lib/commands/FORGET.ts index 1820f8f2024..68335ee92e9 100644 --- a/packages/json/lib/commands/FORGET.ts +++ b/packages/json/lib/commands/FORGET.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonForgetOptions) { const args = ['JSON.FORGET', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/GET.spec.ts b/packages/json/lib/commands/GET.spec.ts index ed831689a93..dec66dbb365 100644 --- a/packages/json/lib/commands/GET.spec.ts +++ b/packages/json/lib/commands/GET.spec.ts @@ -1,78 +1,37 @@ 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'] - ); - }); +import GET from './GET'; + +describe('JSON.GET', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + GET.transformArguments('key'), + ['JSON.GET', 'key'] + ); }); - testUtils.testWithClient('client.json.get', async client => { - assert.equal( - await client.json.get('key'), - null + describe('with path', () => { + it('string', () => { + assert.deepEqual( + GET.transformArguments('key', { path: '$' }), + ['JSON.GET', 'key', '$'] ); - }, GLOBAL.SERVERS.OPEN); + }); + + it('array', () => { + assert.deepEqual( + GET.transformArguments('key', { path: ['$.1', '$.2'] }), + ['JSON.GET', 'key', '$.1', '$.2'] + ); + }); + }); + }); + + 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 index 445f0b3eaef..b7bcc52e3cb 100644 --- a/packages/json/lib/commands/GET.ts +++ b/packages/json/lib/commands/GET.ts @@ -1,42 +1,22 @@ -// import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -// import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; - -// 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): RedisCommandArguments { -// let args: RedisCommandArguments = ['JSON.GET', key]; - -// if (options?.path) { -// args = pushVariadicArguments(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 '.'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { transformRedisJsonNullReply } from '.'; + +export interface JsonGetOptions { + path?: RedisVariadicArgument; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments(key: RedisArgument, options?: JsonGetOptions) { + let args = ['JSON.GET', key]; + + if (options?.path !== undefined) { + args = pushVariadicArguments(args, options.path); + } + + return args; + }, + transformReply: transformRedisJsonNullReply +} as const satisfies Command; diff --git a/packages/json/lib/commands/MERGE.spec.ts b/packages/json/lib/commands/MERGE.spec.ts index fbb84aaaeba..a2f880176f5 100644 --- a/packages/json/lib/commands/MERGE.spec.ts +++ b/packages/json/lib/commands/MERGE.spec.ts @@ -6,7 +6,7 @@ describe('MERGE', () => { it('transformArguments', () => { assert.deepEqual( MERGE.transformArguments('key', '$', 'value'), - ['JSON.MERGE', 'key', '$', 'value'] + ['JSON.MERGE', 'key', '$', '"value"'] ); }); diff --git a/packages/json/lib/commands/MGET.spec.ts b/packages/json/lib/commands/MGET.spec.ts index 456e160dd50..79d0657bf93 100644 --- a/packages/json/lib/commands/MGET.spec.ts +++ b/packages/json/lib/commands/MGET.spec.ts @@ -1,19 +1,19 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './MGET'; +import MGET from './MGET'; describe('MGET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(['1', '2'], '$'), - ['JSON.MGET', '1', '2', '$'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + MGET.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); + 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 index 582b73bf85a..a7aea82ac2e 100644 --- a/packages/json/lib/commands/MGET.ts +++ b/packages/json/lib/commands/MGET.ts @@ -1,15 +1,17 @@ -import { RedisJSON, transformRedisJsonNullReply } from '.'; +import { RedisArgument, UnwrapReply, ArrayReply, NullReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { transformRedisJsonNullReply } from '.'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(keys: Array, path: string): Array { +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(keys: Array, path: RedisArgument) { return [ - 'JSON.MGET', - ...keys, - path + 'JSON.MGET', + ...keys, + path ]; -} - -export function transformReply(reply: Array): Array { - return reply.map(transformRedisJsonNullReply); -} + }, + transformReply(reply: UnwrapReply>) { + return reply.map(json => transformRedisJsonNullReply(json)) + } +} as const satisfies Command; diff --git a/packages/json/lib/commands/MSET.ts b/packages/json/lib/commands/MSET.ts index ac4105a85ab..a081bfd543a 100644 --- a/packages/json/lib/commands/MSET.ts +++ b/packages/json/lib/commands/MSET.ts @@ -11,15 +11,15 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, transformArguments(items: Array) { - const args = new Array(1 + items.length * 3); + const args = new Array(1 + items.length * 3); args[0] = 'JSON.MSET'; let argsIndex = 1; for (let i = 0; i < items.length; i++) { - const item = items[i]; - args[argsIndex++] = item.key; - args[argsIndex++] = item.path; - args[argsIndex++] = transformRedisJsonArgument(item.value); + const item = items[i]; + args[argsIndex++] = item.key; + args[argsIndex++] = item.path; + args[argsIndex++] = transformRedisJsonArgument(item.value); } return args; diff --git a/packages/json/lib/commands/NUMINCRBY.spec.ts b/packages/json/lib/commands/NUMINCRBY.spec.ts index ee3675643dc..d2b21df4cac 100644 --- a/packages/json/lib/commands/NUMINCRBY.spec.ts +++ b/packages/json/lib/commands/NUMINCRBY.spec.ts @@ -11,11 +11,11 @@ describe('JSON.NUMINCRBY', () => { }); testUtils.testWithClient('client.json.numIncrBy', async client => { - await client.json.set('key', '$', 0); + const [, reply] = await Promise.all([ + client.json.set('key', '$', 0), + client.json.numIncrBy('key', '$', 1) + ]); - assert.deepEqual( - await client.json.numIncrBy('key', '$', 1), - [1] - ); + assert.deepEqual(reply, [1]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/NUMINCRBY.ts b/packages/json/lib/commands/NUMINCRBY.ts index 68c1de2b0bb..65cc7db68a9 100644 --- a/packages/json/lib/commands/NUMINCRBY.ts +++ b/packages/json/lib/commands/NUMINCRBY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, DoubleReply, NullReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, ArrayReply, NumberReply, DoubleReply, NullReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { FIRST_KEY_INDEX: 1, @@ -8,8 +8,8 @@ export default { }, transformReply: { 2: (reply: UnwrapReply) => { - return JSON.parse(reply.toString()) as number | Array; + return JSON.parse(reply.toString()) as number | Array; }, - 3: undefined as unknown as () => NumberReply | DoubleReply | NullReply + 3: undefined as unknown as () => ArrayReply } } as const satisfies Command; diff --git a/packages/json/lib/commands/NUMMULTBY.spec.ts b/packages/json/lib/commands/NUMMULTBY.spec.ts index 471c276f0ba..a02a8f75cc9 100644 --- a/packages/json/lib/commands/NUMMULTBY.spec.ts +++ b/packages/json/lib/commands/NUMMULTBY.spec.ts @@ -11,11 +11,11 @@ describe('JSON.NUMMULTBY', () => { }); testUtils.testWithClient('client.json.numMultBy', async client => { - await client.json.set('key', '$', 1); + const [, reply] = await Promise.all([ + client.json.set('key', '$', 1), + client.json.numMultBy('key', '$', 2) + ]); - assert.deepEqual( - await client.json.numMultBy('key', '$', 2), - [2] - ); + assert.deepEqual(reply, [2]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/NUMMULTBY.ts b/packages/json/lib/commands/NUMMULTBY.ts index 11a56d0d729..255685a9a50 100644 --- a/packages/json/lib/commands/NUMMULTBY.ts +++ b/packages/json/lib/commands/NUMMULTBY.ts @@ -1,4 +1,5 @@ -import { RedisArgument, Command, ArrayReply, NumberReply, DoubleReply, NullReply } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import NUMINCRBY from './NUMINCRBY'; export default { FIRST_KEY_INDEX: 1, @@ -6,5 +7,5 @@ export default { transformArguments(key: RedisArgument, path: RedisArgument, by: number) { return ['JSON.NUMMULTBY', key, path, by.toString()]; }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: NUMINCRBY.transformReply } as const satisfies Command; diff --git a/packages/json/lib/commands/OBJKEYS.spec.ts b/packages/json/lib/commands/OBJKEYS.spec.ts index ccdb7f97f6a..8c3222d671b 100644 --- a/packages/json/lib/commands/OBJKEYS.spec.ts +++ b/packages/json/lib/commands/OBJKEYS.spec.ts @@ -22,9 +22,9 @@ describe('JSON.OBJKEYS', () => { }); testUtils.testWithClient('client.json.objKeys', async client => { - assert.deepEqual( + assert.equal( await client.json.objKeys('key'), - [null] + null ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/OBJKEYS.ts b/packages/json/lib/commands/OBJKEYS.ts index 6973d6b1f95..fb8ae6bb034 100644 --- a/packages/json/lib/commands/OBJKEYS.ts +++ b/packages/json/lib/commands/OBJKEYS.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonObjKeysOptions) { const args = ['JSON.OBJKEYS', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/OBJLEN.ts b/packages/json/lib/commands/OBJLEN.ts index 756651bde90..f9c45e336ad 100644 --- a/packages/json/lib/commands/OBJLEN.ts +++ b/packages/json/lib/commands/OBJLEN.ts @@ -10,7 +10,7 @@ export default { transformArguments(key: RedisArgument, options?: JsonObjLenOptions) { const args = ['JSON.OBJLEN', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } diff --git a/packages/json/lib/commands/STRAPPEND.ts b/packages/json/lib/commands/STRAPPEND.ts index ad3cd377c9d..12ee7cc394c 100644 --- a/packages/json/lib/commands/STRAPPEND.ts +++ b/packages/json/lib/commands/STRAPPEND.ts @@ -1,4 +1,5 @@ import { RedisArgument, Command, NullReply, NumberReply, ArrayReply } from '@redis/client/dist/lib/RESP/types'; +import { transformRedisJsonArgument } from '.'; export interface JsonStrAppendOptions { path?: RedisArgument; @@ -7,14 +8,14 @@ export interface JsonStrAppendOptions { export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, - transformArguments(key: RedisArgument, append: RedisArgument, options?: JsonStrAppendOptions) { + transformArguments(key: RedisArgument, append: string, options?: JsonStrAppendOptions) { const args = ['JSON.STRAPPEND', key]; - if (options?.path) { + if (options?.path !== undefined) { args.push(options.path); } - args.push(append); + args.push(transformRedisJsonArgument(append)); return args; }, transformReply: undefined as unknown as () => NumberReply | ArrayReply diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts index 1c785d97b17..90a456b9209 100644 --- a/packages/json/lib/commands/TOGGLE.spec.ts +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -12,7 +12,7 @@ describe('JSON.TOGGLE', () => { testUtils.testWithClient('client.json.toggle', async client => { const [, reply] = await Promise.all([ - client.json.set('key', '$', ''), + client.json.set('key', '$', true), client.json.toggle('key', '$') ]); diff --git a/packages/json/lib/commands/TYPE.spec.ts b/packages/json/lib/commands/TYPE.spec.ts index 2a90a3bf9ee..b3124ceb31b 100644 --- a/packages/json/lib/commands/TYPE.spec.ts +++ b/packages/json/lib/commands/TYPE.spec.ts @@ -6,14 +6,14 @@ describe('TYPE', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( - transformArguments('key'), + TYPE.transformArguments('key'), ['JSON.TYPE', 'key'] ); }); it('with path', () => { assert.deepEqual( - transformArguments('key', { + TYPE.transformArguments('key', { path: '$' }), ['JSON.TYPE', 'key', '$'] @@ -22,11 +22,9 @@ describe('TYPE', () => { }); testUtils.testWithClient('client.json.type', async client => { - assert.deepEqual( - await client.json.type('key', { - path: '$' - }), - [null] + assert.equal( + await client.json.type('key'), + null ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/json/lib/commands/index.ts b/packages/json/lib/commands/index.ts index 66c0f5efe9f..2724ff2565c 100644 --- a/packages/json/lib/commands/index.ts +++ b/packages/json/lib/commands/index.ts @@ -1,16 +1,17 @@ +import { BlobStringReply, NullReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; import ARRAPPEND from './ARRAPPEND'; import ARRINDEX from './ARRINDEX'; import ARRINSERT from './ARRINSERT'; import ARRLEN from './ARRLEN'; -// import ARRPOP from './ARRPOP'; +import ARRPOP from './ARRPOP'; import ARRTRIM from './ARRTRIM'; import CLEAR from './CLEAR'; import DEBUG_MEMORY from './DEBUG_MEMORY'; import DEL from './DEL'; import FORGET from './FORGET'; -// import GET from './GET'; +import GET from './GET'; import MERGE from './MERGE'; -// import MGET from './MGET'; +import MGET from './MGET'; import MSET from './MSET'; import NUMINCRBY from './NUMINCRBY'; import NUMMULTBY from './NUMMULTBY'; @@ -22,6 +23,7 @@ import STRAPPEND from './STRAPPEND'; import STRLEN from './STRLEN'; import TOGGLE from './TOGGLE'; import TYPE from './TYPE'; +import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { ARRAPPEND, @@ -32,8 +34,8 @@ export default { arrInsert: ARRINSERT, ARRLEN, arrLen: ARRLEN, - // ARRPOP, - // arrPop: ARRPOP, + ARRPOP, + arrPop: ARRPOP, ARRTRIM, arrTrim: ARRTRIM, CLEAR, @@ -44,12 +46,12 @@ export default { del: DEL, FORGET, forget: FORGET, - // GET, - // get: GET, + GET, + get: GET, MERGE, merge: MERGE, - // MGET, - // mGet: MGET, + MGET, + mGet: MGET, MSET, mSet: MSET, NUMINCRBY, @@ -80,29 +82,19 @@ export default { type: TYPE }; -// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RedisJSONArray extends Array { } -interface RedisJSONObject { +export type RedisJSON = null | boolean | number | string | Date | Array | { [key: string]: RedisJSON; [key: number]: RedisJSON; -} -export type RedisJSON = null | boolean | number | string | Date | RedisJSONArray | RedisJSONObject; +}; export function transformRedisJsonArgument(json: RedisJSON): string { return JSON.stringify(json); } -export function transformRedisJsonReply(json: string): RedisJSON { - return JSON.parse(json); -} - -export function transformRedisJsonNullReply(json: string | null): RedisJSON | null { - if (json === null) return null; - - return transformRedisJsonReply(json); +export function transformRedisJsonReply(json: BlobStringReply): RedisJSON { + return JSON.parse((json as unknown as UnwrapReply).toString()); } -export function transformNumbersReply(reply: string): number | Array { - return JSON.parse(reply); +export function transformRedisJsonNullReply(json: NullReply | BlobStringReply): NullReply | RedisJSON { + return isNullReply(json) ? json : transformRedisJsonReply(json); } From 9f511f4171cde0c43cd40e9bd7a21136db9ce53a Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 18:27:08 -0400 Subject: [PATCH 218/325] npm update --- package-lock.json | 4668 +++++----------------------------- package.json | 12 +- packages/client/package.json | 2 +- packages/redis/package.json | 6 +- 4 files changed, 688 insertions(+), 4000 deletions(-) diff --git a/package-lock.json b/package-lock.json index eceb032d14c..16520dc8c6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,36 @@ { - "name": "redis", - "version": "4.6.7", + "name": "redis-monorepo", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "redis", - "version": "4.6.7", - "license": "MIT", + "name": "redis-monorepo", "workspaces": [ "./packages/*" ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.5.8", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.3", - "@redis/time-series": "1.0.4" - }, "devDependencies": { - "@tsconfig/node14": "^1.0.3", - "gh-pages": "^5.0.0", - "release-it": "^15.6.0", - "typescript": "^4.9.5" + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@tsconfig/node16": "^16.1.1", + "@types/mocha": "^10.0.1", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", + "gh-pages": "^6.0.0", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "source-map-support": "^0.5.21", + "ts-node": "^10.9.1", + "typedoc": "^0.25.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/@ampproject/remapping": { @@ -40,12 +47,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" @@ -101,35 +109,56 @@ "node": ">=0.8.0" } }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz", + "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.22.15", + "@babel/helpers": "^7.22.15", + "@babel/parser": "^7.22.15", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -141,21 +170,21 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", + "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.22.15", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -165,14 +194,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -180,13 +209,13 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "yallist": "^3.0.2" + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { @@ -224,31 +253,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz", + "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -270,9 +296,9 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -291,45 +317,45 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz", + "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", + "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", + "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -386,10 +412,31 @@ "node": ">=0.8.0" } }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.15.tgz", + "integrity": "sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -399,33 +446,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz", + "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -443,13 +490,13 @@ } }, "node_modules/@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz", + "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.15", "to-fast-properties": "^2.0.0" }, "engines": { @@ -494,9 +541,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", - "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -526,22 +573,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true, "peer": true, "engines": { @@ -549,9 +584,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "peer": true, "dependencies": { @@ -609,6 +644,19 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -733,30 +781,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@ljharb/through": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.9.tgz", - "integrity": "sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -792,217 +825,6 @@ "node": ">= 8" } }, - "node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", - "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", - "dev": true, - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", - "dev": true, - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "17.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", - "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", - "dev": true, - "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", - "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.2.3", - "deprecation": "^2.3.1" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", - "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", - "dev": true, - "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "dev": true, - "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request/node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", - "dev": true, - "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true - }, - "node_modules/@octokit/types": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", - "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^17.2.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/npm-conf": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-1.0.5.tgz", - "integrity": "sha512-hD8ml183638O3R6/Txrh0L8VzGOrFXgRtRDG4qQC4tONdZ5Z1M+tlUUDUvrjYdmK6G+JTBTeaCLMna11cXzi8A==", - "dev": true, - "dependencies": { - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@redis/bloom": { "resolved": "packages/bloom", "link": true @@ -1031,18 +853,6 @@ "resolved": "packages/time-series", "link": true }, - "node_modules/@sindresorhus/is": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", - "integrity": "sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -1087,27 +897,6 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1121,21 +910,15 @@ "dev": true }, "node_modules/@tsconfig/node14": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-14.1.0.tgz", - "integrity": "sha512-VmsCG04YR58ciHBeJKBDNMWWfYbyP8FekWVuTlpstaUPlat1D0x/tXzkWP7yCMU0eSz9V4OZU0LBWTFJ3xZf6w==", - "dev": true - }, - "node_modules/@tsconfig/node16": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "node_modules/@tsconfig/node16": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-16.1.1.tgz", + "integrity": "sha512-+pio93ejHN4nINX4pXqfnR/fPLRtJBaT4ORaa5RH0Oc1zoYmo2B2koG+M328CQhHKn1Wj6FcOxCDFXAot9NhvA==", "dev": true }, "node_modules/@types/json-schema": { @@ -1151,15 +934,16 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.2.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", - "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==", - "dev": true + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", + "dev": true, + "peer": true }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", "dev": true }, "node_modules/@types/sinon": { @@ -1193,15 +977,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", - "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", + "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/type-utils": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/type-utils": "6.6.0", + "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1226,56 +1011,24 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@typescript-eslint/parser": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", + "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" + "node": "^16.0.0 || >=18.0.0" }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" @@ -1287,13 +1040,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", + "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1304,13 +1057,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", - "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", + "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/utils": "6.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1331,9 +1084,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", + "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1344,13 +1097,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", + "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/visitor-keys": "6.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1370,82 +1123,19 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", + "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.6.0", + "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/typescript-estree": "6.6.0", + "semver": "^7.5.4" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1458,47 +1148,14 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", + "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.6.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1509,9 +1166,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1539,18 +1196,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1581,56 +1226,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "dev": true - }, - "node_modules/ansi-align/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -1640,33 +1235,6 @@ "node": ">=6" } }, - "node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", - "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.0.tgz", - "integrity": "sha512-JaPw5U9ixP0XcpUbQoVSbxSDcK/K4nww20C3kjm9yE6cDRRhptU28AH60VWf9ltXmCrIfIbtt9J+2OUk2Uqiaw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "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", @@ -1740,19 +1308,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -1771,37 +1326,6 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.map": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", - "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -1814,41 +1338,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1858,75 +1347,6 @@ "node": ">=8" } }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/boxen": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.1.tgz", - "integrity": "sha512-8k2eH6SRAK00NDl1iX5q17RJ8rfl53TajdYxE3ssMLehbg487dEVgsad4pIsZb/QqBgYWIl6JOauMTLGX2Kpkw==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1956,9 +1376,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "dev": true, "funding": [ { @@ -1975,10 +1395,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" }, "bin": { "browserslist": "cli.js" @@ -1993,57 +1413,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.8", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.8.tgz", - "integrity": "sha512-IDVO5MJ4LItE6HKFQTqT2ocAQsisOoCTUDu1ddCmnhyiwFQjXNPp4081Xj23N4tO+AFEFNzGuNEf/c8Gwwt15A==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "^4.0.1", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.2", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -2070,21 +1439,18 @@ } }, "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001457", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz", - "integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==", + "version": "1.0.30001527", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001527.tgz", + "integrity": "sha512-YkJi7RwPgWtXVSgK4lG9AHH57nSzvvOp9MesgXmw4Q7n0C3H04L0foHqfxcmSAm5AcWb8dW9AYj2tR7/5GnddQ==", "dev": true, "funding": [ { @@ -2102,9 +1468,9 @@ ] }, "node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -2156,21 +1522,6 @@ "node": ">= 6" } }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2180,142 +1531,15 @@ "node": ">=6" } }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", - "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/cliui/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/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==", - "dev": true - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/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==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" + "wrap-ansi": "^7.0.0" } }, "node_modules/cluster-key-slot": { @@ -2371,30 +1595,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2463,85 +1663,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/degenerator": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", - "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.8" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -2577,9 +1698,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz", - "integrity": "sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==", + "version": "1.4.508", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz", + "integrity": "sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==", "dev": true }, "node_modules/email-addresses": { @@ -2594,119 +1715,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", - "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.4", - "is-array-buffer": "^3.0.1", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2734,103 +1742,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "node_modules/eslint": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -2879,6 +1802,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2890,67 +1814,11 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2958,88 +1826,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -3084,20 +1870,12 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -3110,6 +1888,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -3124,43 +1903,6 @@ "node": ">=0.10.0" } }, - "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3184,6 +1926,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3301,17 +2055,18 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "dev": true, "peer": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.7", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { @@ -3388,76 +2143,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", - "dev": true, - "dependencies": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ftp/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/ftp/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ftp/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -3484,20 +2169,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3507,60 +2178,6 @@ "node": ">=8.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", - "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/get-uri/node_modules/data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/gh-pages": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.0.0.tgz", @@ -3632,16 +2249,16 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "peer": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/globals": { @@ -3660,21 +2277,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -3692,60 +2294,28 @@ "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.0.tgz", - "integrity": "sha512-WTcaQ963xV97MN3x0/CbAriXFZcXCfgxVp91I+Ze6pawQOa7SgzwSx2zIJJsX+kTajMnVs0xcFD1TxZKFqhdnQ==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "peer": true + "dev": true }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/hasha": { @@ -3788,109 +2358,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -3951,118 +2418,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/inquirer": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.0.tgz", - "integrity": "sha512-WWERbVqjsTXjXub1ZW0ZHDit1dyHqy0T9XIkky9TnmKAPrjU9Jkd59nZPK0dUuM3s73GZAZu2Jo4iFU3XSPVLA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^6.0.0", - "chalk": "^5.2.0", - "cli-cursor": "^4.0.0", - "cli-width": "^4.0.0", - "external-editor": "^3.0.3", - "figures": "^5.0.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^6.1.2", - "run-async": "^2.4.0", - "rxjs": "^7.8.0", - "string-width": "^5.1.2", - "strip-ansi": "^7.0.1", - "through": "^2.3.6", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4075,88 +2430,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4227,55 +2500,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4352,9 +2576,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4391,28 +2615,7 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { + "node_modules/istanbul-lib-report/node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", @@ -4427,33 +2630,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -4511,6 +2687,13 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "peer": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4562,29 +2745,15 @@ "dev": true }, "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", "dev": true, + "peer": true, "dependencies": { "json-buffer": "3.0.1" } }, - "node_modules/latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", - "dev": true, - "dependencies": { - "package-json": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4650,12 +2819,12 @@ } }, "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/lunr": { @@ -4664,18 +2833,6 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, - "node_modules/macos-release": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.1.0.tgz", - "integrity": "sha512-/M/R0gCDgM+Cv1IuBG1XGdfTFnMEG6PZeT+KGWHO/OG+imqmaD9CH5vHBTycEM3+Kc4uG2Il+tFAuUWLqQOeUA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4692,9 +2849,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4792,459 +2949,125 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/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==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/mocha/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==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=10" } }, - "node_modules/mocha/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/mocha/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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/nise": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "type-detect": "4.0.8" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "process-on-spawn": "^1.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/mocha/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", - "dev": true, - "dependencies": { - "type-fest": "^2.5.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/new-github-release-url/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", @@ -5282,10 +3105,10 @@ "node": ">=8.9" } }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", @@ -5293,10 +3116,10 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", @@ -5354,47 +3177,52 @@ "node": ">=8" } }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "node_modules/nyc/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==", "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/ora": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz", - "integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==", + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { - "chalk": "^5.0.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.6.1", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.1.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "strip-ansi": "^7.0.1", - "wcwidth": "^1.0.1" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "engines": { "node": ">=8" } }, - "node_modules/os-name": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", - "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { "camelcase": "^5.0.0", @@ -5423,18 +3251,18 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "peer": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -5491,40 +3319,6 @@ "node": ">=6" } }, - "node_modules/pac-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", - "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/pac-resolver": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", - "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", - "dev": true, - "dependencies": { - "degenerator": "^3.0.2", - "ip": "^1.1.5", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/package-hash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", @@ -5540,57 +3334,6 @@ "node": ">=8" } }, - "node_modules/package-json": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.0.tgz", - "integrity": "sha512-hySwcV8RAWeAfPsXb9/HGSPn8lwDnv6fabH+obUZKX169QknRkRhPxd1yMubpKDskLFATkl3jHpNtVtDPFA0Wg==", - "dev": true, - "dependencies": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5740,316 +3483,103 @@ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", - "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/registry-auth-token": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.1.tgz", - "integrity": "sha512-UfxVOj8seK1yaIOiieV4FIP01vfBDLsY0H9sQzi9EbbUdJiuuBjJgLa1DpImXMNPnVkBD4eVxTEXcrZA6kfpJA==", - "dev": true, - "dependencies": { - "@pnpm/npm-conf": "^1.0.4" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/release-it": { - "version": "15.10.3", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-15.10.3.tgz", - "integrity": "sha512-OSdHOg76gwkpLbSLBK09GZQj5XWXwBP+S6v//rSoQKkjqklaCLK04Gl5NkTwNrQOHHiihs4ToesDNh2+w55k3w==", - "dev": true, - "dependencies": { - "@iarna/toml": "2.2.5", - "@octokit/rest": "19.0.7", - "async-retry": "1.3.3", - "chalk": "5.2.0", - "cosmiconfig": "8.1.3", - "execa": "7.1.1", - "git-url-parse": "13.1.0", - "globby": "13.1.4", - "got": "12.6.0", - "inquirer": "9.2.0", - "is-ci": "3.0.1", - "issue-parser": "6.0.0", - "lodash": "4.17.21", - "mime-types": "2.1.35", - "new-github-release-url": "2.0.0", - "node-fetch": "3.3.1", - "open": "9.1.0", - "ora": "6.3.0", - "os-name": "5.1.0", - "promise.allsettled": "1.0.6", - "proxy-agent": "5.0.0", - "semver": "7.5.0", - "shelljs": "0.8.5", - "update-notifier": "6.0.2", - "url-join": "5.0.0", - "wildcard-match": "5.1.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "release-it": "bin/release-it.js" - }, - "engines": { - "node": ">=14.9" - } - }, - "node_modules/release-it/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/release-it/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/release-it/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "fromentries": "^1.2.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/release-it/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, + "peer": true, "engines": { - "node": ">=12" + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.10.0" } }, - "node_modules/release-it/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/redis": { + "resolved": "packages/redis", + "link": true }, "node_modules/release-zalgo": { "version": "1.0.0", @@ -6078,29 +3608,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -6111,70 +3618,6 @@ "node": ">=4" } }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/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==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6200,119 +3643,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/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==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6336,15 +3666,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6366,28 +3687,13 @@ ] }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -6407,22 +3713,7 @@ "node": ">=10" } }, - "node_modules/semver-diff/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-diff/node_modules/yallist": { + "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", @@ -6465,9 +3756,9 @@ } }, "node_modules/shiki": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", - "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz", + "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -6506,62 +3797,18 @@ "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", "dev": true, "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" + "node": ">=0.3.1" } }, - "node_modules/socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6604,51 +3851,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", - "dev": true, - "dependencies": { - "bl": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6660,38 +3862,7 @@ "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, "node_modules/strip-ansi": { @@ -6716,12 +3887,15 @@ } }, "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-outer": { @@ -6746,15 +3920,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/test-exclude": { @@ -6775,18 +3949,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", "dev": true, "peer": true }, @@ -6811,21 +3973,6 @@ "node": ">=8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -6902,10 +4049,10 @@ } } }, - "node_modules/ts-node/node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "node_modules/ts-node/node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "node_modules/ts-node/node_modules/diff": { @@ -6917,33 +4064,6 @@ "node": ">=0.3.1" } }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6967,9 +4087,9 @@ } }, "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==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "peer": true, "engines": { @@ -6979,20 +4099,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -7003,24 +4109,24 @@ } }, "node_modules/typedoc": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", + "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", - "minimatch": "^9.0.0", + "minimatch": "^9.0.3", "shiki": "^0.14.1" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { - "node": ">= 14.14" + "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -7033,9 +4139,9 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -7048,9 +4154,9 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7066,25 +4172,7 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">= 10.0.0" } }, "node_modules/update-browserslist-db": { @@ -7117,67 +4205,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/update-notifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", - "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", - "dev": true, - "dependencies": { - "boxen": "^7.0.0", - "chalk": "^5.0.1", - "configstore": "^6.0.0", - "has-yarn": "^3.0.0", - "import-lazy": "^4.0.0", - "is-ci": "^3.0.1", - "is-installed-globally": "^0.4.0", - "is-npm": "^6.0.0", - "is-yarn-global": "^0.4.0", - "latest-version": "^7.0.0", - "pupa": "^3.1.0", - "semver": "^7.3.7", - "semver-diff": "^4.0.0", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/update-notifier/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7205,190 +4232,36 @@ }, "node_modules/vscode-oniguruma": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "dev": true, - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wildcard-match": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", - "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", - "dev": true - }, - "node_modules/windows-release": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.1.0.tgz", - "integrity": "sha512-CddHecz5dt0ngTjGPP1uYr9Tjl4qq5rEKNk8UGb8XCdngNXI+GRYvqelD055FdiUgqODZz3R/5oZWYldPtXQpA==", - "dev": true, - "dependencies": { - "execa": "^5.1.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/windows-release/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/windows-release/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/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==", - "dev": true, - "engines": { - "node": ">=6" - } + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true }, - "node_modules/windows-release/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true }, - "node_modules/windows-release/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=6" + "bin": { + "node-which": "bin/node-which" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/windows-release/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true }, "node_modules/workerpool": { "version": "6.2.1", @@ -7397,9 +4270,9 @@ "dev": true }, "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -7407,7 +4280,7 @@ "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -7440,46 +4313,28 @@ "node": ">=10" } }, - "node_modules/xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/yargs-parser": { @@ -7556,36 +4411,15 @@ "version": "1.2.0", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "packages/bloom/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" + "@redis/client": "*" } }, "packages/client": { "name": "@redis/client", - "version": "1.5.8", + "version": "2.0.0-next.2", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -7593,19 +4427,8 @@ }, "devDependencies": { "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "@types/sinon": "^10.0.15", - "@types/yallist": "^4.0.1", - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "sinon": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@types/sinon": "^10.0.16", + "sinon": "^15.2.0" }, "engines": { "node": ">=16" @@ -7616,31 +4439,10 @@ "version": "1.1.0", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "packages/graph/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" + "@redis/client": "*" } }, "packages/json": { @@ -7648,105 +4450,61 @@ "version": "1.0.4", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { "@redis/client": "*" } }, - "packages/json/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "packages/redis": { + "version": "4.6.6", + "license": "MIT", + "dependencies": { + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.9", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.3", + "@redis/time-series": "1.0.5" + } + }, + "packages/redis/node_modules/@redis/client": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.9.tgz", + "integrity": "sha512-SffgN+P1zdWJWSXBvJeynvEnmnZrYmtKSRW00xl8pOPFOMJjxRR9u0frSxJpPR6Y4V+k54blJjGW7FgxbTI7bQ==", + "dependencies": { + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" }, "engines": { - "node": ">=12.20" + "node": ">=14" } }, + "packages/redis/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "packages/search": { "name": "@redis/search", "version": "1.1.3", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "packages/search/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" + "@redis/client": "*" } }, "packages/test-utils": { "name": "@redis/test-utils", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", "@types/yargs": "^17.0.24", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typescript": "^5.0.4", "yargs": "^17.7.2" }, "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "packages/test-utils/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@redis/client": "*" } }, "packages/test-utils/node_modules/cliui": { @@ -7763,77 +4521,6 @@ "node": ">=12" } }, - "packages/test-utils/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==", - "dev": true - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "packages/test-utils/node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } - }, - "packages/test-utils/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "packages/test-utils/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "packages/test-utils/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -7852,20 +4539,21 @@ "node": ">=12" } }, + "packages/test-utils/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "packages/time-series": { "name": "@redis/time-series", "version": "1.0.5", "license": "MIT", "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@redis/test-utils": "*", - "@types/node": "^20.2.3", - "nyc": "^15.1.0", - "release-it": "^15.10.3", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.24.7", - "typescript": "^5.0.4" + "@redis/test-utils": "*" }, "peerDependencies": { "@redis/client": "*" diff --git a/package.json b/package.json index 13a7781197f..92e005a102d 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,16 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node16": "^1.0.4", + "@tsconfig/node16": "^16.1.1", "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^5.60.1", - "@typescript-eslint/parser": "^5.60.1", - "gh-pages": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", + "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.24.8", - "typescript": "^5.1.3" + "typedoc": "^0.25.1", + "typescript": "^5.2.2" } } diff --git a/packages/client/package.json b/packages/client/package.json index 8300468496b..a79e51a2652 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,7 +17,7 @@ }, "devDependencies": { "@redis/test-utils": "*", - "@types/sinon": "^10.0.15", + "@types/sinon": "^10.0.16", "sinon": "^15.2.0" }, "engines": { diff --git a/packages/redis/package.json b/packages/redis/package.json index 67abfcaed20..e60de2b3028 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,11 +10,11 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.7", + "@redis/client": "1.5.9", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", - "@redis/search": "1.1.2", - "@redis/time-series": "1.0.4" + "@redis/search": "1.1.3", + "@redis/time-series": "1.0.5" }, "repository": { "type": "git", From 7f5c309bc9be38e25460ebaf1035834fab8722f0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Sep 2023 18:34:48 -0400 Subject: [PATCH 219/325] fix JSON spec describe title --- packages/json/lib/commands/ARRAPPEND.spec.ts | 2 +- packages/json/lib/commands/MERGE.spec.ts | 2 +- packages/json/lib/commands/MGET.spec.ts | 2 +- packages/json/lib/commands/MSET.spec.ts | 2 +- packages/json/lib/commands/TYPE.spec.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts index c5bc636f951..8261a125f00 100644 --- a/packages/json/lib/commands/ARRAPPEND.spec.ts +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRAPPEND from './ARRAPPEND'; -describe('ARRAPPEND', () => { +describe('JSON.ARRAPPEND', () => { describe('transformArguments', () => { it('single element', () => { assert.deepEqual( diff --git a/packages/json/lib/commands/MERGE.spec.ts b/packages/json/lib/commands/MERGE.spec.ts index a2f880176f5..c4d37e32c72 100644 --- a/packages/json/lib/commands/MERGE.spec.ts +++ b/packages/json/lib/commands/MERGE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import MERGE from './MERGE'; -describe('MERGE', () => { +describe('JSON.MERGE', () => { it('transformArguments', () => { assert.deepEqual( MERGE.transformArguments('key', '$', 'value'), diff --git a/packages/json/lib/commands/MGET.spec.ts b/packages/json/lib/commands/MGET.spec.ts index 79d0657bf93..49845d20eda 100644 --- a/packages/json/lib/commands/MGET.spec.ts +++ b/packages/json/lib/commands/MGET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import MGET from './MGET'; -describe('MGET', () => { +describe('JSON.MGET', () => { it('transformArguments', () => { assert.deepEqual( MGET.transformArguments(['1', '2'], '$'), diff --git a/packages/json/lib/commands/MSET.spec.ts b/packages/json/lib/commands/MSET.spec.ts index de2afa571b1..88803c56a83 100644 --- a/packages/json/lib/commands/MSET.spec.ts +++ b/packages/json/lib/commands/MSET.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import MSET from './MSET'; -describe('MSET', () => { +describe('JSON.MSET', () => { it('transformArguments', () => { assert.deepEqual( MSET.transformArguments([{ diff --git a/packages/json/lib/commands/TYPE.spec.ts b/packages/json/lib/commands/TYPE.spec.ts index b3124ceb31b..e0edf9c825e 100644 --- a/packages/json/lib/commands/TYPE.spec.ts +++ b/packages/json/lib/commands/TYPE.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import TYPE from './TYPE'; -describe('TYPE', () => { +describe('JSON.TYPE', () => { describe('transformArguments', () => { it('simple', () => { assert.deepEqual( From 0e8a0b9dd01ff3b1b4e9a41ec89c72a227c7977c Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 12 Sep 2023 16:00:50 -0400 Subject: [PATCH 220/325] remove node16 from tests matrix --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 883ad8e25e9..ee937625c3b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: ['16', '18', '20'] + node-version: ['18', '20'] redis-version: ['5', '6.0', '6.2', '7.0', '7.2-rc'] steps: - uses: actions/checkout@v3 From 17cf320651cd7f6e23d7b6be7aecbe46837bb1ad Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 12 Sep 2023 16:02:12 -0400 Subject: [PATCH 221/325] CLUSERT [INFO|NODES|REPLICAS] --- .../client/lib/commands/CLUSTER_INFO.spec.ts | 61 ++----- packages/client/lib/commands/CLUSTER_INFO.ts | 55 +------ .../client/lib/commands/CLUSTER_NODES.spec.ts | 155 ++---------------- packages/client/lib/commands/CLUSTER_NODES.ts | 113 +------------ .../lib/commands/CLUSTER_REPLICAS.spec.ts | 23 ++- .../client/lib/commands/CLUSTER_REPLICAS.ts | 13 +- packages/client/lib/commands/index.ts | 18 +- 7 files changed, 80 insertions(+), 358 deletions(-) diff --git a/packages/client/lib/commands/CLUSTER_INFO.spec.ts b/packages/client/lib/commands/CLUSTER_INFO.spec.ts index 69d5c4a8c56..53c5b910920 100644 --- a/packages/client/lib/commands/CLUSTER_INFO.spec.ts +++ b/packages/client/lib/commands/CLUSTER_INFO.spec.ts @@ -3,53 +3,18 @@ import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './CLUSTER_INFO'; describe('CLUSTER INFO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'INFO'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + transformArguments(), + ['CLUSTER', 'INFO'] + ); + }); - it('transformReply', () => { - assert.deepEqual( - transformReply([ - 'cluster_state:ok', - 'cluster_slots_assigned:16384', - 'cluster_slots_ok:16384', - 'cluster_slots_pfail:0', - 'cluster_slots_fail:0', - 'cluster_known_nodes:6', - 'cluster_size:3', - 'cluster_current_epoch:6', - 'cluster_my_epoch:2', - 'cluster_stats_messages_sent:1483972', - 'cluster_stats_messages_received:1483968' - ].join('\r\n')), - { - state: 'ok', - slots: { - assigned: 16384, - ok: 16384, - pfail: 0, - fail: 0 - }, - knownNodes: 6, - size: 3, - currentEpoch: 6, - myEpoch: 2, - stats: { - messagesSent: 1483972, - messagesReceived: 1483968 - } - } - ); - }); - - testUtils.testWithCluster('clusterNode.clusterInfo', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.notEqual( - await client.clusterInfo(), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterInfo', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterInfo(), + 'string' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_INFO.ts b/packages/client/lib/commands/CLUSTER_INFO.ts index 634515f927c..c541de17294 100644 --- a/packages/client/lib/commands/CLUSTER_INFO.ts +++ b/packages/client/lib/commands/CLUSTER_INFO.ts @@ -1,47 +1,10 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'INFO']; -} - -interface ClusterInfoReply { - state: string; - slots: { - assigned: number; - ok: number; - pfail: number; - fail: number; - }; - knownNodes: number; - size: number; - currentEpoch: number; - myEpoch: number; - stats: { - messagesSent: number; - messagesReceived: number; - }; -} - -export function transformReply(reply: string): ClusterInfoReply { - const lines = reply.split('\r\n'); +import { VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; - return { - state: extractLineValue(lines[0]), - slots: { - assigned: Number(extractLineValue(lines[1])), - ok: Number(extractLineValue(lines[2])), - pfail: Number(extractLineValue(lines[3])), - fail: Number(extractLineValue(lines[4])) - }, - knownNodes: Number(extractLineValue(lines[5])), - size: Number(extractLineValue(lines[6])), - currentEpoch: Number(extractLineValue(lines[7])), - myEpoch: Number(extractLineValue(lines[8])), - stats: { - messagesSent: Number(extractLineValue(lines[9])), - messagesReceived: Number(extractLineValue(lines[10])) - } - }; -} - -export function extractLineValue(line: string): string { - return line.substring(line.indexOf(':') + 1); -} +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'INFO']; + }, + transformReply: undefined as unknown as () => VerbatimStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_NODES.spec.ts b/packages/client/lib/commands/CLUSTER_NODES.spec.ts index 5c6cb74d6cb..5c25ab209b2 100644 --- a/packages/client/lib/commands/CLUSTER_NODES.spec.ts +++ b/packages/client/lib/commands/CLUSTER_NODES.spec.ts @@ -1,145 +1,20 @@ import { strict as assert } from 'assert'; -import { RedisClusterNodeLinkStates, transformArguments, transformReply } from './CLUSTER_NODES'; +import testUtils, { GLOBAL } from '../test-utils'; +import CLUSTER_NODES from './CLUSTER_NODES'; describe('CLUSTER NODES', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'NODES'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_NODES.transformArguments(), + ['CLUSTER', 'NODES'] + ); + }); - describe('transformReply', () => { - it('simple', () => { - assert.deepEqual( - transformReply([ - 'master 127.0.0.1:30001@31001 myself,master - 0 0 1 connected 0-16384', - 'slave 127.0.0.1:30002@31002 slave master 0 0 1 connected', - '' - ].join('\n')), - [{ - id: 'master', - address: '127.0.0.1:30001@31001', - host: '127.0.0.1', - port: 30001, - cport: 31001, - flags: ['myself', 'master'], - pingSent: 0, - pongRecv: 0, - configEpoch: 1, - linkState: RedisClusterNodeLinkStates.CONNECTED, - slots: [{ - from: 0, - to: 16384 - }], - replicas: [{ - id: 'slave', - address: '127.0.0.1:30002@31002', - host: '127.0.0.1', - port: 30002, - cport: 31002, - flags: ['slave'], - pingSent: 0, - pongRecv: 0, - configEpoch: 1, - linkState: RedisClusterNodeLinkStates.CONNECTED - }] - }] - ); - }); - - it('should support addresses without cport', () => { - assert.deepEqual( - transformReply( - 'id 127.0.0.1:30001 master - 0 0 0 connected 0-16384\n' - ), - [{ - id: 'id', - address: '127.0.0.1:30001', - host: '127.0.0.1', - port: 30001, - cport: null, - flags: ['master'], - pingSent: 0, - pongRecv: 0, - configEpoch: 0, - linkState: RedisClusterNodeLinkStates.CONNECTED, - slots: [{ - from: 0, - to: 16384 - }], - replicas: [] - }] - ); - }); - - it('should support ipv6 addresses', () => { - assert.deepEqual( - transformReply( - 'id 2a02:6b8:c21:330d:0:1589:ebbe:b1a0:6379@16379 master - 0 0 0 connected 0-549\n' - ), - [{ - id: 'id', - address: '2a02:6b8:c21:330d:0:1589:ebbe:b1a0:6379@16379', - host: '2a02:6b8:c21:330d:0:1589:ebbe:b1a0', - port: 6379, - cport: 16379, - flags: ['master'], - pingSent: 0, - pongRecv: 0, - configEpoch: 0, - linkState: RedisClusterNodeLinkStates.CONNECTED, - slots: [{ - from: 0, - to: 549 - }], - replicas: [] - }] - ); - }); - - it.skip('with importing slots', () => { - assert.deepEqual( - transformReply( - 'id 127.0.0.1:30001@31001 master - 0 0 0 connected 0-<-16384\n' - ), - [{ - id: 'id', - address: '127.0.0.1:30001@31001', - host: '127.0.0.1', - port: 30001, - cport: 31001, - flags: ['master'], - pingSent: 0, - pongRecv: 0, - configEpoch: 0, - linkState: RedisClusterNodeLinkStates.CONNECTED, - slots: [], // TODO - replicas: [] - }] - ); - }); - - it.skip('with migrating slots', () => { - assert.deepEqual( - transformReply( - 'id 127.0.0.1:30001@31001 master - 0 0 0 connected 0->-16384\n' - ), - [{ - id: 'id', - address: '127.0.0.1:30001@31001', - host: '127.0.0.1', - port: 30001, - cport: 31001, - flags: ['master'], - pingSent: 0, - pongRecv: 0, - configEpoch: 0, - linkState: RedisClusterNodeLinkStates.CONNECTED, - slots: [], // TODO - replicas: [] - }] - ); - }); - }); + testUtils.testWithCluster('clusterNode.clusterNodes', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterNodes(), + 'string' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_NODES.ts b/packages/client/lib/commands/CLUSTER_NODES.ts index 7c433da5f12..9166ce52f08 100644 --- a/packages/client/lib/commands/CLUSTER_NODES.ts +++ b/packages/client/lib/commands/CLUSTER_NODES.ts @@ -1,105 +1,10 @@ -export function transformArguments(): Array { - return ['CLUSTER', 'NODES']; -} - -export enum RedisClusterNodeLinkStates { - CONNECTED = 'connected', - DISCONNECTED = 'disconnected' -} - -interface RedisClusterNodeAddress { - host: string; - port: number; - cport: number | null; -} - -export interface RedisClusterReplicaNode extends RedisClusterNodeAddress { - id: string; - address: string; - flags: Array; - pingSent: number; - pongRecv: number; - configEpoch: number; - linkState: RedisClusterNodeLinkStates; -} - -export interface RedisClusterMasterNode extends RedisClusterReplicaNode { - slots: Array<{ - from: number; - to: number; - }>; - replicas: Array; -} - -export function transformReply(reply: string): Array { - const lines = reply.split('\n'); - lines.pop(); // last line is empty - - const mastersMap = new Map(), - replicasMap = new Map>(); +import { VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; - for (const line of lines) { - const [id, address, flags, masterId, pingSent, pongRecv, configEpoch, linkState, ...slots] = line.split(' '), - node = { - id, - address, - ...transformNodeAddress(address), - flags: flags.split(','), - pingSent: Number(pingSent), - pongRecv: Number(pongRecv), - configEpoch: Number(configEpoch), - linkState: (linkState as RedisClusterNodeLinkStates) - }; - - if (masterId === '-') { - let replicas = replicasMap.get(id); - if (!replicas) { - replicas = []; - replicasMap.set(id, replicas); - } - - mastersMap.set(id, { - ...node, - slots: slots.map(slot => { - // TODO: importing & exporting (https://redis.io/commands/cluster-nodes#special-slot-entries) - const [fromString, toString] = slot.split('-', 2), - from = Number(fromString); - return { - from, - to: toString ? Number(toString) : from - }; - }), - replicas - }); - } else { - const replicas = replicasMap.get(masterId); - if (!replicas) { - replicasMap.set(masterId, [node]); - } else { - replicas.push(node); - } - } - } - - return [...mastersMap.values()]; -} - -function transformNodeAddress(address: string): RedisClusterNodeAddress { - const indexOfColon = address.lastIndexOf(':'), - indexOfAt = address.indexOf('@', indexOfColon), - host = address.substring(0, indexOfColon); - - if (indexOfAt === -1) { - return { - host, - port: Number(address.substring(indexOfColon + 1)), - cport: null - }; - } - - return { - host: address.substring(0, indexOfColon), - port: Number(address.substring(indexOfColon + 1, indexOfAt)), - cport: Number(address.substring(indexOfAt + 1)) - }; -} +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { + return ['CLUSTER', 'NODES']; + }, + transformReply: undefined as unknown as () => VerbatimStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts index 6c902dc0d82..18b9fed5e47 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts @@ -1,11 +1,20 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './CLUSTER_REPLICAS'; +import testUtils, { GLOBAL } from '../test-utils'; +import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; describe('CLUSTER REPLICAS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('0'), - ['CLUSTER', 'REPLICAS', '0'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_REPLICAS.transformArguments('0'), + ['CLUSTER', 'REPLICAS', '0'] + ); + }); + + testUtils.testWithCluster('clusterNode.clusterReplicas', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterReplicas(cluster.masters[0].id), + 'string' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.ts index a4130125fbf..7cb0eaae437 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.ts @@ -1,5 +1,10 @@ -export function transformArguments(nodeId: string): Array { - return ['CLUSTER', 'REPLICAS', nodeId]; -} +import { RedisArgument, VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export { transformReply } from './CLUSTER_NODES'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(nodeId: RedisArgument) { + return ['CLUSTER', 'REPLICAS', nodeId]; + }, + transformReply: undefined as unknown as () => VerbatimStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index d8eb66b66af..ab3711ab3a7 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -54,13 +54,13 @@ import CLUSTER_FAILOVER from './CLUSTER_FAILOVER'; import CLUSTER_FLUSHSLOTS from './CLUSTER_FLUSHSLOTS'; import CLUSTER_FORGET from './CLUSTER_FORGET'; import CLUSTER_GETKEYSINSLOT from './CLUSTER_GETKEYSINSLOT'; -// import CLUSTER_INFO from './CLUSTER_INFO'; +import CLUSTER_INFO from './CLUSTER_INFO'; import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; import CLUSTER_LINKS from './CLUSTER_LINKS'; import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; -// import CLUSTER_NODES from './CLUSTER_NODES'; -// import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; +import CLUSTER_NODES from './CLUSTER_NODES'; +import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; import CLUSTER_RESET from './CLUSTER_RESET'; import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; @@ -437,8 +437,8 @@ export default { clusterForget: CLUSTER_FORGET, CLUSTER_GETKEYSINSLOT, clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT, - // CLUSTER_INFO, - // clusterInfo: CLUSTER_INFO, + CLUSTER_INFO, + clusterInfo: CLUSTER_INFO, CLUSTER_KEYSLOT, clusterKeySlot: CLUSTER_KEYSLOT, CLUSTER_LINKS, @@ -447,10 +447,10 @@ export default { clusterMeet: CLUSTER_MEET, CLUSTER_MYID, clusterMyId: CLUSTER_MYID, - // CLUSTER_NODES, - // clusterNodes: CLUSTER_NODES, - // CLUSTER_REPLICAS, - // clusterReplicas: CLUSTER_REPLICAS, + CLUSTER_NODES, + clusterNodes: CLUSTER_NODES, + CLUSTER_REPLICAS, + clusterReplicas: CLUSTER_REPLICAS, CLUSTER_REPLICATE, clusterReplicate: CLUSTER_REPLICATE, CLUSTER_RESET, From 292dc58e15f26c4ab5b85fe0e4fda80c455db028 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 12 Sep 2023 16:03:29 -0400 Subject: [PATCH 222/325] cluster v4-to-v5 --- docs/v4-to-v5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 1ad3aab8dac..4130c659395 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -180,9 +180,9 @@ Some command arguments/replies have changed to align more closely to data types - `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] - `JSON.ARRPOP`: `path` and `index` arguments moved to `{ path: string; index: number; }` [^future-proofing] - `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRAPPEND`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] -- : `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` - `TS.SYNUPDATE`: `Array>` -> `Record>` +- `CLUSTER NODES`, `CLUSTER REPLICAS`, `CLUSTER INFO`: returning the raw `VerbatimStringReply` [^enum-to-constants]: TODO From 3fa54fef584852d481eec7f788492b500283ea59 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 12:40:12 -0400 Subject: [PATCH 223/325] fix #2614 - add support for RediSearch GEOSHAPE fields --- packages/search/lib/commands/CREATE.spec.ts | 36 +++++++++++++++++++++ packages/search/lib/commands/CREATE.ts | 24 ++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 37aa06011bf..0c0b3e89a22 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -194,6 +194,42 @@ describe('FT.CREATE', () => { ); }); }); + + describe('GEOSHAPE', () => { + describe('without options', () => { + it('SCHEMA_FIELD_TYPE.GEOSHAPE', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: SCHEMA_FIELD_TYPE.GEOSHAPE + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE'] + ); + }); + + it('{ type: SCHEMA_FIELD_TYPE.GEOSHAPE }', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.GEOSHAPE + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE'] + ); + }); + }); + + it('with COORD_SYSTEM', () => { + assert.deepEqual( + CREATE.transformArguments('index', { + field: { + type: SCHEMA_FIELD_TYPE.GEOSHAPE, + COORD_SYSTEM: 'SPHERICAL' + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE', 'COORD_SYSTEM', 'SPHERICAL'] + ); + }); + }); it('with AS', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index 98a616f04ef..ea63873be45 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -7,7 +7,8 @@ export const SCHEMA_FIELD_TYPE = { NUMERIC: 'NUMERIC', GEO: 'GEO', TAG: 'TAG', - VECTOR: 'VECTOR' + VECTOR: 'VECTOR', + GEOSHAPE: 'GEOSHAPE' } as const; export type SchemaFieldType = typeof SCHEMA_FIELD_TYPE[keyof typeof SCHEMA_FIELD_TYPE]; @@ -85,6 +86,17 @@ type SchemaHNSWVectorField = SchemaVectorField; +export const SCHEMA_GEO_SHAPE_COORD_SYSTEM = { + SPHERICAL: 'SPHERICAL', + FLAT: 'FLAT' +} as const; + +export type SchemaGeoShapeFieldCoordSystem = typeof SCHEMA_GEO_SHAPE_COORD_SYSTEM[keyof typeof SCHEMA_GEO_SHAPE_COORD_SYSTEM]; + +type SchemaGeoShapeField = SchemaField; + export interface RediSearchSchema { [field: string]:( SchemaTextField | @@ -92,7 +104,8 @@ export interface RediSearchSchema { SchemaGeoField | SchemaTagField | SchemaFlatVectorField | - SchemaHNSWVectorField + SchemaHNSWVectorField | + SchemaGeoShapeField ); } @@ -191,6 +204,13 @@ export function pushSchema(args: CommandArguments, schema: RediSearchSchema) { args[lengthIndex] = (args.length - lengthIndex - 1).toString(); continue; // vector fields do not contain SORTABLE and NOINDEX options + + case SCHEMA_FIELD_TYPE.GEOSHAPE: + if (fieldOptions.COORD_SYSTEM !== undefined) { + args.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM); + } + + continue; // geo shape fields do not contain SORTABLE and NOINDEX options } if (fieldOptions.SORTABLE) { From 266d635a600a69b2e86fd006a87602c1c5541e63 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 15:03:07 -0400 Subject: [PATCH 224/325] add `node:` to node "core modules" imports --- benchmark/lib/index.js | 10 +++++----- benchmark/lib/ping/v3.js | 4 ++-- benchmark/lib/runner.js | 4 ++-- benchmark/lib/set-get-delete-string/index.js | 2 +- benchmark/lib/set-get-delete-string/v3.js | 4 ++-- packages/bloom/lib/commands/bloom/ADD.spec.ts | 2 +- .../bloom/lib/commands/bloom/CARD.spec.ts | 2 +- .../bloom/lib/commands/bloom/EXISTS.spec.ts | 2 +- .../bloom/lib/commands/bloom/INFO.spec.ts | 2 +- .../bloom/lib/commands/bloom/INSERT.spec.ts | 2 +- .../lib/commands/bloom/LOADCHUNK.spec.ts | 2 +- .../bloom/lib/commands/bloom/MADD.spec.ts | 2 +- .../bloom/lib/commands/bloom/MEXISTS.spec.ts | 2 +- .../bloom/lib/commands/bloom/RESERVE.spec.ts | 2 +- .../bloom/lib/commands/bloom/SCANDUMP.spec.ts | 2 +- .../commands/count-min-sketch/INCRBY.spec.ts | 2 +- .../commands/count-min-sketch/INFO.spec.ts | 2 +- .../count-min-sketch/INITBYDIM.spec.ts | 2 +- .../count-min-sketch/INITBYPROB.spec.ts | 2 +- .../commands/count-min-sketch/MERGE.spec.ts | 2 +- .../commands/count-min-sketch/QUERY.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/ADD.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/ADDNX.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/COUNT.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/DEL.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/EXISTS.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/INFO.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/INSERT.spec.ts | 2 +- .../lib/commands/cuckoo/INSERTNX.spec.ts | 2 +- .../lib/commands/cuckoo/LOADCHUNK.spec.ts | 2 +- .../bloom/lib/commands/cuckoo/RESERVE.spec.ts | 2 +- .../lib/commands/cuckoo/SCANDUMP.spec.ts | 2 +- .../bloom/lib/commands/t-digest/ADD.spec.ts | 2 +- .../lib/commands/t-digest/BYRANK.spec.ts | 2 +- .../lib/commands/t-digest/BYREVRANK.spec.ts | 2 +- .../bloom/lib/commands/t-digest/CDF.spec.ts | 2 +- .../lib/commands/t-digest/CREATE.spec.ts | 2 +- .../bloom/lib/commands/t-digest/INFO.spec.ts | 2 +- .../bloom/lib/commands/t-digest/MAX.spec.ts | 2 +- .../bloom/lib/commands/t-digest/MERGE.spec.ts | 2 +- .../bloom/lib/commands/t-digest/MIN.spec.ts | 2 +- .../lib/commands/t-digest/QUANTILE.spec.ts | 2 +- .../bloom/lib/commands/t-digest/RANK.spec.ts | 2 +- .../bloom/lib/commands/t-digest/RESET.spec.ts | 2 +- .../lib/commands/t-digest/REVRANK.spec.ts | 2 +- .../commands/t-digest/TRIMMED_MEAN.spec.ts | 2 +- packages/bloom/lib/commands/top-k/ADD.spec.ts | 2 +- .../bloom/lib/commands/top-k/COUNT.spec.ts | 2 +- .../bloom/lib/commands/top-k/INCRBY.spec.ts | 2 +- .../bloom/lib/commands/top-k/INFO.spec.ts | 2 +- .../bloom/lib/commands/top-k/LIST.spec.ts | 2 +- .../lib/commands/top-k/LIST_WITHCOUNT.spec.ts | 2 +- .../bloom/lib/commands/top-k/QUERY.spec.ts | 2 +- .../bloom/lib/commands/top-k/RESERVE.spec.ts | 2 +- packages/client/lib/RESP/decoder.spec.ts | 2 +- packages/client/lib/RESP/encoder.spec.ts | 2 +- packages/client/lib/client/commands-queue.ts | 2 +- packages/client/lib/client/index.spec.ts | 6 +++--- packages/client/lib/client/index.ts | 6 +++--- .../client/lib/client/legacy-mode.spec.ts | 6 +++--- packages/client/lib/client/pool.ts | 2 +- packages/client/lib/client/pub-sub.spec.ts | 2 +- packages/client/lib/client/socket.spec.ts | 4 ++-- packages/client/lib/client/socket.ts | 6 +++--- packages/client/lib/cluster/cluster-slots.ts | 4 ++-- packages/client/lib/cluster/index.spec.ts | 2 +- packages/client/lib/cluster/index.ts | 20 +++++++++---------- packages/client/lib/commands/ACL_CAT.spec.ts | 2 +- .../client/lib/commands/ACL_DELUSER.spec.ts | 2 +- .../client/lib/commands/ACL_DRYRUN.spec.ts | 2 +- .../client/lib/commands/ACL_GENPASS.spec.ts | 2 +- .../client/lib/commands/ACL_GETUSER.spec.ts | 2 +- packages/client/lib/commands/ACL_LIST.spec.ts | 2 +- packages/client/lib/commands/ACL_LOAD.spec.ts | 2 +- packages/client/lib/commands/ACL_LOG.spec.ts | 2 +- .../client/lib/commands/ACL_LOG_RESET.spec.ts | 2 +- packages/client/lib/commands/ACL_SAVE.spec.ts | 2 +- .../client/lib/commands/ACL_SETUSER.spec.ts | 2 +- .../client/lib/commands/ACL_USERS.spec.ts | 2 +- .../client/lib/commands/ACL_WHOAMI.spec.ts | 2 +- packages/client/lib/commands/APPEND.spec.ts | 2 +- packages/client/lib/commands/ASKING.spec.ts | 2 +- packages/client/lib/commands/AUTH.spec.ts | 2 +- .../client/lib/commands/BGREWRITEAOF.spec.ts | 2 +- packages/client/lib/commands/BGSAVE.spec.ts | 2 +- packages/client/lib/commands/BITCOUNT.spec.ts | 2 +- packages/client/lib/commands/BITFIELD.spec.ts | 2 +- .../client/lib/commands/BITFIELD_RO.spec.ts | 2 +- packages/client/lib/commands/BITOP.spec.ts | 2 +- packages/client/lib/commands/BITPOS.spec.ts | 2 +- packages/client/lib/commands/BLMOVE.spec.ts | 2 +- packages/client/lib/commands/BLMPOP.spec.ts | 2 +- packages/client/lib/commands/BLPOP.spec.ts | 2 +- packages/client/lib/commands/BRPOP.spec.ts | 2 +- .../client/lib/commands/BRPOPLPUSH.spec.ts | 2 +- packages/client/lib/commands/BZMPOP.spec.ts | 2 +- packages/client/lib/commands/BZPOPMAX.spec.ts | 2 +- packages/client/lib/commands/BZPOPMIN.spec.ts | 2 +- .../lib/commands/CLIENT_CACHING.spec.ts | 2 +- .../lib/commands/CLIENT_GETNAME.spec.ts | 2 +- .../lib/commands/CLIENT_GETREDIR.spec.ts | 2 +- .../client/lib/commands/CLIENT_ID.spec.ts | 2 +- .../client/lib/commands/CLIENT_INFO.spec.ts | 2 +- .../client/lib/commands/CLIENT_KILL.spec.ts | 2 +- .../client/lib/commands/CLIENT_LIST.spec.ts | 2 +- .../lib/commands/CLIENT_NO-EVICT.spec.ts | 2 +- .../client/lib/commands/CLIENT_PAUSE.spec.ts | 2 +- .../lib/commands/CLIENT_SETNAME.spec.ts | 2 +- .../lib/commands/CLIENT_TRACKING.spec.ts | 2 +- .../lib/commands/CLIENT_TRACKINGINFO.spec.ts | 2 +- .../lib/commands/CLIENT_UNPAUSE.spec.ts | 2 +- .../lib/commands/CLUSTER_ADDSLOTS.spec.ts | 2 +- .../commands/CLUSTER_ADDSLOTSRANGE.spec.ts | 2 +- .../lib/commands/CLUSTER_BUMPEPOCH.spec.ts | 2 +- .../CLUSTER_COUNT-FAILURE-REPORTS.spec.ts | 2 +- .../commands/CLUSTER_COUNTKEYSINSLOT.spec.ts | 2 +- .../lib/commands/CLUSTER_DELSLOTS.spec.ts | 2 +- .../commands/CLUSTER_DELSLOTSRANGE.spec.ts | 2 +- .../lib/commands/CLUSTER_FAILOVER.spec.ts | 2 +- .../lib/commands/CLUSTER_FLUSHSLOTS.spec.ts | 2 +- .../lib/commands/CLUSTER_FORGET.spec.ts | 2 +- .../commands/CLUSTER_GETKEYSINSLOT.spec.ts | 2 +- .../client/lib/commands/CLUSTER_INFO.spec.ts | 2 +- .../lib/commands/CLUSTER_KEYSLOT.spec.ts | 2 +- .../client/lib/commands/CLUSTER_LINKS.spec.ts | 2 +- .../client/lib/commands/CLUSTER_MEET.spec.ts | 2 +- .../client/lib/commands/CLUSTER_MYID.spec.ts | 2 +- .../client/lib/commands/CLUSTER_NODES.spec.ts | 2 +- .../lib/commands/CLUSTER_REPLICAS.spec.ts | 2 +- .../lib/commands/CLUSTER_REPLICATE.spec.ts | 2 +- .../client/lib/commands/CLUSTER_RESET.spec.ts | 2 +- .../lib/commands/CLUSTER_SAVECONFIG.spec.ts | 2 +- .../commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts | 2 +- .../lib/commands/CLUSTER_SETSLOT.spec.ts | 2 +- .../client/lib/commands/CLUSTER_SLOTS.spec.ts | 2 +- packages/client/lib/commands/COMMAND.spec.ts | 2 +- .../client/lib/commands/COMMAND_COUNT.spec.ts | 2 +- .../lib/commands/COMMAND_GETKEYS.spec.ts | 2 +- .../commands/COMMAND_GETKEYSANDFLAGS.spec.ts | 2 +- .../client/lib/commands/COMMAND_INFO.spec.ts | 2 +- .../client/lib/commands/COMMAND_LIST.spec.ts | 2 +- .../client/lib/commands/CONFIG_GET.spec.ts | 2 +- .../lib/commands/CONFIG_RESETSTAT.spec.ts | 2 +- .../lib/commands/CONFIG_REWRITE.spec.ts | 2 +- .../client/lib/commands/CONFIG_SET.spec.ts | 2 +- packages/client/lib/commands/COPY.spec.ts | 2 +- packages/client/lib/commands/DBSIZE.spec.ts | 2 +- packages/client/lib/commands/DECR.spec.ts | 2 +- packages/client/lib/commands/DECRBY.spec.ts | 2 +- packages/client/lib/commands/DEL.spec.ts | 2 +- packages/client/lib/commands/DISCARD.spec.ts | 2 +- packages/client/lib/commands/DUMP.spec.ts | 2 +- packages/client/lib/commands/ECHO.spec.ts | 2 +- packages/client/lib/commands/EVAL.spec.ts | 2 +- packages/client/lib/commands/EVALSHA.spec.ts | 2 +- .../client/lib/commands/EVALSHA_RO.spec.ts | 2 +- packages/client/lib/commands/EVAL_RO.spec.ts | 2 +- packages/client/lib/commands/EXISTS.spec.ts | 2 +- packages/client/lib/commands/EXPIRE.spec.ts | 2 +- packages/client/lib/commands/EXPIREAT.spec.ts | 2 +- .../client/lib/commands/EXPIRETIME.spec.ts | 2 +- packages/client/lib/commands/FAILOVER.spec.ts | 2 +- packages/client/lib/commands/FCALL.spec.ts | 2 +- packages/client/lib/commands/FCALL_RO.spec.ts | 2 +- packages/client/lib/commands/FLUSHALL.spec.ts | 2 +- packages/client/lib/commands/FLUSHDB.spec.ts | 2 +- .../lib/commands/FUNCTION_DELETE.spec.ts | 2 +- .../client/lib/commands/FUNCTION_DUMP.spec.ts | 2 +- .../lib/commands/FUNCTION_FLUSH.spec.ts | 2 +- .../client/lib/commands/FUNCTION_KILL.spec.ts | 2 +- .../client/lib/commands/FUNCTION_LIST.spec.ts | 2 +- .../commands/FUNCTION_LIST_WITHCODE.spec.ts | 2 +- .../client/lib/commands/FUNCTION_LOAD.spec.ts | 2 +- .../lib/commands/FUNCTION_RESTORE.spec.ts | 2 +- .../lib/commands/FUNCTION_STATS.spec.ts | 4 ++-- packages/client/lib/commands/GEOADD.spec.ts | 2 +- packages/client/lib/commands/GEODIST.spec.ts | 2 +- packages/client/lib/commands/GEOHASH.spec.ts | 2 +- packages/client/lib/commands/GEOPOS.spec.ts | 2 +- .../client/lib/commands/GEORADIUS.spec.ts | 2 +- .../lib/commands/GEORADIUSBYMEMBER.spec.ts | 2 +- .../lib/commands/GEORADIUSBYMEMBER_RO.spec.ts | 2 +- .../GEORADIUSBYMEMBER_RO_WITH.spec.ts | 2 +- .../commands/GEORADIUSBYMEMBER_STORE.spec.ts | 2 +- .../commands/GEORADIUSBYMEMBER_WITH.spec.ts | 2 +- .../client/lib/commands/GEORADIUS_RO.spec.ts | 2 +- .../lib/commands/GEORADIUS_RO_WITH.spec.ts | 2 +- .../lib/commands/GEORADIUS_STORE.spec.ts | 2 +- .../lib/commands/GEORADIUS_WITH.spec.ts | 2 +- .../client/lib/commands/GEOSEARCH.spec.ts | 2 +- .../lib/commands/GEOSEARCHSTORE.spec.ts | 2 +- .../lib/commands/GEOSEARCH_WITH.spec.ts | 2 +- packages/client/lib/commands/GET.spec.ts | 2 +- packages/client/lib/commands/GETBIT.spec.ts | 2 +- packages/client/lib/commands/GETDEL.spec.ts | 2 +- packages/client/lib/commands/GETEX.spec.ts | 2 +- packages/client/lib/commands/GETRANGE.spec.ts | 2 +- packages/client/lib/commands/GETSET.spec.ts | 2 +- packages/client/lib/commands/HDEL.spec.ts | 2 +- packages/client/lib/commands/HELLO.spec.ts | 2 +- packages/client/lib/commands/HEXISTS.spec.ts | 2 +- packages/client/lib/commands/HGET.spec.ts | 2 +- packages/client/lib/commands/HGETALL.spec.ts | 2 +- packages/client/lib/commands/HINCRBY.spec.ts | 2 +- .../client/lib/commands/HINCRBYFLOAT.spec.ts | 2 +- packages/client/lib/commands/HKEYS.spec.ts | 2 +- packages/client/lib/commands/HLEN.spec.ts | 2 +- packages/client/lib/commands/HMGET.spec.ts | 2 +- .../client/lib/commands/HRANDFIELD.spec.ts | 2 +- .../lib/commands/HRANDFIELD_COUNT.spec.ts | 2 +- packages/client/lib/commands/HSCAN.spec.ts | 2 +- packages/client/lib/commands/HSET.spec.ts | 2 +- packages/client/lib/commands/HSETNX.spec.ts | 2 +- packages/client/lib/commands/HSTRLEN.spec.ts | 2 +- packages/client/lib/commands/HVALS.spec.ts | 2 +- packages/client/lib/commands/INCR.spec.ts | 2 +- packages/client/lib/commands/INCRBY.spec.ts | 2 +- .../client/lib/commands/INCRBYFLOAT.spec.ts | 2 +- packages/client/lib/commands/INFO.spec.ts | 2 +- packages/client/lib/commands/KEYS.spec.ts | 2 +- packages/client/lib/commands/LASTSAVE.spec.ts | 2 +- .../lib/commands/LATENCY_DOCTOR.spec.ts | 2 +- .../client/lib/commands/LATENCY_GRAPH.spec.ts | 2 +- .../lib/commands/LATENCY_LATEST.spec.ts | 2 +- packages/client/lib/commands/LCS.spec.ts | 2 +- packages/client/lib/commands/LCS_IDX.spec.ts | 2 +- .../lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts | 2 +- packages/client/lib/commands/LCS_LEN.spec.ts | 2 +- packages/client/lib/commands/LINDEX.spec.ts | 2 +- packages/client/lib/commands/LINSERT.spec.ts | 2 +- packages/client/lib/commands/LLEN.spec.ts | 2 +- packages/client/lib/commands/LMOVE.spec.ts | 2 +- packages/client/lib/commands/LMPOP.spec.ts | 2 +- packages/client/lib/commands/LOLWUT.spec.ts | 2 +- packages/client/lib/commands/LPOP.spec.ts | 2 +- .../client/lib/commands/LPOP_COUNT.spec.ts | 2 +- packages/client/lib/commands/LPOS.spec.ts | 2 +- .../client/lib/commands/LPOS_COUNT.spec.ts | 2 +- packages/client/lib/commands/LPUSH.spec.ts | 2 +- packages/client/lib/commands/LPUSHX.spec.ts | 2 +- packages/client/lib/commands/LRANGE.spec.ts | 2 +- packages/client/lib/commands/LREM.spec.ts | 2 +- packages/client/lib/commands/LSET.spec.ts | 2 +- packages/client/lib/commands/LTRIM.spec.ts | 2 +- .../client/lib/commands/MEMORY_DOCTOR.spec.ts | 2 +- .../lib/commands/MEMORY_MALLOC-STATS.spec.ts | 2 +- .../client/lib/commands/MEMORY_PURGE.spec.ts | 2 +- .../client/lib/commands/MEMORY_STATS.spec.ts | 2 +- .../client/lib/commands/MEMORY_USAGE.spec.ts | 2 +- packages/client/lib/commands/MGET.spec.ts | 2 +- packages/client/lib/commands/MIGRATE.spec.ts | 2 +- .../client/lib/commands/MODULE_LIST.spec.ts | 2 +- .../client/lib/commands/MODULE_LOAD.spec.ts | 2 +- .../client/lib/commands/MODULE_UNLOAD.spec.ts | 2 +- packages/client/lib/commands/MOVE.spec.ts | 2 +- packages/client/lib/commands/MSET.spec.ts | 2 +- packages/client/lib/commands/MSETNX.spec.ts | 2 +- .../lib/commands/OBJECT_ENCODING.spec.ts | 2 +- .../client/lib/commands/OBJECT_FREQ.spec.ts | 2 +- .../lib/commands/OBJECT_IDLETIME.spec.ts | 2 +- .../lib/commands/OBJECT_REFCOUNT.spec.ts | 2 +- packages/client/lib/commands/PERSIST.spec.ts | 2 +- packages/client/lib/commands/PEXPIRE.spec.ts | 2 +- .../client/lib/commands/PEXPIREAT.spec.ts | 2 +- .../client/lib/commands/PEXPIRETIME.spec.ts | 2 +- packages/client/lib/commands/PFADD.spec.ts | 2 +- packages/client/lib/commands/PFCOUNT.spec.ts | 2 +- packages/client/lib/commands/PFMERGE.spec.ts | 2 +- packages/client/lib/commands/PING.spec.ts | 2 +- packages/client/lib/commands/PSETEX.spec.ts | 2 +- packages/client/lib/commands/PTTL.spec.ts | 2 +- packages/client/lib/commands/PUBLISH.spec.ts | 2 +- .../lib/commands/PUBSUB_CHANNELS.spec.ts | 2 +- .../client/lib/commands/PUBSUB_NUMPAT.spec.ts | 2 +- .../client/lib/commands/PUBSUB_NUMSUB.spec.ts | 2 +- .../lib/commands/PUBSUB_SHARDCHANNELS.spec.ts | 2 +- .../client/lib/commands/RANDOMKEY.spec.ts | 2 +- packages/client/lib/commands/READONLY.spec.ts | 2 +- .../client/lib/commands/READWRITE.spec.ts | 2 +- packages/client/lib/commands/RENAME.spec.ts | 2 +- packages/client/lib/commands/RENAMENX.spec.ts | 2 +- .../client/lib/commands/REPLICAOF.spec.ts | 2 +- .../lib/commands/RESTORE-ASKING.spec.ts | 2 +- packages/client/lib/commands/ROLE.spec.ts | 2 +- packages/client/lib/commands/RPOP.spec.ts | 2 +- .../client/lib/commands/RPOPLPUSH.spec.ts | 2 +- .../client/lib/commands/RPOP_COUNT.spec.ts | 2 +- packages/client/lib/commands/RPUSH.spec.ts | 2 +- packages/client/lib/commands/RPUSHX.spec.ts | 2 +- packages/client/lib/commands/SADD.spec.ts | 2 +- packages/client/lib/commands/SAVE.spec.ts | 2 +- packages/client/lib/commands/SCAN.spec.ts | 2 +- packages/client/lib/commands/SCARD.spec.ts | 2 +- .../client/lib/commands/SCRIPT_DEBUG.spec.ts | 2 +- .../client/lib/commands/SCRIPT_EXISTS.spec.ts | 2 +- .../client/lib/commands/SCRIPT_FLUSH.spec.ts | 2 +- .../client/lib/commands/SCRIPT_KILL.spec.ts | 2 +- .../client/lib/commands/SCRIPT_LOAD.spec.ts | 2 +- packages/client/lib/commands/SDIFF.spec.ts | 2 +- .../client/lib/commands/SDIFFSTORE.spec.ts | 2 +- packages/client/lib/commands/SET.spec.ts | 2 +- packages/client/lib/commands/SETBIT.spec.ts | 2 +- packages/client/lib/commands/SETEX.spec.ts | 2 +- packages/client/lib/commands/SETNX .spec.ts | 2 +- packages/client/lib/commands/SETRANGE.spec.ts | 2 +- packages/client/lib/commands/SHUTDOWN.spec.ts | 2 +- packages/client/lib/commands/SINTER.spec.ts | 2 +- .../client/lib/commands/SINTERCARD.spec.ts | 2 +- .../client/lib/commands/SINTERSTORE.spec.ts | 2 +- .../client/lib/commands/SISMEMBER.spec.ts | 2 +- packages/client/lib/commands/SMEMBERS.spec.ts | 2 +- .../client/lib/commands/SMISMEMBER.spec.ts | 2 +- packages/client/lib/commands/SMOVE.spec.ts | 2 +- packages/client/lib/commands/SORT.spec.ts | 2 +- packages/client/lib/commands/SORT_RO.spec.ts | 2 +- .../client/lib/commands/SORT_STORE.spec.ts | 2 +- packages/client/lib/commands/SPOP.spec.ts | 2 +- .../client/lib/commands/SPOP_COUNT.spec.ts | 2 +- packages/client/lib/commands/SPUBLISH.spec.ts | 2 +- .../client/lib/commands/SRANDMEMBER.spec.ts | 2 +- .../lib/commands/SRANDMEMBER_COUNT.spec.ts | 2 +- packages/client/lib/commands/SREM.spec.ts | 2 +- packages/client/lib/commands/SSCAN.spec.ts | 2 +- packages/client/lib/commands/STRLEN.spec.ts | 2 +- packages/client/lib/commands/SUNION.spec.ts | 2 +- .../client/lib/commands/SUNIONSTORE.spec.ts | 2 +- packages/client/lib/commands/SWAPDB.spec.ts | 2 +- packages/client/lib/commands/TIME.spec.ts | 2 +- packages/client/lib/commands/TOUCH.spec.ts | 2 +- packages/client/lib/commands/TTL.spec.ts | 2 +- packages/client/lib/commands/TYPE.spec.ts | 2 +- packages/client/lib/commands/UNLINK.spec.ts | 2 +- packages/client/lib/commands/UNWATCH.spec.ts | 2 +- packages/client/lib/commands/WAIT.spec.ts | 2 +- packages/client/lib/commands/WATCH.spec.ts | 2 +- packages/client/lib/commands/XACK.spec.ts | 2 +- packages/client/lib/commands/XADD.spec.ts | 2 +- .../lib/commands/XADD_NOMKSTREAM.spec.ts | 2 +- .../client/lib/commands/XAUTOCLAIM.spec.ts | 2 +- .../lib/commands/XAUTOCLAIM_JUSTID.spec.ts | 2 +- packages/client/lib/commands/XCLAIM.spec.ts | 2 +- .../client/lib/commands/XCLAIM_JUSTID.spec.ts | 2 +- packages/client/lib/commands/XDEL.spec.ts | 2 +- .../client/lib/commands/XGROUP_CREATE.spec.ts | 2 +- .../commands/XGROUP_CREATECONSUMER.spec.ts | 2 +- .../lib/commands/XGROUP_DELCONSUMER.spec.ts | 2 +- .../lib/commands/XGROUP_DESTROY.spec.ts | 2 +- .../client/lib/commands/XGROUP_SETID.spec.ts | 2 +- .../lib/commands/XINFO_CONSUMERS.spec.ts | 2 +- .../client/lib/commands/XINFO_GROUPS.spec.ts | 2 +- .../client/lib/commands/XINFO_STREAM.spec.ts | 2 +- packages/client/lib/commands/XLEN.spec.ts | 2 +- packages/client/lib/commands/XPENDING.spec.ts | 2 +- .../lib/commands/XPENDING_RANGE.spec.ts | 2 +- packages/client/lib/commands/XRANGE.spec.ts | 2 +- packages/client/lib/commands/XREAD.spec.ts | 2 +- .../client/lib/commands/XREADGROUP.spec.ts | 2 +- .../client/lib/commands/XREVRANGE.spec.ts | 2 +- packages/client/lib/commands/XSETID.spec.ts | 2 +- packages/client/lib/commands/XTRIM.spec.ts | 2 +- packages/client/lib/commands/ZADD.spec.ts | 2 +- .../client/lib/commands/ZADD_INCR.spec.ts | 2 +- packages/client/lib/commands/ZCARD.spec.ts | 2 +- packages/client/lib/commands/ZCOUNT.spec.ts | 2 +- packages/client/lib/commands/ZDIFF.spec.ts | 2 +- .../client/lib/commands/ZDIFFSTORE.spec.ts | 2 +- .../lib/commands/ZDIFF_WITHSCORES.spec.ts | 2 +- packages/client/lib/commands/ZINCRBY.spec.ts | 2 +- packages/client/lib/commands/ZINTER.spec.ts | 2 +- .../client/lib/commands/ZINTERCARD.spec.ts | 2 +- .../client/lib/commands/ZINTERSTORE.spec.ts | 2 +- .../lib/commands/ZINTER_WITHSCORES.spec.ts | 2 +- .../client/lib/commands/ZLEXCOUNT.spec.ts | 2 +- packages/client/lib/commands/ZMPOP.spec.ts | 2 +- packages/client/lib/commands/ZMSCORE.spec.ts | 2 +- packages/client/lib/commands/ZPOPMAX.spec.ts | 2 +- .../client/lib/commands/ZPOPMAX_COUNT.spec.ts | 2 +- packages/client/lib/commands/ZPOPMIN.spec.ts | 2 +- .../client/lib/commands/ZPOPMIN_COUNT.spec.ts | 2 +- .../client/lib/commands/ZRANDMEMBER.spec.ts | 2 +- .../lib/commands/ZRANDMEMBER_COUNT.spec.ts | 2 +- .../ZRANDMEMBER_COUNT_WITHSCORES.spec.ts | 2 +- packages/client/lib/commands/ZRANGE.spec.ts | 2 +- .../client/lib/commands/ZRANGEBYLEX.spec.ts | 2 +- .../client/lib/commands/ZRANGEBYSCORE.spec.ts | 2 +- .../commands/ZRANGEBYSCORE_WITHSCORES.spec.ts | 2 +- .../client/lib/commands/ZRANGESTORE.spec.ts | 2 +- .../lib/commands/ZRANGE_WITHSCORES.spec.ts | 2 +- packages/client/lib/commands/ZRANK.spec.ts | 2 +- .../lib/commands/ZRANK_WITHSCORE.spec.ts | 2 +- packages/client/lib/commands/ZREM.spec.ts | 2 +- .../lib/commands/ZREMRANGEBYLEX.spec.ts | 2 +- .../lib/commands/ZREMRANGEBYRANK.spec.ts | 2 +- .../lib/commands/ZREMRANGEBYSCORE.spec.ts | 2 +- packages/client/lib/commands/ZREVRANK.spec.ts | 2 +- packages/client/lib/commands/ZSCAN.spec.ts | 2 +- packages/client/lib/commands/ZSCORE.spec.ts | 2 +- packages/client/lib/commands/ZUNION.spec.ts | 2 +- .../client/lib/commands/ZUNIONSTORE.spec.ts | 2 +- .../lib/commands/ZUNION_WITHSCORES.spec.ts | 2 +- .../lib/commands/generic-transformers.spec.ts | 2 +- packages/client/lib/commands/index.ts | 6 +++--- packages/client/lib/lua-script.ts | 2 +- packages/client/lib/multi-command.spec.ts | 2 +- .../graph/lib/commands/CONFIG_GET.spec.ts | 2 +- .../graph/lib/commands/CONFIG_SET.spec.ts | 2 +- packages/graph/lib/commands/DELETE.spec.ts | 2 +- packages/graph/lib/commands/EXPLAIN.spec.ts | 2 +- packages/graph/lib/commands/LIST.spec.ts | 2 +- packages/graph/lib/commands/PROFILE.spec.ts | 2 +- packages/graph/lib/commands/QUERY.spec.ts | 2 +- packages/graph/lib/commands/RO_QUERY.spec.ts | 2 +- packages/graph/lib/commands/SLOWLOG.spec.ts | 2 +- packages/graph/lib/graph.spec.ts | 2 +- packages/json/lib/commands/ARRAPPEND.spec.ts | 2 +- packages/json/lib/commands/ARRINDEX.spec.ts | 2 +- packages/json/lib/commands/ARRINSERT.spec.ts | 2 +- packages/json/lib/commands/ARRLEN.spec.ts | 2 +- packages/json/lib/commands/ARRPOP.spec.ts | 2 +- packages/json/lib/commands/ARRTRIM.spec.ts | 2 +- packages/json/lib/commands/CLEAR.spec.ts | 2 +- .../json/lib/commands/DEBUG_MEMORY.spec.ts | 2 +- packages/json/lib/commands/DEL.spec.ts | 2 +- packages/json/lib/commands/FORGET.spec.ts | 2 +- packages/json/lib/commands/GET.spec.ts | 2 +- packages/json/lib/commands/MERGE.spec.ts | 2 +- packages/json/lib/commands/MGET.spec.ts | 2 +- packages/json/lib/commands/MSET.spec.ts | 2 +- packages/json/lib/commands/NUMINCRBY.spec.ts | 2 +- packages/json/lib/commands/NUMMULTBY.spec.ts | 2 +- packages/json/lib/commands/OBJKEYS.spec.ts | 2 +- packages/json/lib/commands/OBJLEN.spec.ts | 2 +- packages/json/lib/commands/RESP.spec.ts | 2 +- packages/json/lib/commands/SET.spec.ts | 2 +- packages/json/lib/commands/STRAPPEND.spec.ts | 2 +- packages/json/lib/commands/STRLEN.spec.ts | 2 +- packages/json/lib/commands/TOGGLE.spec.ts | 2 +- packages/json/lib/commands/TYPE.spec.ts | 2 +- .../search/lib/commands/AGGREGATE.spec.ts | 2 +- .../lib/commands/AGGREGATE_WITHCURSOR.spec.ts | 2 +- packages/search/lib/commands/ALIASADD.spec.ts | 2 +- packages/search/lib/commands/ALIASDEL.spec.ts | 2 +- .../search/lib/commands/ALIASUPDATE.spec.ts | 2 +- packages/search/lib/commands/ALTER.spec.ts | 2 +- .../search/lib/commands/CONFIG_GET.spec.ts | 2 +- .../search/lib/commands/CONFIG_SET.spec.ts | 2 +- packages/search/lib/commands/CREATE.spec.ts | 2 +- .../search/lib/commands/CURSOR_DEL.spec.ts | 2 +- .../search/lib/commands/CURSOR_READ.spec.ts | 2 +- packages/search/lib/commands/DICTADD.spec.ts | 2 +- packages/search/lib/commands/DICTDEL.spec.ts | 2 +- packages/search/lib/commands/DICTDUMP.spec.ts | 2 +- .../search/lib/commands/DROPINDEX.spec.ts | 2 +- packages/search/lib/commands/EXPLAIN.spec.ts | 2 +- .../search/lib/commands/EXPLAINCLI.spec.ts | 2 +- packages/search/lib/commands/INFO.spec.ts | 2 +- .../lib/commands/PROFILE_AGGREGATE.spec.ts | 2 +- .../lib/commands/PROFILE_SEARCH.spec.ts | 2 +- packages/search/lib/commands/SEARCH.spec.ts | 2 +- .../search/lib/commands/SPELLCHECK.spec.ts | 2 +- packages/search/lib/commands/SUGADD.spec.ts | 2 +- packages/search/lib/commands/SUGDEL.spec.ts | 2 +- packages/search/lib/commands/SUGGET.spec.ts | 2 +- .../lib/commands/SUGGET_WITHPAYLOADS.spec.ts | 2 +- .../lib/commands/SUGGET_WITHSCORES.spec.ts | 2 +- .../SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts | 2 +- packages/search/lib/commands/SUGLEN.spec.ts | 2 +- packages/search/lib/commands/SYNDUMP.spec.ts | 2 +- .../search/lib/commands/SYNUPDATE.spec.ts | 2 +- packages/search/lib/commands/TAGVALS.spec.ts | 2 +- packages/search/lib/commands/_LIST.spec.ts | 2 +- packages/search/lib/commands/index.spec.ts | 2 +- packages/test-utils/lib/dockers.ts | 10 +++++----- packages/time-series/lib/commands/ADD.spec.ts | 2 +- .../time-series/lib/commands/ALTER.spec.ts | 2 +- .../time-series/lib/commands/CREATE.spec.ts | 2 +- .../lib/commands/CREATERULE.spec.ts | 2 +- .../time-series/lib/commands/DECRBY.spec.ts | 2 +- packages/time-series/lib/commands/DEL.spec.ts | 2 +- .../lib/commands/DELETERULE.spec.ts | 2 +- packages/time-series/lib/commands/GET.spec.ts | 2 +- .../time-series/lib/commands/INCRBY.spec.ts | 2 +- .../time-series/lib/commands/INFO.spec.ts | 2 +- .../lib/commands/INFO_DEBUG.spec.ts | 2 +- .../time-series/lib/commands/MADD.spec.ts | 2 +- .../time-series/lib/commands/MGET.spec.ts | 2 +- .../lib/commands/MGET_WITHLABELS.spec.ts | 2 +- .../time-series/lib/commands/MRANGE.spec.ts | 2 +- .../lib/commands/MRANGE_WITHLABELS.spec.ts | 2 +- .../lib/commands/MREVRANGE.spec.ts | 2 +- .../lib/commands/MREVRANGE_WITHLABELS.spec.ts | 2 +- .../lib/commands/QUERYINDEX.spec.ts | 2 +- .../time-series/lib/commands/RANGE.spec.ts | 2 +- .../time-series/lib/commands/REVRANGE.spec.ts | 2 +- .../time-series/lib/commands/index.spec.ts | 2 +- 495 files changed, 528 insertions(+), 528 deletions(-) diff --git a/benchmark/lib/index.js b/benchmark/lib/index.js index 15c8a12f401..5576999bfbc 100644 --- a/benchmark/lib/index.js +++ b/benchmark/lib/index.js @@ -1,10 +1,10 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { promises as fs } from 'fs'; -import { fork } from 'child_process'; -import { URL, fileURLToPath } from 'url'; -import { once } from 'events'; -import { extname } from 'path'; +import { promises as fs } from 'node:fs'; +import { fork } from 'node:child_process'; +import { URL, fileURLToPath } from 'node:url'; +import { once } from 'node:events'; +import { extname } from 'node:path'; async function getPathChoices() { const dirents = await fs.readdir(new URL('.', import.meta.url), { diff --git a/benchmark/lib/ping/v3.js b/benchmark/lib/ping/v3.js index 26f269a42cf..e7e62d3e15a 100644 --- a/benchmark/lib/ping/v3.js +++ b/benchmark/lib/ping/v3.js @@ -1,6 +1,6 @@ import { createClient } from 'redis-v3'; -import { once } from 'events'; -import { promisify } from 'util'; +import { once } from 'node:events'; +import { promisify } from 'node:util'; export default async (host) => { const client = createClient({ host }), diff --git a/benchmark/lib/runner.js b/benchmark/lib/runner.js index fd61a1a1e5c..7d81d3bb8c7 100644 --- a/benchmark/lib/runner.js +++ b/benchmark/lib/runner.js @@ -1,7 +1,7 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { basename } from 'path'; -import { promises as fs } from 'fs'; +import { basename } from 'node:path'; +import { promises as fs } from 'node:fs'; import * as hdr from 'hdr-histogram-js'; hdr.initWebAssemblySync(); diff --git a/benchmark/lib/set-get-delete-string/index.js b/benchmark/lib/set-get-delete-string/index.js index 719edfc7fdf..506b222a6cb 100644 --- a/benchmark/lib/set-get-delete-string/index.js +++ b/benchmark/lib/set-get-delete-string/index.js @@ -1,6 +1,6 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { randomBytes } from 'crypto'; +import { randomBytes } from 'node:crypto'; const { size } = yargs(hideBin(process.argv)) .option('size', { diff --git a/benchmark/lib/set-get-delete-string/v3.js b/benchmark/lib/set-get-delete-string/v3.js index 27ff6702a51..1e2122a0e49 100644 --- a/benchmark/lib/set-get-delete-string/v3.js +++ b/benchmark/lib/set-get-delete-string/v3.js @@ -1,6 +1,6 @@ import { createClient } from 'redis-v3'; -import { once } from 'events'; -import { promisify } from 'util'; +import { once } from 'node:events'; +import { promisify } from 'node:util'; export default async (host, { randomString }) => { const client = createClient({ host }), diff --git a/packages/bloom/lib/commands/bloom/ADD.spec.ts b/packages/bloom/lib/commands/bloom/ADD.spec.ts index 5a14e0c7799..11267e2afdb 100644 --- a/packages/bloom/lib/commands/bloom/ADD.spec.ts +++ b/packages/bloom/lib/commands/bloom/ADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import ADD from './ADD'; diff --git a/packages/bloom/lib/commands/bloom/CARD.spec.ts b/packages/bloom/lib/commands/bloom/CARD.spec.ts index ed54a436148..b150f812574 100644 --- a/packages/bloom/lib/commands/bloom/CARD.spec.ts +++ b/packages/bloom/lib/commands/bloom/CARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import CARD from './CARD'; diff --git a/packages/bloom/lib/commands/bloom/EXISTS.spec.ts b/packages/bloom/lib/commands/bloom/EXISTS.spec.ts index 276607b5d1e..7db891b92bf 100644 --- a/packages/bloom/lib/commands/bloom/EXISTS.spec.ts +++ b/packages/bloom/lib/commands/bloom/EXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import EXISTS from './EXISTS'; diff --git a/packages/bloom/lib/commands/bloom/INFO.spec.ts b/packages/bloom/lib/commands/bloom/INFO.spec.ts index 7a9f30faa71..77b6a589ba4 100644 --- a/packages/bloom/lib/commands/bloom/INFO.spec.ts +++ b/packages/bloom/lib/commands/bloom/INFO.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../../test-utils'; // import { transformArguments } from './INFO'; diff --git a/packages/bloom/lib/commands/bloom/INSERT.spec.ts b/packages/bloom/lib/commands/bloom/INSERT.spec.ts index cb18dcd7a11..ccd81e070f1 100644 --- a/packages/bloom/lib/commands/bloom/INSERT.spec.ts +++ b/packages/bloom/lib/commands/bloom/INSERT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INSERT from './INSERT'; diff --git a/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts b/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts index 29a22cbd713..f958863c0dc 100644 --- a/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts +++ b/packages/bloom/lib/commands/bloom/LOADCHUNK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import LOADCHUNK from './LOADCHUNK'; import { RESP_TYPES } from '@redis/client'; diff --git a/packages/bloom/lib/commands/bloom/MADD.spec.ts b/packages/bloom/lib/commands/bloom/MADD.spec.ts index f4abf6e2480..5241a09485a 100644 --- a/packages/bloom/lib/commands/bloom/MADD.spec.ts +++ b/packages/bloom/lib/commands/bloom/MADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MADD from './MADD'; diff --git a/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts b/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts index 0023a41e9b2..0f313ba636f 100644 --- a/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts +++ b/packages/bloom/lib/commands/bloom/MEXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MEXISTS from './MEXISTS'; diff --git a/packages/bloom/lib/commands/bloom/RESERVE.spec.ts b/packages/bloom/lib/commands/bloom/RESERVE.spec.ts index dfb6c820ff4..caf40d4a48f 100644 --- a/packages/bloom/lib/commands/bloom/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/bloom/RESERVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import RESERVE from './RESERVE'; diff --git a/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts b/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts index 4e5f5c3cccc..a7de98eabe7 100644 --- a/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts +++ b/packages/bloom/lib/commands/bloom/SCANDUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import SCANDUMP from './SCANDUMP'; diff --git a/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts index 3b77d3b93d8..1d2921cab75 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INCRBY from './INCRBY'; diff --git a/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts index ff227cb5be0..24b74e2c744 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INFO from './INFO'; diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts index 0c9a712183b..a3d27c17df3 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYDIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INITBYDIM from './INITBYDIM'; diff --git a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts index 592be4db6bf..8df62020e89 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INITBYPROB.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INITBYPROB from './INITBYPROB'; diff --git a/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts b/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts index f996f88648c..eef4bd403ae 100644 --- a/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/MERGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MERGE from './MERGE'; diff --git a/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts b/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts index f321c28a0e9..cc9c913b563 100644 --- a/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts +++ b/packages/bloom/lib/commands/count-min-sketch/QUERY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import QUERY from './QUERY'; diff --git a/packages/bloom/lib/commands/cuckoo/ADD.spec.ts b/packages/bloom/lib/commands/cuckoo/ADD.spec.ts index d05c1c0e7f3..fa610cc6666 100644 --- a/packages/bloom/lib/commands/cuckoo/ADD.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/ADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import ADD from './ADD'; diff --git a/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts b/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts index 1a291e7b308..f50ad87dc15 100644 --- a/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/ADDNX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import ADDNX from './ADDNX'; diff --git a/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts b/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts index e3b53cd35a5..ff8d40f064e 100644 --- a/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import COUNT from './COUNT'; diff --git a/packages/bloom/lib/commands/cuckoo/DEL.spec.ts b/packages/bloom/lib/commands/cuckoo/DEL.spec.ts index eddfe7298d3..e02b5636e12 100644 --- a/packages/bloom/lib/commands/cuckoo/DEL.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/DEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import DEL from './DEL'; diff --git a/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts b/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts index 08e3c522f4d..899c11e8394 100644 --- a/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/EXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import EXISTS from './EXISTS'; diff --git a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts index 1663ed0c7c8..e92e32f1251 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../../test-utils'; // import { transformArguments } from './INFO'; diff --git a/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts b/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts index 40571f34cb4..096cf547098 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INSERT from './INSERT'; diff --git a/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts b/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts index bca4f90546c..0f874278220 100644 --- a/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INSERTNX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INSERTNX from './INSERTNX'; diff --git a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts index a2292d78bd3..4af0d24db45 100644 --- a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import LOADCHUNK from './LOADCHUNK'; import { RESP_TYPES } from '@redis/client'; diff --git a/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts b/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts index ee4d56af488..b8f2556bc4f 100644 --- a/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/RESERVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import RESERVE from './RESERVE'; diff --git a/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts b/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts index e84142b4ae6..e1bac59d323 100644 --- a/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/SCANDUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import SCANDUMP from './SCANDUMP'; diff --git a/packages/bloom/lib/commands/t-digest/ADD.spec.ts b/packages/bloom/lib/commands/t-digest/ADD.spec.ts index e77d67cba2c..31d4957c6ad 100644 --- a/packages/bloom/lib/commands/t-digest/ADD.spec.ts +++ b/packages/bloom/lib/commands/t-digest/ADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import ADD from './ADD'; diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts index d6e31f59b4e..a6443d77432 100644 --- a/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import BYRANK from './BYRANK'; diff --git a/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts index 7549ea870c2..f5bb4e62816 100644 --- a/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import BYREVRANK from './BYREVRANK'; diff --git a/packages/bloom/lib/commands/t-digest/CDF.spec.ts b/packages/bloom/lib/commands/t-digest/CDF.spec.ts index 7ba56ccda6b..09208deba11 100644 --- a/packages/bloom/lib/commands/t-digest/CDF.spec.ts +++ b/packages/bloom/lib/commands/t-digest/CDF.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import CDF from './CDF'; diff --git a/packages/bloom/lib/commands/t-digest/CREATE.spec.ts b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts index f731241ab38..781b2a7e432 100644 --- a/packages/bloom/lib/commands/t-digest/CREATE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import CREATE from './CREATE'; diff --git a/packages/bloom/lib/commands/t-digest/INFO.spec.ts b/packages/bloom/lib/commands/t-digest/INFO.spec.ts index b3aa1281cda..7845c49804f 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.spec.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../../test-utils'; // import { transformArguments } from './INFO'; diff --git a/packages/bloom/lib/commands/t-digest/MAX.spec.ts b/packages/bloom/lib/commands/t-digest/MAX.spec.ts index cd6fc6517db..caa92b0a6a0 100644 --- a/packages/bloom/lib/commands/t-digest/MAX.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MAX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MAX from './MAX'; diff --git a/packages/bloom/lib/commands/t-digest/MERGE.spec.ts b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts index a20bf4626d9..1ee792e3a40 100644 --- a/packages/bloom/lib/commands/t-digest/MERGE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MERGE from './MERGE'; diff --git a/packages/bloom/lib/commands/t-digest/MIN.spec.ts b/packages/bloom/lib/commands/t-digest/MIN.spec.ts index 7fac680558e..0d1637cc9b7 100644 --- a/packages/bloom/lib/commands/t-digest/MIN.spec.ts +++ b/packages/bloom/lib/commands/t-digest/MIN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import MIN from './MIN'; diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts index 7d96d5c9197..c427f8c4501 100644 --- a/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import QUANTILE from './QUANTILE'; diff --git a/packages/bloom/lib/commands/t-digest/RANK.spec.ts b/packages/bloom/lib/commands/t-digest/RANK.spec.ts index 8cac177ecc6..dcdae48cb06 100644 --- a/packages/bloom/lib/commands/t-digest/RANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/RANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import RANK from './RANK'; diff --git a/packages/bloom/lib/commands/t-digest/RESET.spec.ts b/packages/bloom/lib/commands/t-digest/RESET.spec.ts index 41c4d1491db..072257113b9 100644 --- a/packages/bloom/lib/commands/t-digest/RESET.spec.ts +++ b/packages/bloom/lib/commands/t-digest/RESET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import RESET from './RESET'; diff --git a/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts index 8600ea3645b..baa1b94afa8 100644 --- a/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts +++ b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import REVRANK from './REVRANK'; diff --git a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts index 387a605a188..c43c0f47553 100644 --- a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts +++ b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import TRIMMED_MEAN from './TRIMMED_MEAN'; diff --git a/packages/bloom/lib/commands/top-k/ADD.spec.ts b/packages/bloom/lib/commands/top-k/ADD.spec.ts index dc29aab803a..8f6f9300b36 100644 --- a/packages/bloom/lib/commands/top-k/ADD.spec.ts +++ b/packages/bloom/lib/commands/top-k/ADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import ADD from './ADD'; diff --git a/packages/bloom/lib/commands/top-k/COUNT.spec.ts b/packages/bloom/lib/commands/top-k/COUNT.spec.ts index 156b6147e90..dce03f0e78c 100644 --- a/packages/bloom/lib/commands/top-k/COUNT.spec.ts +++ b/packages/bloom/lib/commands/top-k/COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import COUNT from './COUNT'; diff --git a/packages/bloom/lib/commands/top-k/INCRBY.spec.ts b/packages/bloom/lib/commands/top-k/INCRBY.spec.ts index 5e14ba49c28..aa7032a9a02 100644 --- a/packages/bloom/lib/commands/top-k/INCRBY.spec.ts +++ b/packages/bloom/lib/commands/top-k/INCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INCRBY from './INCRBY'; diff --git a/packages/bloom/lib/commands/top-k/INFO.spec.ts b/packages/bloom/lib/commands/top-k/INFO.spec.ts index d138c90393d..8e17829a2a6 100644 --- a/packages/bloom/lib/commands/top-k/INFO.spec.ts +++ b/packages/bloom/lib/commands/top-k/INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import INFO from './INFO'; diff --git a/packages/bloom/lib/commands/top-k/LIST.spec.ts b/packages/bloom/lib/commands/top-k/LIST.spec.ts index b2ba11fcdd2..7ab96182bbe 100644 --- a/packages/bloom/lib/commands/top-k/LIST.spec.ts +++ b/packages/bloom/lib/commands/top-k/LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import LIST from './LIST'; diff --git a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts index 06d40ad37a8..862d17eb3e3 100644 --- a/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts +++ b/packages/bloom/lib/commands/top-k/LIST_WITHCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import LIST_WITHCOUNT from './LIST_WITHCOUNT'; diff --git a/packages/bloom/lib/commands/top-k/QUERY.spec.ts b/packages/bloom/lib/commands/top-k/QUERY.spec.ts index fdaefe91eab..d5ecfebb6c6 100644 --- a/packages/bloom/lib/commands/top-k/QUERY.spec.ts +++ b/packages/bloom/lib/commands/top-k/QUERY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import QUERY from './QUERY'; diff --git a/packages/bloom/lib/commands/top-k/RESERVE.spec.ts b/packages/bloom/lib/commands/top-k/RESERVE.spec.ts index f58c5b8b33f..39d8fb7efc6 100644 --- a/packages/bloom/lib/commands/top-k/RESERVE.spec.ts +++ b/packages/bloom/lib/commands/top-k/RESERVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../../test-utils'; import RESERVE from './RESERVE'; diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index 911baafb506..e4e447fab6b 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import { SinonSpy, spy } from 'sinon'; // import { Decoder, RESP_TYPES } from './decoder'; // import { ErrorReply } from '../errors'; diff --git a/packages/client/lib/RESP/encoder.spec.ts b/packages/client/lib/RESP/encoder.spec.ts index f8f20d783b3..2cbdc7d0b24 100644 --- a/packages/client/lib/RESP/encoder.spec.ts +++ b/packages/client/lib/RESP/encoder.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { describe } from 'mocha'; import encodeCommand from './encoder'; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 1adc1a76925..5a25674a7ee 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -4,7 +4,7 @@ import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder'; import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; -import { EventEmitter } from 'stream'; +import { EventEmitter } from 'node:stream'; export interface CommandOptions { chainId?: symbol; diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 0312aa9d0c3..4c77a257cd8 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; import RedisClient, { RedisClientType } from '.'; // import { RedisClientMultiCommandType } from './multi-command'; @@ -6,9 +6,9 @@ import RedisClient, { RedisClientType } from '.'; import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; // import { spy } from 'sinon'; -import { once } from 'events'; +import { once } from 'node:events'; // import { ClientKillFilters } from '../commands/CLIENT_KILL'; -// import { promisify } from 'util'; +// import { promisify } from 'node:util'; import { MATH_FUNCTION, loadMathFunction } from '../commands/FUNCTION_LOAD.spec'; import { RESP_TYPES } from '../RESP/decoder'; import { SortedSetMember } from '../commands/generic-transformers'; diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 5e2d102bf89..60b814e3ea8 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -1,11 +1,11 @@ import COMMANDS from '../commands'; import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket'; import RedisCommandsQueue, { CommandOptions } from './commands-queue'; -import { EventEmitter } from 'events'; +import { EventEmitter } from 'node:events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchError } from '../errors'; -import { URL } from 'url'; -import { TcpSocketConnectOpts } from 'net'; +import { URL } from 'node:url'; +import { TcpSocketConnectOpts } from 'node:net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; import { Command, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; diff --git a/packages/client/lib/client/legacy-mode.spec.ts b/packages/client/lib/client/legacy-mode.spec.ts index 4a2936c9e5e..306ea7f3353 100644 --- a/packages/client/lib/client/legacy-mode.spec.ts +++ b/packages/client/lib/client/legacy-mode.spec.ts @@ -1,10 +1,10 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { promisify } from 'util'; +import { promisify } from 'node:util'; import { RedisLegacyClientType } from './legacy-mode'; import { ErrorReply } from '../errors'; import { RedisClientType } from '.'; -import { once } from 'events'; +import { once } from 'node:events'; function testWithLegacyClient(title: string, fn: (legacy: RedisLegacyClientType, client: RedisClientType) => Promise) { testUtils.testWithClient(title, client => fn(client.legacy(), client), GLOBAL.SERVERS.OPEN); diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 4cf7fc43de6..6ed008f8867 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -1,7 +1,7 @@ import COMMANDS from '../commands'; import { Command, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; import RedisClient, { RedisClientType, RedisClientOptions, RedisClientExtensions } from '.'; -import { EventEmitter } from 'events'; +import { EventEmitter } from 'node:events'; import { DoublyLinkedNode, DoublyLinkedList, SinglyLinkedList } from './linked-list'; import { TimeoutError } from '../errors'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; diff --git a/packages/client/lib/client/pub-sub.spec.ts b/packages/client/lib/client/pub-sub.spec.ts index 8b9f16732cb..65152909325 100644 --- a/packages/client/lib/client/pub-sub.spec.ts +++ b/packages/client/lib/client/pub-sub.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { PubSub, PubSubType } from './pub-sub'; describe('PubSub', () => { diff --git a/packages/client/lib/client/socket.spec.ts b/packages/client/lib/client/socket.spec.ts index ad874f06c76..20b238a3a38 100644 --- a/packages/client/lib/client/socket.spec.ts +++ b/packages/client/lib/client/socket.spec.ts @@ -1,6 +1,6 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { spy } from 'sinon'; -import { once } from 'events'; +import { once } from 'node:events'; import RedisSocket, { RedisSocketOptions } from './socket'; describe('Socket', () => { diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 86c99233933..93d128dbe14 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -1,6 +1,6 @@ -import { EventEmitter } from 'events'; -import * as net from 'net'; -import * as tls from 'tls'; +import { EventEmitter } from 'node:events'; +import * as net from 'node:net'; +import * as tls from 'node:tls'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError, ReconnectStrategyError } from '../errors'; import { setTimeout } from 'timers/promises'; import { RedisArgument } from '../RESP/types'; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 39d463bad59..19ce00735fa 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -1,8 +1,8 @@ import { RedisClusterClientOptions, RedisClusterOptions } from '.'; import { RootNodesUnavailableError } from '../errors'; import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; -import { types } from 'util'; -import { EventEmitter } from 'stream'; +import { types } from 'node:util'; +import { EventEmitter } from 'node:stream'; import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index 2b283a18b58..4a50f7f801a 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; // import RedisCluster from '.'; // import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 718e1198728..d52ad944975 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -2,7 +2,7 @@ import { RedisClientOptions, RedisClientType } from '../client'; import { CommandOptions } from '../client/commands-queue'; import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; -import { EventEmitter } from 'events'; +import { EventEmitter } from 'node:events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command'; @@ -16,14 +16,14 @@ interface ClusterCommander< S extends RedisScripts, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + // POLICIES extends CommandPolicies > extends CommanderConfig{ - commandOptions?: ClusterCommandOptions; + commandOptions?: ClusterCommandOptions; } export type RedisClusterClientOptions = Omit< RedisClientOptions, - keyof ClusterCommander + keyof ClusterCommander >; export interface RedisClusterOptions< @@ -32,8 +32,8 @@ export interface RedisClusterOptions< S extends RedisScripts = RedisScripts, RESP extends RespVersions = RespVersions, TYPE_MAPPING extends TypeMapping = TypeMapping, - POLICIES extends CommandPolicies = CommandPolicies -> extends ClusterCommander { + // POLICIES extends CommandPolicies = CommandPolicies +> extends ClusterCommander { /** * Should contain details for some of the cluster nodes that the client will use to discover * the "cluster topology". We recommend including details for at least 3 nodes here. @@ -68,9 +68,9 @@ export interface RedisClusterOptions< type WithCommands< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + // POLICIES extends CommandPolicies > = { - [P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING, POLICIES>; +[P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING, POLICIES>; }; export type RedisClusterType< @@ -79,8 +79,8 @@ export type RedisClusterType< S extends RedisScripts = {}, RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {}, - POLICIES extends CommandPolicies = {} -> = RedisCluster & WithCommands; + // POLICIES extends CommandPolicies = {} +> = RedisCluster & WithCommands; // & WithModules & WithFunctions & WithScripts export interface ClusterCommandOptions< diff --git a/packages/client/lib/commands/ACL_CAT.spec.ts b/packages/client/lib/commands/ACL_CAT.spec.ts index 0fc8b08b2fa..2ce9d7db922 100644 --- a/packages/client/lib/commands/ACL_CAT.spec.ts +++ b/packages/client/lib/commands/ACL_CAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_CAT from './ACL_CAT'; diff --git a/packages/client/lib/commands/ACL_DELUSER.spec.ts b/packages/client/lib/commands/ACL_DELUSER.spec.ts index bccd2ccdc5e..d6acbb22230 100644 --- a/packages/client/lib/commands/ACL_DELUSER.spec.ts +++ b/packages/client/lib/commands/ACL_DELUSER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_DELUSER from './ACL_DELUSER'; diff --git a/packages/client/lib/commands/ACL_DRYRUN.spec.ts b/packages/client/lib/commands/ACL_DRYRUN.spec.ts index 051e6a561da..519092e0114 100644 --- a/packages/client/lib/commands/ACL_DRYRUN.spec.ts +++ b/packages/client/lib/commands/ACL_DRYRUN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_DRYRUN from './ACL_DRYRUN'; diff --git a/packages/client/lib/commands/ACL_GENPASS.spec.ts b/packages/client/lib/commands/ACL_GENPASS.spec.ts index 7b489f1e9ec..44c1e167eb7 100644 --- a/packages/client/lib/commands/ACL_GENPASS.spec.ts +++ b/packages/client/lib/commands/ACL_GENPASS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_GENPASS from './ACL_GENPASS'; diff --git a/packages/client/lib/commands/ACL_GETUSER.spec.ts b/packages/client/lib/commands/ACL_GETUSER.spec.ts index 6a0948d6f07..47351571127 100644 --- a/packages/client/lib/commands/ACL_GETUSER.spec.ts +++ b/packages/client/lib/commands/ACL_GETUSER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_GETUSER from './ACL_GETUSER'; diff --git a/packages/client/lib/commands/ACL_LIST.spec.ts b/packages/client/lib/commands/ACL_LIST.spec.ts index 8b2d875bda1..b188cae30b0 100644 --- a/packages/client/lib/commands/ACL_LIST.spec.ts +++ b/packages/client/lib/commands/ACL_LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_LIST from './ACL_LIST'; diff --git a/packages/client/lib/commands/ACL_LOAD.spec.ts b/packages/client/lib/commands/ACL_LOAD.spec.ts index 66afcf356a7..68552164ce0 100644 --- a/packages/client/lib/commands/ACL_LOAD.spec.ts +++ b/packages/client/lib/commands/ACL_LOAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import ACL_LOAD from './ACL_LOAD'; diff --git a/packages/client/lib/commands/ACL_LOG.spec.ts b/packages/client/lib/commands/ACL_LOG.spec.ts index 8e66ea063aa..b85a7076f4a 100644 --- a/packages/client/lib/commands/ACL_LOG.spec.ts +++ b/packages/client/lib/commands/ACL_LOG.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_LOG from './ACL_LOG'; diff --git a/packages/client/lib/commands/ACL_LOG_RESET.spec.ts b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts index 7f3fbf1ade9..8849440c1a6 100644 --- a/packages/client/lib/commands/ACL_LOG_RESET.spec.ts +++ b/packages/client/lib/commands/ACL_LOG_RESET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ACL_LOG_RESET from './ACL_LOG_RESET'; diff --git a/packages/client/lib/commands/ACL_SAVE.spec.ts b/packages/client/lib/commands/ACL_SAVE.spec.ts index 065b75f93b6..1fe402867e7 100644 --- a/packages/client/lib/commands/ACL_SAVE.spec.ts +++ b/packages/client/lib/commands/ACL_SAVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import ACL_SAVE from './ACL_SAVE'; diff --git a/packages/client/lib/commands/ACL_SETUSER.spec.ts b/packages/client/lib/commands/ACL_SETUSER.spec.ts index 00032046641..10aea62ed02 100644 --- a/packages/client/lib/commands/ACL_SETUSER.spec.ts +++ b/packages/client/lib/commands/ACL_SETUSER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import ACL_SETUSER from './ACL_SETUSER'; diff --git a/packages/client/lib/commands/ACL_USERS.spec.ts b/packages/client/lib/commands/ACL_USERS.spec.ts index 925a42f8a82..2d433d4ec1e 100644 --- a/packages/client/lib/commands/ACL_USERS.spec.ts +++ b/packages/client/lib/commands/ACL_USERS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import ACL_USERS from './ACL_USERS'; diff --git a/packages/client/lib/commands/ACL_WHOAMI.spec.ts b/packages/client/lib/commands/ACL_WHOAMI.spec.ts index d4bad99dbd5..24a5cbd1d63 100644 --- a/packages/client/lib/commands/ACL_WHOAMI.spec.ts +++ b/packages/client/lib/commands/ACL_WHOAMI.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import ACL_WHOAMI from './ACL_WHOAMI'; diff --git a/packages/client/lib/commands/APPEND.spec.ts b/packages/client/lib/commands/APPEND.spec.ts index c85501f4a0c..ca18a00ac42 100644 --- a/packages/client/lib/commands/APPEND.spec.ts +++ b/packages/client/lib/commands/APPEND.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import APPEND from './APPEND'; diff --git a/packages/client/lib/commands/ASKING.spec.ts b/packages/client/lib/commands/ASKING.spec.ts index 661a5aa7c1d..bd83bec599f 100644 --- a/packages/client/lib/commands/ASKING.spec.ts +++ b/packages/client/lib/commands/ASKING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import ASKING from './ASKING'; describe('ASKING', () => { diff --git a/packages/client/lib/commands/AUTH.spec.ts b/packages/client/lib/commands/AUTH.spec.ts index 290ba936bf7..2da016ba873 100644 --- a/packages/client/lib/commands/AUTH.spec.ts +++ b/packages/client/lib/commands/AUTH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import AUTH from './AUTH'; describe('AUTH', () => { diff --git a/packages/client/lib/commands/BGREWRITEAOF.spec.ts b/packages/client/lib/commands/BGREWRITEAOF.spec.ts index b29e90634cb..5447fc70a79 100644 --- a/packages/client/lib/commands/BGREWRITEAOF.spec.ts +++ b/packages/client/lib/commands/BGREWRITEAOF.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BGREWRITEAOF from './BGREWRITEAOF'; diff --git a/packages/client/lib/commands/BGSAVE.spec.ts b/packages/client/lib/commands/BGSAVE.spec.ts index 51817cbc0fb..7944722dd56 100644 --- a/packages/client/lib/commands/BGSAVE.spec.ts +++ b/packages/client/lib/commands/BGSAVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BGSAVE from './BGSAVE'; diff --git a/packages/client/lib/commands/BITCOUNT.spec.ts b/packages/client/lib/commands/BITCOUNT.spec.ts index 6744a6014fd..ceb6476a31c 100644 --- a/packages/client/lib/commands/BITCOUNT.spec.ts +++ b/packages/client/lib/commands/BITCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITCOUNT from './BITCOUNT'; diff --git a/packages/client/lib/commands/BITFIELD.spec.ts b/packages/client/lib/commands/BITFIELD.spec.ts index 93ca665deb7..7f805755493 100644 --- a/packages/client/lib/commands/BITFIELD.spec.ts +++ b/packages/client/lib/commands/BITFIELD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITFIELD from './BITFIELD'; diff --git a/packages/client/lib/commands/BITFIELD_RO.spec.ts b/packages/client/lib/commands/BITFIELD_RO.spec.ts index 2857155a60f..0793100193f 100644 --- a/packages/client/lib/commands/BITFIELD_RO.spec.ts +++ b/packages/client/lib/commands/BITFIELD_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITFIELD_RO from './BITFIELD_RO'; diff --git a/packages/client/lib/commands/BITOP.spec.ts b/packages/client/lib/commands/BITOP.spec.ts index bb411c0f1a2..4df1782467f 100644 --- a/packages/client/lib/commands/BITOP.spec.ts +++ b/packages/client/lib/commands/BITOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITOP from './BITOP'; diff --git a/packages/client/lib/commands/BITPOS.spec.ts b/packages/client/lib/commands/BITPOS.spec.ts index 34e975ca03b..61940560057 100644 --- a/packages/client/lib/commands/BITPOS.spec.ts +++ b/packages/client/lib/commands/BITPOS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import BITPOS from './BITPOS'; diff --git a/packages/client/lib/commands/BLMOVE.spec.ts b/packages/client/lib/commands/BLMOVE.spec.ts index 27029e61612..0eca8c61005 100644 --- a/packages/client/lib/commands/BLMOVE.spec.ts +++ b/packages/client/lib/commands/BLMOVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLMOVE from './BLMOVE'; diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts index b47fb68ac4e..b40556b1e46 100644 --- a/packages/client/lib/commands/BLMPOP.spec.ts +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLMPOP from './BLMPOP'; diff --git a/packages/client/lib/commands/BLPOP.spec.ts b/packages/client/lib/commands/BLPOP.spec.ts index ca9dd76ce7c..4bcc08d0fc9 100644 --- a/packages/client/lib/commands/BLPOP.spec.ts +++ b/packages/client/lib/commands/BLPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BLPOP from './BLPOP'; diff --git a/packages/client/lib/commands/BRPOP.spec.ts b/packages/client/lib/commands/BRPOP.spec.ts index 3e61ff7581a..21631d763f4 100644 --- a/packages/client/lib/commands/BRPOP.spec.ts +++ b/packages/client/lib/commands/BRPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BRPOP from './BRPOP'; diff --git a/packages/client/lib/commands/BRPOPLPUSH.spec.ts b/packages/client/lib/commands/BRPOPLPUSH.spec.ts index d9f433707db..1f6dc48bfea 100644 --- a/packages/client/lib/commands/BRPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/BRPOPLPUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BRPOPLPUSH from './BRPOPLPUSH'; diff --git a/packages/client/lib/commands/BZMPOP.spec.ts b/packages/client/lib/commands/BZMPOP.spec.ts index dcd480c8720..554e6898d62 100644 --- a/packages/client/lib/commands/BZMPOP.spec.ts +++ b/packages/client/lib/commands/BZMPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZMPOP from './BZMPOP'; diff --git a/packages/client/lib/commands/BZPOPMAX.spec.ts b/packages/client/lib/commands/BZPOPMAX.spec.ts index 53c6187e4e0..1f0a4d44f07 100644 --- a/packages/client/lib/commands/BZPOPMAX.spec.ts +++ b/packages/client/lib/commands/BZPOPMAX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZPOPMAX from './BZPOPMAX'; diff --git a/packages/client/lib/commands/BZPOPMIN.spec.ts b/packages/client/lib/commands/BZPOPMIN.spec.ts index 96acf25a1e1..7f39f7d1896 100644 --- a/packages/client/lib/commands/BZPOPMIN.spec.ts +++ b/packages/client/lib/commands/BZPOPMIN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, BLOCKING_MIN_VALUE } from '../test-utils'; import BZPOPMIN from './BZPOPMIN'; diff --git a/packages/client/lib/commands/CLIENT_CACHING.spec.ts b/packages/client/lib/commands/CLIENT_CACHING.spec.ts index bf8e4ed12bf..34023f98922 100644 --- a/packages/client/lib/commands/CLIENT_CACHING.spec.ts +++ b/packages/client/lib/commands/CLIENT_CACHING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLIENT_CACHING from './CLIENT_CACHING'; describe('CLIENT CACHING', () => { diff --git a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts index bb9c24cd6f5..8975f1fee9c 100644 --- a/packages/client/lib/commands/CLIENT_GETNAME.spec.ts +++ b/packages/client/lib/commands/CLIENT_GETNAME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_GETNAME from './CLIENT_GETNAME'; diff --git a/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts b/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts index 057eb237129..5cfedf2a4e7 100644 --- a/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts +++ b/packages/client/lib/commands/CLIENT_GETREDIR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLIENT_GETREDIR from './CLIENT_GETREDIR'; describe('CLIENT GETREDIR', () => { diff --git a/packages/client/lib/commands/CLIENT_ID.spec.ts b/packages/client/lib/commands/CLIENT_ID.spec.ts index 28865a4ade7..7b51e6bd930 100644 --- a/packages/client/lib/commands/CLIENT_ID.spec.ts +++ b/packages/client/lib/commands/CLIENT_ID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_ID from './CLIENT_ID'; diff --git a/packages/client/lib/commands/CLIENT_INFO.spec.ts b/packages/client/lib/commands/CLIENT_INFO.spec.ts index ecc290d2f2c..0aba384aa3a 100644 --- a/packages/client/lib/commands/CLIENT_INFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLIENT_INFO from './CLIENT_INFO'; import testUtils, { GLOBAL } from '../test-utils'; diff --git a/packages/client/lib/commands/CLIENT_KILL.spec.ts b/packages/client/lib/commands/CLIENT_KILL.spec.ts index 28be6e12727..0685c46ba4a 100644 --- a/packages/client/lib/commands/CLIENT_KILL.spec.ts +++ b/packages/client/lib/commands/CLIENT_KILL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLIENT_KILL, { CLIENT_KILL_FILTERS } from './CLIENT_KILL'; describe('CLIENT KILL', () => { diff --git a/packages/client/lib/commands/CLIENT_LIST.spec.ts b/packages/client/lib/commands/CLIENT_LIST.spec.ts index 5da86aa2971..e967a8dc0ff 100644 --- a/packages/client/lib/commands/CLIENT_LIST.spec.ts +++ b/packages/client/lib/commands/CLIENT_LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLIENT_LIST from './CLIENT_LIST'; import testUtils, { GLOBAL } from '../test-utils'; diff --git a/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts b/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts index e87025a3b67..5de4dfd7604 100644 --- a/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts +++ b/packages/client/lib/commands/CLIENT_NO-EVICT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_NO_EVICT from './CLIENT_NO-EVICT'; diff --git a/packages/client/lib/commands/CLIENT_PAUSE.spec.ts b/packages/client/lib/commands/CLIENT_PAUSE.spec.ts index 8cf414410fd..a30f9075072 100644 --- a/packages/client/lib/commands/CLIENT_PAUSE.spec.ts +++ b/packages/client/lib/commands/CLIENT_PAUSE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_PAUSE from './CLIENT_PAUSE'; diff --git a/packages/client/lib/commands/CLIENT_SETNAME.spec.ts b/packages/client/lib/commands/CLIENT_SETNAME.spec.ts index d9af526bb46..8e6b914791d 100644 --- a/packages/client/lib/commands/CLIENT_SETNAME.spec.ts +++ b/packages/client/lib/commands/CLIENT_SETNAME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_SETNAME from './CLIENT_SETNAME'; diff --git a/packages/client/lib/commands/CLIENT_TRACKING.spec.ts b/packages/client/lib/commands/CLIENT_TRACKING.spec.ts index 0a8ea58e084..98fe091fb1b 100644 --- a/packages/client/lib/commands/CLIENT_TRACKING.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_TRACKING from './CLIENT_TRACKING'; diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts index beee6649f7d..0921a9141fe 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO'; import { RESP_TYPES } from '../RESP/decoder'; diff --git a/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts b/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts index 1c59c3b82c6..bddf3ca0f02 100644 --- a/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts +++ b/packages/client/lib/commands/CLIENT_UNPAUSE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_UNPAUSE from './CLIENT_UNPAUSE'; diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts index 4faed754227..56f7b2a85e7 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_ADDSLOTS from './CLUSTER_ADDSLOTS'; describe('CLUSTER ADDSLOTS', () => { diff --git a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts index 496d52bd592..6af6f586e99 100644 --- a/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_ADDSLOTSRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import CLUSTER_ADDSLOTSRANGE from './CLUSTER_ADDSLOTSRANGE'; diff --git a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts index 4c064a08127..d21bc47c5d0 100644 --- a/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts +++ b/packages/client/lib/commands/CLUSTER_BUMPEPOCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_BUMPEPOCH from './CLUSTER_BUMPEPOCH'; diff --git a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts index 68b3cde620b..93c2aca7804 100644 --- a/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_COUNT_FAILURE_REPORTS from './CLUSTER_COUNT-FAILURE-REPORTS'; diff --git a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts index 2faa95c0804..180a120e153 100644 --- a/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_COUNTKEYSINSLOT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_COUNTKEYSINSLOT from './CLUSTER_COUNTKEYSINSLOT'; diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts index 85a188c31e0..59e40217b9c 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_DELSLOTS from './CLUSTER_DELSLOTS'; describe('CLUSTER DELSLOTS', () => { diff --git a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts index 38ee60b9178..2615f394b87 100644 --- a/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_DELSLOTSRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_DELSLOTSRANGE from './CLUSTER_DELSLOTSRANGE'; describe('CLUSTER DELSLOTSRANGE', () => { diff --git a/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts b/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts index 542e529f46b..ac18a9a7f8f 100644 --- a/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FAILOVER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_FAILOVER, { FAILOVER_MODES } from './CLUSTER_FAILOVER'; describe('CLUSTER FAILOVER', () => { diff --git a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts index 7ea2c33ccaf..fbc4346136d 100644 --- a/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FLUSHSLOTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_FLUSHSLOTS from './CLUSTER_FLUSHSLOTS'; describe('CLUSTER FLUSHSLOTS', () => { diff --git a/packages/client/lib/commands/CLUSTER_FORGET.spec.ts b/packages/client/lib/commands/CLUSTER_FORGET.spec.ts index 5d144ac1091..a9a923b01ee 100644 --- a/packages/client/lib/commands/CLUSTER_FORGET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_FORGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_FORGET from './CLUSTER_FORGET'; describe('CLUSTER FORGET', () => { diff --git a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts index cba7a384eed..f1a4e2c3bcc 100644 --- a/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_GETKEYSINSLOT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_GETKEYSINSLOT from './CLUSTER_GETKEYSINSLOT'; diff --git a/packages/client/lib/commands/CLUSTER_INFO.spec.ts b/packages/client/lib/commands/CLUSTER_INFO.spec.ts index 53c5b910920..e20b90a3011 100644 --- a/packages/client/lib/commands/CLUSTER_INFO.spec.ts +++ b/packages/client/lib/commands/CLUSTER_INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments, transformReply } from './CLUSTER_INFO'; diff --git a/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts index 1af795be5e0..d582c616cd1 100644 --- a/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_KEYSLOT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; diff --git a/packages/client/lib/commands/CLUSTER_LINKS.spec.ts b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts index c1490663935..d94231634e0 100644 --- a/packages/client/lib/commands/CLUSTER_LINKS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_LINKS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_LINKS from './CLUSTER_LINKS'; diff --git a/packages/client/lib/commands/CLUSTER_MEET.spec.ts b/packages/client/lib/commands/CLUSTER_MEET.spec.ts index 283c996cf8a..0b678f009f7 100644 --- a/packages/client/lib/commands/CLUSTER_MEET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_MEET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_MEET from './CLUSTER_MEET'; describe('CLUSTER MEET', () => { diff --git a/packages/client/lib/commands/CLUSTER_MYID.spec.ts b/packages/client/lib/commands/CLUSTER_MYID.spec.ts index 01282fadd8b..74540e98ab7 100644 --- a/packages/client/lib/commands/CLUSTER_MYID.spec.ts +++ b/packages/client/lib/commands/CLUSTER_MYID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_MYID from './CLUSTER_MYID'; diff --git a/packages/client/lib/commands/CLUSTER_NODES.spec.ts b/packages/client/lib/commands/CLUSTER_NODES.spec.ts index 5c25ab209b2..99db17a23e6 100644 --- a/packages/client/lib/commands/CLUSTER_NODES.spec.ts +++ b/packages/client/lib/commands/CLUSTER_NODES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_NODES from './CLUSTER_NODES'; diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts index 18b9fed5e47..5e1a0341ca8 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; diff --git a/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts b/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts index bb6335a7117..80935385a88 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; describe('CLUSTER REPLICATE', () => { diff --git a/packages/client/lib/commands/CLUSTER_RESET.spec.ts b/packages/client/lib/commands/CLUSTER_RESET.spec.ts index c9186ca7b11..190bdaf69e1 100644 --- a/packages/client/lib/commands/CLUSTER_RESET.spec.ts +++ b/packages/client/lib/commands/CLUSTER_RESET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_RESET from './CLUSTER_RESET'; describe('CLUSTER RESET', () => { diff --git a/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts b/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts index d49b32a426e..ece8087e8e4 100644 --- a/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SAVECONFIG.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG'; diff --git a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts index b4c26b659c7..39cf026d0ef 100644 --- a/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SET-CONFIG-EPOCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH'; describe('CLUSTER SET-CONFIG-EPOCH', () => { diff --git a/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts b/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts index cbdbaa89296..7bce6d74b4a 100644 --- a/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SETSLOT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CLUSTER_SETSLOT, { CLUSTER_SLOT_STATES } from './CLUSTER_SETSLOT'; describe('CLUSTER SETSLOT', () => { diff --git a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts index 9010361c78b..198dfdc6c1b 100644 --- a/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_SLOTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLUSTER_SLOTS from './CLUSTER_SLOTS'; diff --git a/packages/client/lib/commands/COMMAND.spec.ts b/packages/client/lib/commands/COMMAND.spec.ts index ed82d5c5ecb..860ffc30685 100644 --- a/packages/client/lib/commands/COMMAND.spec.ts +++ b/packages/client/lib/commands/COMMAND.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../test-utils'; // import { transformArguments } from './COMMAND'; // import { assertPingCommand } from './COMMAND_INFO.spec'; diff --git a/packages/client/lib/commands/COMMAND_COUNT.spec.ts b/packages/client/lib/commands/COMMAND_COUNT.spec.ts index 63b3af4866f..05bd29f223c 100644 --- a/packages/client/lib/commands/COMMAND_COUNT.spec.ts +++ b/packages/client/lib/commands/COMMAND_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import COMMAND_COUNT from './COMMAND_COUNT'; diff --git a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts index a1a7bd2fc26..d5b9f60790d 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import COMMAND_GETKEYS from './COMMAND_GETKEYS'; diff --git a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts index 8d16ad501c6..49652762d65 100644 --- a/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts +++ b/packages/client/lib/commands/COMMAND_GETKEYSANDFLAGS.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../test-utils'; // import { transformArguments } from './COMMAND_GETKEYSANDFLAGS'; diff --git a/packages/client/lib/commands/COMMAND_INFO.spec.ts b/packages/client/lib/commands/COMMAND_INFO.spec.ts index fb9603ea96d..fd8c22ae803 100644 --- a/packages/client/lib/commands/COMMAND_INFO.spec.ts +++ b/packages/client/lib/commands/COMMAND_INFO.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../test-utils'; // import { transformArguments } from './COMMAND_INFO'; // import { CommandCategories, CommandFlags, CommandReply } from './generic-transformers'; diff --git a/packages/client/lib/commands/COMMAND_LIST.spec.ts b/packages/client/lib/commands/COMMAND_LIST.spec.ts index 0cf0cd3b60d..266dda4198d 100644 --- a/packages/client/lib/commands/COMMAND_LIST.spec.ts +++ b/packages/client/lib/commands/COMMAND_LIST.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import testUtils, { GLOBAL } from '../test-utils'; // import { transformArguments, FilterBy } from './COMMAND_LIST'; diff --git a/packages/client/lib/commands/CONFIG_GET.spec.ts b/packages/client/lib/commands/CONFIG_GET.spec.ts index ae65092e4f7..94bb2fadcb9 100644 --- a/packages/client/lib/commands/CONFIG_GET.spec.ts +++ b/packages/client/lib/commands/CONFIG_GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_GET from './CONFIG_GET'; diff --git a/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts b/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts index 00336dcf515..c0699e182fc 100644 --- a/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts +++ b/packages/client/lib/commands/CONFIG_RESETSTAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CONFIG_RESETSTAT from './CONFIG_RESETSTAT'; describe('CONFIG RESETSTAT', () => { diff --git a/packages/client/lib/commands/CONFIG_REWRITE.spec.ts b/packages/client/lib/commands/CONFIG_REWRITE.spec.ts index a7a0af85e61..d612ae216bc 100644 --- a/packages/client/lib/commands/CONFIG_REWRITE.spec.ts +++ b/packages/client/lib/commands/CONFIG_REWRITE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import CONFIG_REWRITE from './CONFIG_REWRITE'; describe('CONFIG REWRITE', () => { diff --git a/packages/client/lib/commands/CONFIG_SET.spec.ts b/packages/client/lib/commands/CONFIG_SET.spec.ts index 86d590072c8..060183f58d1 100644 --- a/packages/client/lib/commands/CONFIG_SET.spec.ts +++ b/packages/client/lib/commands/CONFIG_SET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_SET from './CONFIG_SET'; diff --git a/packages/client/lib/commands/COPY.spec.ts b/packages/client/lib/commands/COPY.spec.ts index 44649d3c783..c4c26c30dc2 100644 --- a/packages/client/lib/commands/COPY.spec.ts +++ b/packages/client/lib/commands/COPY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import COPY from './COPY'; diff --git a/packages/client/lib/commands/DBSIZE.spec.ts b/packages/client/lib/commands/DBSIZE.spec.ts index cb2d72aae79..bd668d166e7 100644 --- a/packages/client/lib/commands/DBSIZE.spec.ts +++ b/packages/client/lib/commands/DBSIZE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DBSIZE from './DBSIZE'; diff --git a/packages/client/lib/commands/DECR.spec.ts b/packages/client/lib/commands/DECR.spec.ts index aa7f2ad5c0a..80d6c8eb55e 100644 --- a/packages/client/lib/commands/DECR.spec.ts +++ b/packages/client/lib/commands/DECR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DECR from './DECR'; diff --git a/packages/client/lib/commands/DECRBY.spec.ts b/packages/client/lib/commands/DECRBY.spec.ts index 60c18c4b06c..fc0c1033187 100644 --- a/packages/client/lib/commands/DECRBY.spec.ts +++ b/packages/client/lib/commands/DECRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DECRBY from './DECRBY'; diff --git a/packages/client/lib/commands/DEL.spec.ts b/packages/client/lib/commands/DEL.spec.ts index 6ec8ed8021a..caac8ac13b5 100644 --- a/packages/client/lib/commands/DEL.spec.ts +++ b/packages/client/lib/commands/DEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEL from './DEL'; diff --git a/packages/client/lib/commands/DISCARD.spec.ts b/packages/client/lib/commands/DISCARD.spec.ts index b08daecea6a..76e0abd57af 100644 --- a/packages/client/lib/commands/DISCARD.spec.ts +++ b/packages/client/lib/commands/DISCARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import DISCARD from './DISCARD'; describe('DISCARD', () => { diff --git a/packages/client/lib/commands/DUMP.spec.ts b/packages/client/lib/commands/DUMP.spec.ts index 94cc11ed513..15be3fae086 100644 --- a/packages/client/lib/commands/DUMP.spec.ts +++ b/packages/client/lib/commands/DUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('DUMP', () => { diff --git a/packages/client/lib/commands/ECHO.spec.ts b/packages/client/lib/commands/ECHO.spec.ts index 04ce759b1f8..c0d0725282c 100644 --- a/packages/client/lib/commands/ECHO.spec.ts +++ b/packages/client/lib/commands/ECHO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ECHO from './ECHO'; diff --git a/packages/client/lib/commands/EVAL.spec.ts b/packages/client/lib/commands/EVAL.spec.ts index e131cd79abf..2aea64e0991 100644 --- a/packages/client/lib/commands/EVAL.spec.ts +++ b/packages/client/lib/commands/EVAL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EVAL from './EVAL'; diff --git a/packages/client/lib/commands/EVALSHA.spec.ts b/packages/client/lib/commands/EVALSHA.spec.ts index ce08ec89c87..81d3a0ec2b0 100644 --- a/packages/client/lib/commands/EVALSHA.spec.ts +++ b/packages/client/lib/commands/EVALSHA.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import EVALSHA from './EVALSHA'; describe('EVALSHA', () => { diff --git a/packages/client/lib/commands/EVALSHA_RO.spec.ts b/packages/client/lib/commands/EVALSHA_RO.spec.ts index 0afd5d18037..20b4a27e0d1 100644 --- a/packages/client/lib/commands/EVALSHA_RO.spec.ts +++ b/packages/client/lib/commands/EVALSHA_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import EVALSHA_RO from './EVALSHA_RO'; diff --git a/packages/client/lib/commands/EVAL_RO.spec.ts b/packages/client/lib/commands/EVAL_RO.spec.ts index 06ae6c64096..3f071e80681 100644 --- a/packages/client/lib/commands/EVAL_RO.spec.ts +++ b/packages/client/lib/commands/EVAL_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EVAL_RO from './EVAL_RO'; diff --git a/packages/client/lib/commands/EXISTS.spec.ts b/packages/client/lib/commands/EXISTS.spec.ts index bc5f564a45f..695795697f1 100644 --- a/packages/client/lib/commands/EXISTS.spec.ts +++ b/packages/client/lib/commands/EXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXISTS from './EXISTS'; diff --git a/packages/client/lib/commands/EXPIRE.spec.ts b/packages/client/lib/commands/EXPIRE.spec.ts index add2040eb31..817e37cca45 100644 --- a/packages/client/lib/commands/EXPIRE.spec.ts +++ b/packages/client/lib/commands/EXPIRE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXPIRE from './EXPIRE'; diff --git a/packages/client/lib/commands/EXPIREAT.spec.ts b/packages/client/lib/commands/EXPIREAT.spec.ts index 730d925d998..31efdcea398 100644 --- a/packages/client/lib/commands/EXPIREAT.spec.ts +++ b/packages/client/lib/commands/EXPIREAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXPIREAT from './EXPIREAT'; diff --git a/packages/client/lib/commands/EXPIRETIME.spec.ts b/packages/client/lib/commands/EXPIRETIME.spec.ts index 8936c7638dc..3c202d2427f 100644 --- a/packages/client/lib/commands/EXPIRETIME.spec.ts +++ b/packages/client/lib/commands/EXPIRETIME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXPIRETIME from './EXPIRETIME'; diff --git a/packages/client/lib/commands/FAILOVER.spec.ts b/packages/client/lib/commands/FAILOVER.spec.ts index f97663e419b..96602caff91 100644 --- a/packages/client/lib/commands/FAILOVER.spec.ts +++ b/packages/client/lib/commands/FAILOVER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import FAILOVER from './FAILOVER'; describe('FAILOVER', () => { diff --git a/packages/client/lib/commands/FCALL.spec.ts b/packages/client/lib/commands/FCALL.spec.ts index 45016e2702d..06616ba1db3 100644 --- a/packages/client/lib/commands/FCALL.spec.ts +++ b/packages/client/lib/commands/FCALL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; import FCALL from './FCALL'; diff --git a/packages/client/lib/commands/FCALL_RO.spec.ts b/packages/client/lib/commands/FCALL_RO.spec.ts index ec43a97c6c5..114430eb588 100644 --- a/packages/client/lib/commands/FCALL_RO.spec.ts +++ b/packages/client/lib/commands/FCALL_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; import FCALL_RO from './FCALL_RO'; diff --git a/packages/client/lib/commands/FLUSHALL.spec.ts b/packages/client/lib/commands/FLUSHALL.spec.ts index 3cef3798a68..63ad38dd7de 100644 --- a/packages/client/lib/commands/FLUSHALL.spec.ts +++ b/packages/client/lib/commands/FLUSHALL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FLUSHALL, { REDIS_FLUSH_MODES } from './FLUSHALL'; diff --git a/packages/client/lib/commands/FLUSHDB.spec.ts b/packages/client/lib/commands/FLUSHDB.spec.ts index 93b328eda69..ad09ecfc945 100644 --- a/packages/client/lib/commands/FLUSHDB.spec.ts +++ b/packages/client/lib/commands/FLUSHDB.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FLUSHDB from './FLUSHDB'; import { REDIS_FLUSH_MODES } from './FLUSHALL'; diff --git a/packages/client/lib/commands/FUNCTION_DELETE.spec.ts b/packages/client/lib/commands/FUNCTION_DELETE.spec.ts index a763686d15b..1172e84b956 100644 --- a/packages/client/lib/commands/FUNCTION_DELETE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_DELETE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_DELETE from './FUNCTION_DELETE'; import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; diff --git a/packages/client/lib/commands/FUNCTION_DUMP.spec.ts b/packages/client/lib/commands/FUNCTION_DUMP.spec.ts index fe6a44c6769..4d4e885e4f2 100644 --- a/packages/client/lib/commands/FUNCTION_DUMP.spec.ts +++ b/packages/client/lib/commands/FUNCTION_DUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_DUMP from './FUNCTION_DUMP'; diff --git a/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts b/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts index 0f3c64cf7cc..5601784ed6a 100644 --- a/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts +++ b/packages/client/lib/commands/FUNCTION_FLUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_FLUSH from './FUNCTION_FLUSH'; diff --git a/packages/client/lib/commands/FUNCTION_KILL.spec.ts b/packages/client/lib/commands/FUNCTION_KILL.spec.ts index a79ae9515cf..be231e41180 100644 --- a/packages/client/lib/commands/FUNCTION_KILL.spec.ts +++ b/packages/client/lib/commands/FUNCTION_KILL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils from '../test-utils'; import FUNCTION_KILL from './FUNCTION_KILL'; diff --git a/packages/client/lib/commands/FUNCTION_LIST.spec.ts b/packages/client/lib/commands/FUNCTION_LIST.spec.ts index 52c0ea9b63b..e269d3150b6 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_LIST from './FUNCTION_LIST'; import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; diff --git a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts index 528062eba66..8ff40582460 100644 --- a/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LIST_WITHCODE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_LIST_WITHCODE from './FUNCTION_LIST_WITHCODE'; import { MATH_FUNCTION, loadMathFunction } from './FUNCTION_LOAD.spec'; diff --git a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts index 61246c45235..a739d8f7f46 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_LOAD from './FUNCTION_LOAD'; import { RedisClientType } from '../client'; diff --git a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts index 09f46b32db2..465e99b6104 100644 --- a/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts +++ b/packages/client/lib/commands/FUNCTION_RESTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FUNCTION_RESTORE from './FUNCTION_RESTORE'; import { RESP_TYPES } from '../RESP/decoder'; diff --git a/packages/client/lib/commands/FUNCTION_STATS.spec.ts b/packages/client/lib/commands/FUNCTION_STATS.spec.ts index c67175a6222..76c1ddafc18 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.spec.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.spec.ts @@ -1,5 +1,5 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; +// import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; // import { transformArguments } from './FUNCTION_STATS'; // describe('FUNCTION STATS', () => { diff --git a/packages/client/lib/commands/GEOADD.spec.ts b/packages/client/lib/commands/GEOADD.spec.ts index 3b9584aed0a..14195ed289c 100644 --- a/packages/client/lib/commands/GEOADD.spec.ts +++ b/packages/client/lib/commands/GEOADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOADD from './GEOADD'; diff --git a/packages/client/lib/commands/GEODIST.spec.ts b/packages/client/lib/commands/GEODIST.spec.ts index 2e0af2a9575..eb5a1ef801e 100644 --- a/packages/client/lib/commands/GEODIST.spec.ts +++ b/packages/client/lib/commands/GEODIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEODIST from './GEODIST'; diff --git a/packages/client/lib/commands/GEOHASH.spec.ts b/packages/client/lib/commands/GEOHASH.spec.ts index 0d575b487ab..8efe55d89b6 100644 --- a/packages/client/lib/commands/GEOHASH.spec.ts +++ b/packages/client/lib/commands/GEOHASH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOHASH from './GEOHASH'; diff --git a/packages/client/lib/commands/GEOPOS.spec.ts b/packages/client/lib/commands/GEOPOS.spec.ts index 297faba490b..20ad5c5c942 100644 --- a/packages/client/lib/commands/GEOPOS.spec.ts +++ b/packages/client/lib/commands/GEOPOS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOPOS from './GEOPOS'; diff --git a/packages/client/lib/commands/GEORADIUS.spec.ts b/packages/client/lib/commands/GEORADIUS.spec.ts index 28975864877..533e48f6898 100644 --- a/packages/client/lib/commands/GEORADIUS.spec.ts +++ b/packages/client/lib/commands/GEORADIUS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUS from './GEORADIUS'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts index b44a649bcea..57349a79acb 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts index 47e4dabbbcc..abf10013973 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUSBYMEMBER_RO from './GEORADIUSBYMEMBER_RO'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts index 166088495e1..bcf91266365 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUSBYMEMBER_RO_WITH from './GEORADIUSBYMEMBER_RO_WITH'; import { CommandArguments } from '../RESP/types'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts index 6eab34211a7..3d44060f205 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUSBYMEMBER_STORE from './GEORADIUSBYMEMBER_STORE'; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts index 3160c65cfb8..ffe3b2efff3 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUSBYMEMBER_WITH from './GEORADIUSBYMEMBER_WITH'; import { CommandArguments } from '../RESP/types'; diff --git a/packages/client/lib/commands/GEORADIUS_RO.spec.ts b/packages/client/lib/commands/GEORADIUS_RO.spec.ts index 6f6aeb80e67..43a2ef1d583 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUS_RO from './GEORADIUS_RO'; diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts index 639b1917028..cb0540d8a18 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUS_RO_WITH from './GEORADIUS_RO_WITH'; import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; diff --git a/packages/client/lib/commands/GEORADIUS_STORE.spec.ts b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts index 3fff9bc43dc..04a7d28aa95 100644 --- a/packages/client/lib/commands/GEORADIUS_STORE.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUS_STORE from './GEORADIUS_STORE'; diff --git a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts index 2219aa8490e..bdbfc9c1f3a 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEORADIUS_WITH from './GEORADIUS_WITH'; import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; diff --git a/packages/client/lib/commands/GEOSEARCH.spec.ts b/packages/client/lib/commands/GEOSEARCH.spec.ts index 7f06d646b18..49f076880a6 100644 --- a/packages/client/lib/commands/GEOSEARCH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOSEARCH from './GEOSEARCH'; diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts index 6b270af8dca..c66d3e8e45e 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOSEARCHSTORE from './GEOSEARCHSTORE'; diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts index a01f47d287a..e27fb295aaf 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GEOSEARCH_WITH, { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; import { CommandArguments } from '../RESP/types'; diff --git a/packages/client/lib/commands/GET.spec.ts b/packages/client/lib/commands/GET.spec.ts index 9e131694b11..4bd74183222 100644 --- a/packages/client/lib/commands/GET.spec.ts +++ b/packages/client/lib/commands/GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GET from './GET'; diff --git a/packages/client/lib/commands/GETBIT.spec.ts b/packages/client/lib/commands/GETBIT.spec.ts index 5dbab538c1b..ac39222b918 100644 --- a/packages/client/lib/commands/GETBIT.spec.ts +++ b/packages/client/lib/commands/GETBIT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GETBIT from './GETBIT'; diff --git a/packages/client/lib/commands/GETDEL.spec.ts b/packages/client/lib/commands/GETDEL.spec.ts index cbb7553cfeb..311f15e554d 100644 --- a/packages/client/lib/commands/GETDEL.spec.ts +++ b/packages/client/lib/commands/GETDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GETDEL from './GETDEL'; diff --git a/packages/client/lib/commands/GETEX.spec.ts b/packages/client/lib/commands/GETEX.spec.ts index 3bc0a5e03b9..302d034b961 100644 --- a/packages/client/lib/commands/GETEX.spec.ts +++ b/packages/client/lib/commands/GETEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GETEX from './GETEX'; diff --git a/packages/client/lib/commands/GETRANGE.spec.ts b/packages/client/lib/commands/GETRANGE.spec.ts index 1a31e1a76f0..2aac1ca16d9 100644 --- a/packages/client/lib/commands/GETRANGE.spec.ts +++ b/packages/client/lib/commands/GETRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GETRANGE from './GETRANGE'; diff --git a/packages/client/lib/commands/GETSET.spec.ts b/packages/client/lib/commands/GETSET.spec.ts index f52c2f29293..6583ec34f75 100644 --- a/packages/client/lib/commands/GETSET.spec.ts +++ b/packages/client/lib/commands/GETSET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GETSET from './GETSET'; diff --git a/packages/client/lib/commands/HDEL.spec.ts b/packages/client/lib/commands/HDEL.spec.ts index c87b20397ee..9f69485d9fe 100644 --- a/packages/client/lib/commands/HDEL.spec.ts +++ b/packages/client/lib/commands/HDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HDEL from './HDEL'; diff --git a/packages/client/lib/commands/HELLO.spec.ts b/packages/client/lib/commands/HELLO.spec.ts index 0a60c7ae69f..a0f088a4ba6 100644 --- a/packages/client/lib/commands/HELLO.spec.ts +++ b/packages/client/lib/commands/HELLO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HELLO from './HELLO'; diff --git a/packages/client/lib/commands/HEXISTS.spec.ts b/packages/client/lib/commands/HEXISTS.spec.ts index 0e0e82fa21b..69ca6fa765f 100644 --- a/packages/client/lib/commands/HEXISTS.spec.ts +++ b/packages/client/lib/commands/HEXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HEXISTS from './HEXISTS'; diff --git a/packages/client/lib/commands/HGET.spec.ts b/packages/client/lib/commands/HGET.spec.ts index 33824d903a1..397f22b5604 100644 --- a/packages/client/lib/commands/HGET.spec.ts +++ b/packages/client/lib/commands/HGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HGET from './HGET'; diff --git a/packages/client/lib/commands/HGETALL.spec.ts b/packages/client/lib/commands/HGETALL.spec.ts index 28e1dacf834..93d122bae07 100644 --- a/packages/client/lib/commands/HGETALL.spec.ts +++ b/packages/client/lib/commands/HGETALL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('HGETALL', () => { diff --git a/packages/client/lib/commands/HINCRBY.spec.ts b/packages/client/lib/commands/HINCRBY.spec.ts index 263f841e3f8..7718fe955eb 100644 --- a/packages/client/lib/commands/HINCRBY.spec.ts +++ b/packages/client/lib/commands/HINCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HINCRBY from './HINCRBY'; diff --git a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts index 56754ea2cf0..6c265dc6d10 100644 --- a/packages/client/lib/commands/HINCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/HINCRBYFLOAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HINCRBYFLOAT from './HINCRBYFLOAT'; diff --git a/packages/client/lib/commands/HKEYS.spec.ts b/packages/client/lib/commands/HKEYS.spec.ts index 080bfa46706..dada7b4d6fd 100644 --- a/packages/client/lib/commands/HKEYS.spec.ts +++ b/packages/client/lib/commands/HKEYS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HKEYS from './HKEYS'; diff --git a/packages/client/lib/commands/HLEN.spec.ts b/packages/client/lib/commands/HLEN.spec.ts index a0d804dff73..2457a261299 100644 --- a/packages/client/lib/commands/HLEN.spec.ts +++ b/packages/client/lib/commands/HLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HLEN from './HLEN'; diff --git a/packages/client/lib/commands/HMGET.spec.ts b/packages/client/lib/commands/HMGET.spec.ts index e21f67e2c61..99d94a6d375 100644 --- a/packages/client/lib/commands/HMGET.spec.ts +++ b/packages/client/lib/commands/HMGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HMGET from './HMGET'; diff --git a/packages/client/lib/commands/HRANDFIELD.spec.ts b/packages/client/lib/commands/HRANDFIELD.spec.ts index 492733c5834..33f2d281803 100644 --- a/packages/client/lib/commands/HRANDFIELD.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HRANDFIELD from './HRANDFIELD'; diff --git a/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts index 7b38d61695c..99788dc4962 100644 --- a/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts +++ b/packages/client/lib/commands/HRANDFIELD_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HRANDFIELD_COUNT from './HRANDFIELD_COUNT'; diff --git a/packages/client/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts index 0a3dfd19be9..463d557f743 100644 --- a/packages/client/lib/commands/HSCAN.spec.ts +++ b/packages/client/lib/commands/HSCAN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HSCAN from './HSCAN'; diff --git a/packages/client/lib/commands/HSET.spec.ts b/packages/client/lib/commands/HSET.spec.ts index 093edee6d22..eb5fdcd9b32 100644 --- a/packages/client/lib/commands/HSET.spec.ts +++ b/packages/client/lib/commands/HSET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HSET from './HSET'; diff --git a/packages/client/lib/commands/HSETNX.spec.ts b/packages/client/lib/commands/HSETNX.spec.ts index 2e39edc81ff..522732624e1 100644 --- a/packages/client/lib/commands/HSETNX.spec.ts +++ b/packages/client/lib/commands/HSETNX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HSETNX from './HSETNX'; diff --git a/packages/client/lib/commands/HSTRLEN.spec.ts b/packages/client/lib/commands/HSTRLEN.spec.ts index 98d96454186..59b737b692b 100644 --- a/packages/client/lib/commands/HSTRLEN.spec.ts +++ b/packages/client/lib/commands/HSTRLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HSTRLEN from './HSTRLEN'; diff --git a/packages/client/lib/commands/HVALS.spec.ts b/packages/client/lib/commands/HVALS.spec.ts index ce450042ecb..922aa588137 100644 --- a/packages/client/lib/commands/HVALS.spec.ts +++ b/packages/client/lib/commands/HVALS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import HVALS from './HVALS'; diff --git a/packages/client/lib/commands/INCR.spec.ts b/packages/client/lib/commands/INCR.spec.ts index 76a849aa4c2..67129760245 100644 --- a/packages/client/lib/commands/INCR.spec.ts +++ b/packages/client/lib/commands/INCR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import INCR from './INCR'; diff --git a/packages/client/lib/commands/INCRBY.spec.ts b/packages/client/lib/commands/INCRBY.spec.ts index 08c84a437b3..d66c01acce5 100644 --- a/packages/client/lib/commands/INCRBY.spec.ts +++ b/packages/client/lib/commands/INCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import INCRBY from './INCRBY'; diff --git a/packages/client/lib/commands/INCRBYFLOAT.spec.ts b/packages/client/lib/commands/INCRBYFLOAT.spec.ts index 79daac612ea..8bdd9c332de 100644 --- a/packages/client/lib/commands/INCRBYFLOAT.spec.ts +++ b/packages/client/lib/commands/INCRBYFLOAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import INCRBYFLOAT from './INCRBYFLOAT'; diff --git a/packages/client/lib/commands/INFO.spec.ts b/packages/client/lib/commands/INFO.spec.ts index 118682c7da1..f59ce26168a 100644 --- a/packages/client/lib/commands/INFO.spec.ts +++ b/packages/client/lib/commands/INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { transformArguments } from './INFO'; describe('INFO', () => { diff --git a/packages/client/lib/commands/KEYS.spec.ts b/packages/client/lib/commands/KEYS.spec.ts index 5827fa14f67..46f8a3cb0b2 100644 --- a/packages/client/lib/commands/KEYS.spec.ts +++ b/packages/client/lib/commands/KEYS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('KEYS', () => { diff --git a/packages/client/lib/commands/LASTSAVE.spec.ts b/packages/client/lib/commands/LASTSAVE.spec.ts index 224ad364d9b..74cf30705fa 100644 --- a/packages/client/lib/commands/LASTSAVE.spec.ts +++ b/packages/client/lib/commands/LASTSAVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LASTSAVE from './LASTSAVE'; diff --git a/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts b/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts index 67446270be3..00eabfb4cb3 100644 --- a/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts +++ b/packages/client/lib/commands/LATENCY_DOCTOR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LATENCY_DOCTOR from './LATENCY_DOCTOR'; diff --git a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts index f4a3c668965..55d98d38234 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LATENCY_GRAPH from './LATENCY_GRAPH'; diff --git a/packages/client/lib/commands/LATENCY_LATEST.spec.ts b/packages/client/lib/commands/LATENCY_LATEST.spec.ts index 0fe8085ef66..58b3a6de64d 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.spec.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LATENCY_LATEST from './LATENCY_LATEST'; diff --git a/packages/client/lib/commands/LCS.spec.ts b/packages/client/lib/commands/LCS.spec.ts index b24ba2c6f22..ff9d63db1b1 100644 --- a/packages/client/lib/commands/LCS.spec.ts +++ b/packages/client/lib/commands/LCS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LCS from './LCS'; diff --git a/packages/client/lib/commands/LCS_IDX.spec.ts b/packages/client/lib/commands/LCS_IDX.spec.ts index c948fa3eb6c..2f60a205faa 100644 --- a/packages/client/lib/commands/LCS_IDX.spec.ts +++ b/packages/client/lib/commands/LCS_IDX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LCS_IDX from './LCS_IDX'; diff --git a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts index 784ece8a616..39ba17e8f2c 100644 --- a/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts +++ b/packages/client/lib/commands/LCS_IDX_WITHMATCHLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; diff --git a/packages/client/lib/commands/LCS_LEN.spec.ts b/packages/client/lib/commands/LCS_LEN.spec.ts index 0ad10b3ed82..9dc163a68a9 100644 --- a/packages/client/lib/commands/LCS_LEN.spec.ts +++ b/packages/client/lib/commands/LCS_LEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LCS_LEN from './LCS_LEN'; diff --git a/packages/client/lib/commands/LINDEX.spec.ts b/packages/client/lib/commands/LINDEX.spec.ts index 6fd68d9c4d4..60346b85f21 100644 --- a/packages/client/lib/commands/LINDEX.spec.ts +++ b/packages/client/lib/commands/LINDEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LINDEX from './LINDEX'; diff --git a/packages/client/lib/commands/LINSERT.spec.ts b/packages/client/lib/commands/LINSERT.spec.ts index 296683c23f0..6cafa3f5a84 100644 --- a/packages/client/lib/commands/LINSERT.spec.ts +++ b/packages/client/lib/commands/LINSERT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LINSERT from './LINSERT'; diff --git a/packages/client/lib/commands/LLEN.spec.ts b/packages/client/lib/commands/LLEN.spec.ts index 931969a936e..f6ac9a73cc3 100644 --- a/packages/client/lib/commands/LLEN.spec.ts +++ b/packages/client/lib/commands/LLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LLEN from './LLEN'; diff --git a/packages/client/lib/commands/LMOVE.spec.ts b/packages/client/lib/commands/LMOVE.spec.ts index fef7f6deee5..86740aa7b77 100644 --- a/packages/client/lib/commands/LMOVE.spec.ts +++ b/packages/client/lib/commands/LMOVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LMOVE from './LMOVE'; diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts index 78a0cdd9cce..faf39e053ef 100644 --- a/packages/client/lib/commands/LMPOP.spec.ts +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LMPOP from './LMPOP'; diff --git a/packages/client/lib/commands/LOLWUT.spec.ts b/packages/client/lib/commands/LOLWUT.spec.ts index 89b294bdad4..b05c4168f6f 100644 --- a/packages/client/lib/commands/LOLWUT.spec.ts +++ b/packages/client/lib/commands/LOLWUT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LOLWUT from './LOLWUT'; diff --git a/packages/client/lib/commands/LPOP.spec.ts b/packages/client/lib/commands/LPOP.spec.ts index 0e432981a2b..944e559b15f 100644 --- a/packages/client/lib/commands/LPOP.spec.ts +++ b/packages/client/lib/commands/LPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPOP from './LPOP'; diff --git a/packages/client/lib/commands/LPOP_COUNT.spec.ts b/packages/client/lib/commands/LPOP_COUNT.spec.ts index 691af966c56..8286a504428 100644 --- a/packages/client/lib/commands/LPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOP_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPOP_COUNT from './LPOP_COUNT'; diff --git a/packages/client/lib/commands/LPOS.spec.ts b/packages/client/lib/commands/LPOS.spec.ts index 21c8a630f54..94c0bb3c034 100644 --- a/packages/client/lib/commands/LPOS.spec.ts +++ b/packages/client/lib/commands/LPOS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPOS from './LPOS'; diff --git a/packages/client/lib/commands/LPOS_COUNT.spec.ts b/packages/client/lib/commands/LPOS_COUNT.spec.ts index 111323c55d8..747ffbc01cf 100644 --- a/packages/client/lib/commands/LPOS_COUNT.spec.ts +++ b/packages/client/lib/commands/LPOS_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPOS_COUNT from './LPOS_COUNT'; diff --git a/packages/client/lib/commands/LPUSH.spec.ts b/packages/client/lib/commands/LPUSH.spec.ts index 7ed3262ed28..8d2ddb5ccc2 100644 --- a/packages/client/lib/commands/LPUSH.spec.ts +++ b/packages/client/lib/commands/LPUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPUSH from './LPUSH'; diff --git a/packages/client/lib/commands/LPUSHX.spec.ts b/packages/client/lib/commands/LPUSHX.spec.ts index 8cbe89e31b0..f7dafe025c7 100644 --- a/packages/client/lib/commands/LPUSHX.spec.ts +++ b/packages/client/lib/commands/LPUSHX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LPUSHX from './LPUSHX'; diff --git a/packages/client/lib/commands/LRANGE.spec.ts b/packages/client/lib/commands/LRANGE.spec.ts index a5a70db6ee3..3e768cc0731 100644 --- a/packages/client/lib/commands/LRANGE.spec.ts +++ b/packages/client/lib/commands/LRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LRANGE from './LRANGE'; diff --git a/packages/client/lib/commands/LREM.spec.ts b/packages/client/lib/commands/LREM.spec.ts index 40aff2e8af6..1a35dab7c54 100644 --- a/packages/client/lib/commands/LREM.spec.ts +++ b/packages/client/lib/commands/LREM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LREM from './LREM'; diff --git a/packages/client/lib/commands/LSET.spec.ts b/packages/client/lib/commands/LSET.spec.ts index 3f73e813958..ae4b1bf9f2f 100644 --- a/packages/client/lib/commands/LSET.spec.ts +++ b/packages/client/lib/commands/LSET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LSET from './LSET'; diff --git a/packages/client/lib/commands/LTRIM.spec.ts b/packages/client/lib/commands/LTRIM.spec.ts index df151d2ddb5..3edc3669737 100644 --- a/packages/client/lib/commands/LTRIM.spec.ts +++ b/packages/client/lib/commands/LTRIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LTRIM from './LTRIM'; diff --git a/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts index 0936bd98983..e1d718d7aab 100644 --- a/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts +++ b/packages/client/lib/commands/MEMORY_DOCTOR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MEMORY_DOCTOR from './MEMORY_DOCTOR'; diff --git a/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts index 7cf5e5dc8b1..8484fcbf0b7 100644 --- a/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_MALLOC-STATS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MEMORY_MALLOC_STATS from './MEMORY_MALLOC-STATS'; diff --git a/packages/client/lib/commands/MEMORY_PURGE.spec.ts b/packages/client/lib/commands/MEMORY_PURGE.spec.ts index f54769bcc2a..41b01f87c4b 100644 --- a/packages/client/lib/commands/MEMORY_PURGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_PURGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MEMORY_PURGE from './MEMORY_PURGE'; diff --git a/packages/client/lib/commands/MEMORY_STATS.spec.ts b/packages/client/lib/commands/MEMORY_STATS.spec.ts index 29af2b95d90..4fc823c3e66 100644 --- a/packages/client/lib/commands/MEMORY_STATS.spec.ts +++ b/packages/client/lib/commands/MEMORY_STATS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MEMORY_STATS from './MEMORY_STATS'; diff --git a/packages/client/lib/commands/MEMORY_USAGE.spec.ts b/packages/client/lib/commands/MEMORY_USAGE.spec.ts index e4bdb05c59a..250a6884259 100644 --- a/packages/client/lib/commands/MEMORY_USAGE.spec.ts +++ b/packages/client/lib/commands/MEMORY_USAGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MEMORY_USAGE from './MEMORY_USAGE'; diff --git a/packages/client/lib/commands/MGET.spec.ts b/packages/client/lib/commands/MGET.spec.ts index b9fa49bbdd6..296702a1a03 100644 --- a/packages/client/lib/commands/MGET.spec.ts +++ b/packages/client/lib/commands/MGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MGET from './MGET'; diff --git a/packages/client/lib/commands/MIGRATE.spec.ts b/packages/client/lib/commands/MIGRATE.spec.ts index ca7ceb48b39..3d14df5018e 100644 --- a/packages/client/lib/commands/MIGRATE.spec.ts +++ b/packages/client/lib/commands/MIGRATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { transformArguments } from './MIGRATE'; describe('MIGRATE', () => { diff --git a/packages/client/lib/commands/MODULE_LIST.spec.ts b/packages/client/lib/commands/MODULE_LIST.spec.ts index da5544cb098..9c1d3874381 100644 --- a/packages/client/lib/commands/MODULE_LIST.spec.ts +++ b/packages/client/lib/commands/MODULE_LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import MODULE_LIST from './MODULE_LIST'; describe('MODULE LIST', () => { diff --git a/packages/client/lib/commands/MODULE_LOAD.spec.ts b/packages/client/lib/commands/MODULE_LOAD.spec.ts index 254e9755a11..3b7b9dd00a3 100644 --- a/packages/client/lib/commands/MODULE_LOAD.spec.ts +++ b/packages/client/lib/commands/MODULE_LOAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import MODULE_LOAD from './MODULE_LOAD'; describe('MODULE LOAD', () => { diff --git a/packages/client/lib/commands/MODULE_UNLOAD.spec.ts b/packages/client/lib/commands/MODULE_UNLOAD.spec.ts index 3de117bc5ca..e33fb3a5f4f 100644 --- a/packages/client/lib/commands/MODULE_UNLOAD.spec.ts +++ b/packages/client/lib/commands/MODULE_UNLOAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import MODULE_UNLOAD from './MODULE_UNLOAD'; describe('MODULE UNLOAD', () => { diff --git a/packages/client/lib/commands/MOVE.spec.ts b/packages/client/lib/commands/MOVE.spec.ts index e0ca4ec797e..e767568e72b 100644 --- a/packages/client/lib/commands/MOVE.spec.ts +++ b/packages/client/lib/commands/MOVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MOVE from './MOVE'; diff --git a/packages/client/lib/commands/MSET.spec.ts b/packages/client/lib/commands/MSET.spec.ts index d8161b179f2..5435e283108 100644 --- a/packages/client/lib/commands/MSET.spec.ts +++ b/packages/client/lib/commands/MSET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MSET from './MSET'; diff --git a/packages/client/lib/commands/MSETNX.spec.ts b/packages/client/lib/commands/MSETNX.spec.ts index 0c8f07879d3..1583d04a94e 100644 --- a/packages/client/lib/commands/MSETNX.spec.ts +++ b/packages/client/lib/commands/MSETNX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MSETNX from './MSETNX'; diff --git a/packages/client/lib/commands/OBJECT_ENCODING.spec.ts b/packages/client/lib/commands/OBJECT_ENCODING.spec.ts index 0ea77767b8b..48146f12924 100644 --- a/packages/client/lib/commands/OBJECT_ENCODING.spec.ts +++ b/packages/client/lib/commands/OBJECT_ENCODING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJECT_ENCODING from './OBJECT_ENCODING'; diff --git a/packages/client/lib/commands/OBJECT_FREQ.spec.ts b/packages/client/lib/commands/OBJECT_FREQ.spec.ts index e072d371649..cbad72c308d 100644 --- a/packages/client/lib/commands/OBJECT_FREQ.spec.ts +++ b/packages/client/lib/commands/OBJECT_FREQ.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJECT_FREQ from './OBJECT_FREQ'; diff --git a/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts b/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts index ed908d142fe..51866427c81 100644 --- a/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts +++ b/packages/client/lib/commands/OBJECT_IDLETIME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJECT_IDLETIME from './OBJECT_IDLETIME'; diff --git a/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts b/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts index f0c50c8aaf3..f4309786eb1 100644 --- a/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts +++ b/packages/client/lib/commands/OBJECT_REFCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJECT_REFCOUNT from './OBJECT_REFCOUNT'; diff --git a/packages/client/lib/commands/PERSIST.spec.ts b/packages/client/lib/commands/PERSIST.spec.ts index 4e0c288ea0e..d778a1c0a5f 100644 --- a/packages/client/lib/commands/PERSIST.spec.ts +++ b/packages/client/lib/commands/PERSIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PERSIST from './PERSIST'; diff --git a/packages/client/lib/commands/PEXPIRE.spec.ts b/packages/client/lib/commands/PEXPIRE.spec.ts index 2b2a2f4b07f..61bfe69e9a1 100644 --- a/packages/client/lib/commands/PEXPIRE.spec.ts +++ b/packages/client/lib/commands/PEXPIRE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PEXPIRE from './PEXPIRE'; diff --git a/packages/client/lib/commands/PEXPIREAT.spec.ts b/packages/client/lib/commands/PEXPIREAT.spec.ts index 455595313f0..117c5b512e7 100644 --- a/packages/client/lib/commands/PEXPIREAT.spec.ts +++ b/packages/client/lib/commands/PEXPIREAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PEXPIREAT from './PEXPIREAT'; diff --git a/packages/client/lib/commands/PEXPIRETIME.spec.ts b/packages/client/lib/commands/PEXPIRETIME.spec.ts index 53c86acd184..25a8293ec59 100644 --- a/packages/client/lib/commands/PEXPIRETIME.spec.ts +++ b/packages/client/lib/commands/PEXPIRETIME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PEXPIRETIME from './PEXPIRETIME'; diff --git a/packages/client/lib/commands/PFADD.spec.ts b/packages/client/lib/commands/PFADD.spec.ts index 61db8b94647..04ba44164df 100644 --- a/packages/client/lib/commands/PFADD.spec.ts +++ b/packages/client/lib/commands/PFADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PFADD from './PFADD'; diff --git a/packages/client/lib/commands/PFCOUNT.spec.ts b/packages/client/lib/commands/PFCOUNT.spec.ts index 6f531de2715..ebb54ea1d72 100644 --- a/packages/client/lib/commands/PFCOUNT.spec.ts +++ b/packages/client/lib/commands/PFCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PFCOUNT from './PFCOUNT'; diff --git a/packages/client/lib/commands/PFMERGE.spec.ts b/packages/client/lib/commands/PFMERGE.spec.ts index 63e061c6a00..bb2444b3ef1 100644 --- a/packages/client/lib/commands/PFMERGE.spec.ts +++ b/packages/client/lib/commands/PFMERGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PFMERGE from './PFMERGE'; diff --git a/packages/client/lib/commands/PING.spec.ts b/packages/client/lib/commands/PING.spec.ts index 5ea68074d72..0cd75a6a8de 100644 --- a/packages/client/lib/commands/PING.spec.ts +++ b/packages/client/lib/commands/PING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PING from './PING'; diff --git a/packages/client/lib/commands/PSETEX.spec.ts b/packages/client/lib/commands/PSETEX.spec.ts index 11ce8027b42..fd7bcd2dff2 100644 --- a/packages/client/lib/commands/PSETEX.spec.ts +++ b/packages/client/lib/commands/PSETEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PSETEX from './PSETEX'; diff --git a/packages/client/lib/commands/PTTL.spec.ts b/packages/client/lib/commands/PTTL.spec.ts index 116441f5b56..65a9f5dd0ff 100644 --- a/packages/client/lib/commands/PTTL.spec.ts +++ b/packages/client/lib/commands/PTTL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PTTL from './PTTL'; diff --git a/packages/client/lib/commands/PUBLISH.spec.ts b/packages/client/lib/commands/PUBLISH.spec.ts index e9657812915..ec1f108e5ee 100644 --- a/packages/client/lib/commands/PUBLISH.spec.ts +++ b/packages/client/lib/commands/PUBLISH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PUBLISH from './PUBLISH'; diff --git a/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts index 635a88eb107..2fe02523ed1 100644 --- a/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts +++ b/packages/client/lib/commands/PUBSUB_CHANNELS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PUBSUB_CHANNELS from './PUBSUB_CHANNELS'; diff --git a/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts index fce46b23287..43a2b4b5c0e 100644 --- a/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMPAT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PUBSUB_NUMPAT from './PUBSUB_NUMPAT'; diff --git a/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts index bf9741229c1..151dc219288 100644 --- a/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts +++ b/packages/client/lib/commands/PUBSUB_NUMSUB.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PUBSUB_NUMSUB from './PUBSUB_NUMSUB'; diff --git a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts index 7b6bcaf5a03..77982b34670 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDCHANNELS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PUBSUB_SHARDCHANNELS from './PUBSUB_SHARDCHANNELS'; diff --git a/packages/client/lib/commands/RANDOMKEY.spec.ts b/packages/client/lib/commands/RANDOMKEY.spec.ts index 240fc03de10..31de60d7a99 100644 --- a/packages/client/lib/commands/RANDOMKEY.spec.ts +++ b/packages/client/lib/commands/RANDOMKEY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RANDOMKEY from './RANDOMKEY'; diff --git a/packages/client/lib/commands/READONLY.spec.ts b/packages/client/lib/commands/READONLY.spec.ts index 2aa0d274ceb..14bb047349a 100644 --- a/packages/client/lib/commands/READONLY.spec.ts +++ b/packages/client/lib/commands/READONLY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import READONLY from './READONLY'; describe('READONLY', () => { diff --git a/packages/client/lib/commands/READWRITE.spec.ts b/packages/client/lib/commands/READWRITE.spec.ts index 9f9e7982a6b..94a88a0dcc7 100644 --- a/packages/client/lib/commands/READWRITE.spec.ts +++ b/packages/client/lib/commands/READWRITE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import READWRITE from './READWRITE'; describe('READWRITE', () => { diff --git a/packages/client/lib/commands/RENAME.spec.ts b/packages/client/lib/commands/RENAME.spec.ts index d0d16115ea3..cf3dccbf3e7 100644 --- a/packages/client/lib/commands/RENAME.spec.ts +++ b/packages/client/lib/commands/RENAME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RENAME from './RENAME'; diff --git a/packages/client/lib/commands/RENAMENX.spec.ts b/packages/client/lib/commands/RENAMENX.spec.ts index da1e0c4b480..5f83933e957 100644 --- a/packages/client/lib/commands/RENAMENX.spec.ts +++ b/packages/client/lib/commands/RENAMENX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RENAMENX from './RENAMENX'; diff --git a/packages/client/lib/commands/REPLICAOF.spec.ts b/packages/client/lib/commands/REPLICAOF.spec.ts index a88f929e833..77dbe060450 100644 --- a/packages/client/lib/commands/REPLICAOF.spec.ts +++ b/packages/client/lib/commands/REPLICAOF.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import REPLICAOF from './REPLICAOF'; describe('REPLICAOF', () => { diff --git a/packages/client/lib/commands/RESTORE-ASKING.spec.ts b/packages/client/lib/commands/RESTORE-ASKING.spec.ts index c87fd706450..855196b9776 100644 --- a/packages/client/lib/commands/RESTORE-ASKING.spec.ts +++ b/packages/client/lib/commands/RESTORE-ASKING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import RESTORE_ASKING from './RESTORE-ASKING'; describe('RESTORE-ASKING', () => { diff --git a/packages/client/lib/commands/ROLE.spec.ts b/packages/client/lib/commands/ROLE.spec.ts index 85f586e441b..c57ba5ba1f0 100644 --- a/packages/client/lib/commands/ROLE.spec.ts +++ b/packages/client/lib/commands/ROLE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ROLE from './ROLE'; diff --git a/packages/client/lib/commands/RPOP.spec.ts b/packages/client/lib/commands/RPOP.spec.ts index d22dadccd3d..8ac5cb290f4 100644 --- a/packages/client/lib/commands/RPOP.spec.ts +++ b/packages/client/lib/commands/RPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RPOP from './RPOP'; diff --git a/packages/client/lib/commands/RPOPLPUSH.spec.ts b/packages/client/lib/commands/RPOPLPUSH.spec.ts index bb045168bf8..59458fc0aa8 100644 --- a/packages/client/lib/commands/RPOPLPUSH.spec.ts +++ b/packages/client/lib/commands/RPOPLPUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RPOPLPUSH from './RPOPLPUSH'; diff --git a/packages/client/lib/commands/RPOP_COUNT.spec.ts b/packages/client/lib/commands/RPOP_COUNT.spec.ts index 03ede55d6b1..14f1854b8bc 100644 --- a/packages/client/lib/commands/RPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/RPOP_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RPOP_COUNT from './RPOP_COUNT'; diff --git a/packages/client/lib/commands/RPUSH.spec.ts b/packages/client/lib/commands/RPUSH.spec.ts index 0e860b3454f..06078d75951 100644 --- a/packages/client/lib/commands/RPUSH.spec.ts +++ b/packages/client/lib/commands/RPUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RPUSH from './RPUSH'; diff --git a/packages/client/lib/commands/RPUSHX.spec.ts b/packages/client/lib/commands/RPUSHX.spec.ts index a8bd46d07c7..5adaa8b263a 100644 --- a/packages/client/lib/commands/RPUSHX.spec.ts +++ b/packages/client/lib/commands/RPUSHX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RPUSHX from './RPUSHX'; diff --git a/packages/client/lib/commands/SADD.spec.ts b/packages/client/lib/commands/SADD.spec.ts index 5496c003537..77adc1c18ce 100644 --- a/packages/client/lib/commands/SADD.spec.ts +++ b/packages/client/lib/commands/SADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SADD from './SADD'; diff --git a/packages/client/lib/commands/SAVE.spec.ts b/packages/client/lib/commands/SAVE.spec.ts index 66a9e210902..5c014da7edb 100644 --- a/packages/client/lib/commands/SAVE.spec.ts +++ b/packages/client/lib/commands/SAVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import SAVE from './SAVE'; describe('SAVE', () => { diff --git a/packages/client/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts index ccffde48d2d..908c57ffee5 100644 --- a/packages/client/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCAN from './SCAN'; diff --git a/packages/client/lib/commands/SCARD.spec.ts b/packages/client/lib/commands/SCARD.spec.ts index 2d6ba32c6d5..5029f340d96 100644 --- a/packages/client/lib/commands/SCARD.spec.ts +++ b/packages/client/lib/commands/SCARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCARD from './SCARD'; diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts index c90f0573f36..4e07f2c250c 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCRIPT_DEBUG from './SCRIPT_DEBUG'; diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts index 0a8a7be991d..8afdbb5f581 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCRIPT_EXISTS from './SCRIPT_EXISTS'; diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts index 1407c8c3666..ccc14ecc285 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCRIPT_FLUSH from './SCRIPT_FLUSH'; diff --git a/packages/client/lib/commands/SCRIPT_KILL.spec.ts b/packages/client/lib/commands/SCRIPT_KILL.spec.ts index d9313de18b1..1499c97ac07 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.spec.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import SCRIPT_KILL from './SCRIPT_KILL'; describe('SCRIPT KILL', () => { diff --git a/packages/client/lib/commands/SCRIPT_LOAD.spec.ts b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts index 5aaba040855..d964859d2ff 100644 --- a/packages/client/lib/commands/SCRIPT_LOAD.spec.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SCRIPT_LOAD from './SCRIPT_LOAD'; import { scriptSha1 } from '../lua-script'; diff --git a/packages/client/lib/commands/SDIFF.spec.ts b/packages/client/lib/commands/SDIFF.spec.ts index 8c614a04143..83ac6dc1da1 100644 --- a/packages/client/lib/commands/SDIFF.spec.ts +++ b/packages/client/lib/commands/SDIFF.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SDIFF from './SDIFF'; diff --git a/packages/client/lib/commands/SDIFFSTORE.spec.ts b/packages/client/lib/commands/SDIFFSTORE.spec.ts index 27b03266d9b..613a9eb590b 100644 --- a/packages/client/lib/commands/SDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/SDIFFSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SDIFFSTORE from './SDIFFSTORE'; diff --git a/packages/client/lib/commands/SET.spec.ts b/packages/client/lib/commands/SET.spec.ts index 1819cc40f35..4364eb7391a 100644 --- a/packages/client/lib/commands/SET.spec.ts +++ b/packages/client/lib/commands/SET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SET from './SET'; diff --git a/packages/client/lib/commands/SETBIT.spec.ts b/packages/client/lib/commands/SETBIT.spec.ts index 05b817501ee..e4470bb1528 100644 --- a/packages/client/lib/commands/SETBIT.spec.ts +++ b/packages/client/lib/commands/SETBIT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SETBIT from './SETBIT'; diff --git a/packages/client/lib/commands/SETEX.spec.ts b/packages/client/lib/commands/SETEX.spec.ts index 77034dd915a..00f204cc713 100644 --- a/packages/client/lib/commands/SETEX.spec.ts +++ b/packages/client/lib/commands/SETEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SETEX from './SETEX'; diff --git a/packages/client/lib/commands/SETNX .spec.ts b/packages/client/lib/commands/SETNX .spec.ts index 38ac5c36cf1..5cfca29ba62 100644 --- a/packages/client/lib/commands/SETNX .spec.ts +++ b/packages/client/lib/commands/SETNX .spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SETNX from './SETNX'; diff --git a/packages/client/lib/commands/SETRANGE.spec.ts b/packages/client/lib/commands/SETRANGE.spec.ts index 5da1f185503..01d3545a359 100644 --- a/packages/client/lib/commands/SETRANGE.spec.ts +++ b/packages/client/lib/commands/SETRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SETRANGE from './SETRANGE'; diff --git a/packages/client/lib/commands/SHUTDOWN.spec.ts b/packages/client/lib/commands/SHUTDOWN.spec.ts index 4d0d54dc877..7dd46a5d534 100644 --- a/packages/client/lib/commands/SHUTDOWN.spec.ts +++ b/packages/client/lib/commands/SHUTDOWN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import SHUTDOWN from './SHUTDOWN'; describe('SHUTDOWN', () => { diff --git a/packages/client/lib/commands/SINTER.spec.ts b/packages/client/lib/commands/SINTER.spec.ts index f147abbdbb9..5b66fdd3f89 100644 --- a/packages/client/lib/commands/SINTER.spec.ts +++ b/packages/client/lib/commands/SINTER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SINTER from './SINTER'; diff --git a/packages/client/lib/commands/SINTERCARD.spec.ts b/packages/client/lib/commands/SINTERCARD.spec.ts index 643e5114064..cddb886088a 100644 --- a/packages/client/lib/commands/SINTERCARD.spec.ts +++ b/packages/client/lib/commands/SINTERCARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SINTERCARD from './SINTERCARD'; diff --git a/packages/client/lib/commands/SINTERSTORE.spec.ts b/packages/client/lib/commands/SINTERSTORE.spec.ts index 7a78f5a0992..05416742ee9 100644 --- a/packages/client/lib/commands/SINTERSTORE.spec.ts +++ b/packages/client/lib/commands/SINTERSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SINTERSTORE from './SINTERSTORE'; diff --git a/packages/client/lib/commands/SISMEMBER.spec.ts b/packages/client/lib/commands/SISMEMBER.spec.ts index c4b1502230e..0c1b92614cb 100644 --- a/packages/client/lib/commands/SISMEMBER.spec.ts +++ b/packages/client/lib/commands/SISMEMBER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SISMEMBER from './SISMEMBER'; diff --git a/packages/client/lib/commands/SMEMBERS.spec.ts b/packages/client/lib/commands/SMEMBERS.spec.ts index 6ca8ce6597f..016b01ff747 100644 --- a/packages/client/lib/commands/SMEMBERS.spec.ts +++ b/packages/client/lib/commands/SMEMBERS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SMEMBERS from './SMEMBERS'; diff --git a/packages/client/lib/commands/SMISMEMBER.spec.ts b/packages/client/lib/commands/SMISMEMBER.spec.ts index 92619820d63..273ab05dd75 100644 --- a/packages/client/lib/commands/SMISMEMBER.spec.ts +++ b/packages/client/lib/commands/SMISMEMBER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SMISMEMBER from './SMISMEMBER'; diff --git a/packages/client/lib/commands/SMOVE.spec.ts b/packages/client/lib/commands/SMOVE.spec.ts index 60007ceffda..7ff2f773a7b 100644 --- a/packages/client/lib/commands/SMOVE.spec.ts +++ b/packages/client/lib/commands/SMOVE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SMOVE from './SMOVE'; diff --git a/packages/client/lib/commands/SORT.spec.ts b/packages/client/lib/commands/SORT.spec.ts index 58540b3f2f8..4fce8113755 100644 --- a/packages/client/lib/commands/SORT.spec.ts +++ b/packages/client/lib/commands/SORT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SORT from './SORT'; diff --git a/packages/client/lib/commands/SORT_RO.spec.ts b/packages/client/lib/commands/SORT_RO.spec.ts index c49efc11b3b..963416ae639 100644 --- a/packages/client/lib/commands/SORT_RO.spec.ts +++ b/packages/client/lib/commands/SORT_RO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SORT_RO from './SORT_RO'; diff --git a/packages/client/lib/commands/SORT_STORE.spec.ts b/packages/client/lib/commands/SORT_STORE.spec.ts index 1d1152852b2..49efd4c6ad8 100644 --- a/packages/client/lib/commands/SORT_STORE.spec.ts +++ b/packages/client/lib/commands/SORT_STORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SORT_STORE from './SORT_STORE'; diff --git a/packages/client/lib/commands/SPOP.spec.ts b/packages/client/lib/commands/SPOP.spec.ts index b5c67644f00..896c1c820ac 100644 --- a/packages/client/lib/commands/SPOP.spec.ts +++ b/packages/client/lib/commands/SPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SPOP from './SPOP'; diff --git a/packages/client/lib/commands/SPOP_COUNT.spec.ts b/packages/client/lib/commands/SPOP_COUNT.spec.ts index cff078e9e16..ddad816b420 100644 --- a/packages/client/lib/commands/SPOP_COUNT.spec.ts +++ b/packages/client/lib/commands/SPOP_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SPOP_COUNT from './SPOP_COUNT'; diff --git a/packages/client/lib/commands/SPUBLISH.spec.ts b/packages/client/lib/commands/SPUBLISH.spec.ts index 0b1391774b0..741372d0154 100644 --- a/packages/client/lib/commands/SPUBLISH.spec.ts +++ b/packages/client/lib/commands/SPUBLISH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SPUBLISH from './SPUBLISH'; diff --git a/packages/client/lib/commands/SRANDMEMBER.spec.ts b/packages/client/lib/commands/SRANDMEMBER.spec.ts index a0983e4480d..a7df01f0eb9 100644 --- a/packages/client/lib/commands/SRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SRANDMEMBER from './SRANDMEMBER'; diff --git a/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts index 6ed30cd14ab..364eb640341 100644 --- a/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/SRANDMEMBER_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SRANDMEMBER_COUNT from './SRANDMEMBER_COUNT'; diff --git a/packages/client/lib/commands/SREM.spec.ts b/packages/client/lib/commands/SREM.spec.ts index 708fa04eae3..f17c6fb118e 100644 --- a/packages/client/lib/commands/SREM.spec.ts +++ b/packages/client/lib/commands/SREM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SREM from './SREM'; diff --git a/packages/client/lib/commands/SSCAN.spec.ts b/packages/client/lib/commands/SSCAN.spec.ts index 2b394511f56..29a13306fde 100644 --- a/packages/client/lib/commands/SSCAN.spec.ts +++ b/packages/client/lib/commands/SSCAN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SSCAN from './SSCAN'; diff --git a/packages/client/lib/commands/STRLEN.spec.ts b/packages/client/lib/commands/STRLEN.spec.ts index b80a84a010d..b07c07b909a 100644 --- a/packages/client/lib/commands/STRLEN.spec.ts +++ b/packages/client/lib/commands/STRLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import STRLEN from './STRLEN'; diff --git a/packages/client/lib/commands/SUNION.spec.ts b/packages/client/lib/commands/SUNION.spec.ts index d91baa9c66e..ff00c44a1b1 100644 --- a/packages/client/lib/commands/SUNION.spec.ts +++ b/packages/client/lib/commands/SUNION.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUNION from './SUNION'; diff --git a/packages/client/lib/commands/SUNIONSTORE.spec.ts b/packages/client/lib/commands/SUNIONSTORE.spec.ts index e9d288c0298..790fd78060a 100644 --- a/packages/client/lib/commands/SUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/SUNIONSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUNIONSTORE from './SUNIONSTORE'; diff --git a/packages/client/lib/commands/SWAPDB.spec.ts b/packages/client/lib/commands/SWAPDB.spec.ts index a4c6d1833a2..9331854c13b 100644 --- a/packages/client/lib/commands/SWAPDB.spec.ts +++ b/packages/client/lib/commands/SWAPDB.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SWAPDB from './SWAPDB'; diff --git a/packages/client/lib/commands/TIME.spec.ts b/packages/client/lib/commands/TIME.spec.ts index a9e2448dbd9..d9dd9667ea4 100644 --- a/packages/client/lib/commands/TIME.spec.ts +++ b/packages/client/lib/commands/TIME.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TIME from './TIME'; diff --git a/packages/client/lib/commands/TOUCH.spec.ts b/packages/client/lib/commands/TOUCH.spec.ts index 01c5ed9454b..48e77900ee3 100644 --- a/packages/client/lib/commands/TOUCH.spec.ts +++ b/packages/client/lib/commands/TOUCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TOUCH from './TOUCH'; diff --git a/packages/client/lib/commands/TTL.spec.ts b/packages/client/lib/commands/TTL.spec.ts index 792f022593e..6b709226a2b 100644 --- a/packages/client/lib/commands/TTL.spec.ts +++ b/packages/client/lib/commands/TTL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TTL from './TTL'; diff --git a/packages/client/lib/commands/TYPE.spec.ts b/packages/client/lib/commands/TYPE.spec.ts index 01beef42e1c..45cf1cfc1c9 100644 --- a/packages/client/lib/commands/TYPE.spec.ts +++ b/packages/client/lib/commands/TYPE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TYPE from './TYPE'; diff --git a/packages/client/lib/commands/UNLINK.spec.ts b/packages/client/lib/commands/UNLINK.spec.ts index 726c05223a3..1e374783007 100644 --- a/packages/client/lib/commands/UNLINK.spec.ts +++ b/packages/client/lib/commands/UNLINK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import UNLINK from './UNLINK'; diff --git a/packages/client/lib/commands/UNWATCH.spec.ts b/packages/client/lib/commands/UNWATCH.spec.ts index 75bac71d853..2aeb0297e99 100644 --- a/packages/client/lib/commands/UNWATCH.spec.ts +++ b/packages/client/lib/commands/UNWATCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import UNWATCH from './UNWATCH'; diff --git a/packages/client/lib/commands/WAIT.spec.ts b/packages/client/lib/commands/WAIT.spec.ts index 2b8c1de319c..ff91f4ed514 100644 --- a/packages/client/lib/commands/WAIT.spec.ts +++ b/packages/client/lib/commands/WAIT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import WAIT from './WAIT'; diff --git a/packages/client/lib/commands/WATCH.spec.ts b/packages/client/lib/commands/WATCH.spec.ts index d533a0b3e13..c3069fd6200 100644 --- a/packages/client/lib/commands/WATCH.spec.ts +++ b/packages/client/lib/commands/WATCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import WATCH from './WATCH'; describe('WATCH', () => { diff --git a/packages/client/lib/commands/XACK.spec.ts b/packages/client/lib/commands/XACK.spec.ts index 35eed370893..81a7954ffd6 100644 --- a/packages/client/lib/commands/XACK.spec.ts +++ b/packages/client/lib/commands/XACK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XACK from './XACK'; diff --git a/packages/client/lib/commands/XADD.spec.ts b/packages/client/lib/commands/XADD.spec.ts index bfc3e0c2caf..10c6f4daa56 100644 --- a/packages/client/lib/commands/XADD.spec.ts +++ b/packages/client/lib/commands/XADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XADD from './XADD'; diff --git a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts index b78b01c37e6..a3dd5602a3b 100644 --- a/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts +++ b/packages/client/lib/commands/XADD_NOMKSTREAM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; diff --git a/packages/client/lib/commands/XAUTOCLAIM.spec.ts b/packages/client/lib/commands/XAUTOCLAIM.spec.ts index bf3b11c6c00..256c58cc4d6 100644 --- a/packages/client/lib/commands/XAUTOCLAIM.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XAUTOCLAIM from './XAUTOCLAIM'; diff --git a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts index 872d19100f1..96ceb1d8116 100644 --- a/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XAUTOCLAIM_JUSTID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XAUTOCLAIM_JUSTID from './XAUTOCLAIM_JUSTID'; diff --git a/packages/client/lib/commands/XCLAIM.spec.ts b/packages/client/lib/commands/XCLAIM.spec.ts index 48546eecdbe..e8fde2e1a1a 100644 --- a/packages/client/lib/commands/XCLAIM.spec.ts +++ b/packages/client/lib/commands/XCLAIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XCLAIM from './XCLAIM'; diff --git a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts index 3110293e856..6b580ac3c1b 100644 --- a/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts +++ b/packages/client/lib/commands/XCLAIM_JUSTID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XCLAIM_JUSTID from './XCLAIM_JUSTID'; diff --git a/packages/client/lib/commands/XDEL.spec.ts b/packages/client/lib/commands/XDEL.spec.ts index a5c81a58181..15875d3b7b3 100644 --- a/packages/client/lib/commands/XDEL.spec.ts +++ b/packages/client/lib/commands/XDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XDEL from './XDEL'; diff --git a/packages/client/lib/commands/XGROUP_CREATE.spec.ts b/packages/client/lib/commands/XGROUP_CREATE.spec.ts index 8dee9b5fda7..5c9071289c9 100644 --- a/packages/client/lib/commands/XGROUP_CREATE.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XGROUP_CREATE from './XGROUP_CREATE'; diff --git a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts index e959462c220..3c3ecbda0a7 100644 --- a/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_CREATECONSUMER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XGROUP_CREATECONSUMER from './XGROUP_CREATECONSUMER'; diff --git a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts index 7ec59f90c70..afc524eef86 100644 --- a/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts +++ b/packages/client/lib/commands/XGROUP_DELCONSUMER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XGROUP_DELCONSUMER from './XGROUP_DELCONSUMER'; diff --git a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts index 4d7bd9ad2ed..6ec90834518 100644 --- a/packages/client/lib/commands/XGROUP_DESTROY.spec.ts +++ b/packages/client/lib/commands/XGROUP_DESTROY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XGROUP_DESTROY from './XGROUP_DESTROY'; diff --git a/packages/client/lib/commands/XGROUP_SETID.spec.ts b/packages/client/lib/commands/XGROUP_SETID.spec.ts index e0d920627c2..891a796d14d 100644 --- a/packages/client/lib/commands/XGROUP_SETID.spec.ts +++ b/packages/client/lib/commands/XGROUP_SETID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XGROUP_SETID from './XGROUP_SETID'; diff --git a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts index ddfba6f27a9..86abdbb1493 100644 --- a/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts +++ b/packages/client/lib/commands/XINFO_CONSUMERS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XINFO_CONSUMERS from './XINFO_CONSUMERS'; diff --git a/packages/client/lib/commands/XINFO_GROUPS.spec.ts b/packages/client/lib/commands/XINFO_GROUPS.spec.ts index 59326898a5f..1bee02a0e6d 100644 --- a/packages/client/lib/commands/XINFO_GROUPS.spec.ts +++ b/packages/client/lib/commands/XINFO_GROUPS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XINFO_GROUPS from './XINFO_GROUPS'; diff --git a/packages/client/lib/commands/XINFO_STREAM.spec.ts b/packages/client/lib/commands/XINFO_STREAM.spec.ts index 630d25c3961..9e6939092e2 100644 --- a/packages/client/lib/commands/XINFO_STREAM.spec.ts +++ b/packages/client/lib/commands/XINFO_STREAM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XINFO_STREAM from './XINFO_STREAM'; diff --git a/packages/client/lib/commands/XLEN.spec.ts b/packages/client/lib/commands/XLEN.spec.ts index 8f2bf1a8c77..164a6d6f094 100644 --- a/packages/client/lib/commands/XLEN.spec.ts +++ b/packages/client/lib/commands/XLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XLEN from './XLEN'; diff --git a/packages/client/lib/commands/XPENDING.spec.ts b/packages/client/lib/commands/XPENDING.spec.ts index 993245a5d82..e6600cce383 100644 --- a/packages/client/lib/commands/XPENDING.spec.ts +++ b/packages/client/lib/commands/XPENDING.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XPENDING from './XPENDING'; diff --git a/packages/client/lib/commands/XPENDING_RANGE.spec.ts b/packages/client/lib/commands/XPENDING_RANGE.spec.ts index 586914d7b4e..a66484fd2e6 100644 --- a/packages/client/lib/commands/XPENDING_RANGE.spec.ts +++ b/packages/client/lib/commands/XPENDING_RANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XPENDING_RANGE from './XPENDING_RANGE'; diff --git a/packages/client/lib/commands/XRANGE.spec.ts b/packages/client/lib/commands/XRANGE.spec.ts index 5557b04c8fe..ebfe271db86 100644 --- a/packages/client/lib/commands/XRANGE.spec.ts +++ b/packages/client/lib/commands/XRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XRANGE from './XRANGE'; diff --git a/packages/client/lib/commands/XREAD.spec.ts b/packages/client/lib/commands/XREAD.spec.ts index c707d6ef527..69cd6cd6ffe 100644 --- a/packages/client/lib/commands/XREAD.spec.ts +++ b/packages/client/lib/commands/XREAD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XREAD from './XREAD'; diff --git a/packages/client/lib/commands/XREADGROUP.spec.ts b/packages/client/lib/commands/XREADGROUP.spec.ts index ee23689add5..5ff16edcaa3 100644 --- a/packages/client/lib/commands/XREADGROUP.spec.ts +++ b/packages/client/lib/commands/XREADGROUP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XREADGROUP from './XREADGROUP'; diff --git a/packages/client/lib/commands/XREVRANGE.spec.ts b/packages/client/lib/commands/XREVRANGE.spec.ts index 448018a2b98..c9f3043af38 100644 --- a/packages/client/lib/commands/XREVRANGE.spec.ts +++ b/packages/client/lib/commands/XREVRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XREVRANGE from './XREVRANGE'; diff --git a/packages/client/lib/commands/XSETID.spec.ts b/packages/client/lib/commands/XSETID.spec.ts index 993f4638a80..5ebbc943816 100644 --- a/packages/client/lib/commands/XSETID.spec.ts +++ b/packages/client/lib/commands/XSETID.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XSETID from './XSETID'; diff --git a/packages/client/lib/commands/XTRIM.spec.ts b/packages/client/lib/commands/XTRIM.spec.ts index 4c6ea985f1c..a5a2fdf23c5 100644 --- a/packages/client/lib/commands/XTRIM.spec.ts +++ b/packages/client/lib/commands/XTRIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import XTRIM from './XTRIM'; diff --git a/packages/client/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts index 4ca25ee0eee..5f64cb13b92 100644 --- a/packages/client/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZADD from './ZADD'; diff --git a/packages/client/lib/commands/ZADD_INCR.spec.ts b/packages/client/lib/commands/ZADD_INCR.spec.ts index f014160d2e2..c6ffcb796f3 100644 --- a/packages/client/lib/commands/ZADD_INCR.spec.ts +++ b/packages/client/lib/commands/ZADD_INCR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZADD_INCR from './ZADD_INCR'; diff --git a/packages/client/lib/commands/ZCARD.spec.ts b/packages/client/lib/commands/ZCARD.spec.ts index f0c566832df..ff4bb881fb7 100644 --- a/packages/client/lib/commands/ZCARD.spec.ts +++ b/packages/client/lib/commands/ZCARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZCARD from './ZCARD'; diff --git a/packages/client/lib/commands/ZCOUNT.spec.ts b/packages/client/lib/commands/ZCOUNT.spec.ts index dd2a7124d1f..357f24bd796 100644 --- a/packages/client/lib/commands/ZCOUNT.spec.ts +++ b/packages/client/lib/commands/ZCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZCOUNT from './ZCOUNT'; diff --git a/packages/client/lib/commands/ZDIFF.spec.ts b/packages/client/lib/commands/ZDIFF.spec.ts index 6d4ed91df31..a285190398c 100644 --- a/packages/client/lib/commands/ZDIFF.spec.ts +++ b/packages/client/lib/commands/ZDIFF.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZDIFF from './ZDIFF'; diff --git a/packages/client/lib/commands/ZDIFFSTORE.spec.ts b/packages/client/lib/commands/ZDIFFSTORE.spec.ts index 4901c5b1e14..1bd779302bf 100644 --- a/packages/client/lib/commands/ZDIFFSTORE.spec.ts +++ b/packages/client/lib/commands/ZDIFFSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZDIFFSTORE from './ZDIFFSTORE'; diff --git a/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts index 0082be3cf86..4fcd1f978a3 100644 --- a/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZDIFF_WITHSCORES from './ZDIFF_WITHSCORES'; diff --git a/packages/client/lib/commands/ZINCRBY.spec.ts b/packages/client/lib/commands/ZINCRBY.spec.ts index 531f39cc3f8..fea3c7a2f71 100644 --- a/packages/client/lib/commands/ZINCRBY.spec.ts +++ b/packages/client/lib/commands/ZINCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZINCRBY from './ZINCRBY'; diff --git a/packages/client/lib/commands/ZINTER.spec.ts b/packages/client/lib/commands/ZINTER.spec.ts index d90a0074f25..0d678ce1151 100644 --- a/packages/client/lib/commands/ZINTER.spec.ts +++ b/packages/client/lib/commands/ZINTER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZINTER from './ZINTER'; diff --git a/packages/client/lib/commands/ZINTERCARD.spec.ts b/packages/client/lib/commands/ZINTERCARD.spec.ts index c6817b4f27b..312e2825ff4 100644 --- a/packages/client/lib/commands/ZINTERCARD.spec.ts +++ b/packages/client/lib/commands/ZINTERCARD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZINTERCARD from './ZINTERCARD'; diff --git a/packages/client/lib/commands/ZINTERSTORE.spec.ts b/packages/client/lib/commands/ZINTERSTORE.spec.ts index 01591147c44..27914ca0327 100644 --- a/packages/client/lib/commands/ZINTERSTORE.spec.ts +++ b/packages/client/lib/commands/ZINTERSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZINTERSTORE from './ZINTERSTORE'; diff --git a/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts index e2689733b13..05790510e49 100644 --- a/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZINTER_WITHSCORES from './ZINTER_WITHSCORES'; diff --git a/packages/client/lib/commands/ZLEXCOUNT.spec.ts b/packages/client/lib/commands/ZLEXCOUNT.spec.ts index b787f70cf86..d0a76075579 100644 --- a/packages/client/lib/commands/ZLEXCOUNT.spec.ts +++ b/packages/client/lib/commands/ZLEXCOUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZLEXCOUNT from './ZLEXCOUNT'; diff --git a/packages/client/lib/commands/ZMPOP.spec.ts b/packages/client/lib/commands/ZMPOP.spec.ts index e866c09f72b..6335fca81cb 100644 --- a/packages/client/lib/commands/ZMPOP.spec.ts +++ b/packages/client/lib/commands/ZMPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZMPOP from './ZMPOP'; diff --git a/packages/client/lib/commands/ZMSCORE.spec.ts b/packages/client/lib/commands/ZMSCORE.spec.ts index 96cea5d5f78..5035724b117 100644 --- a/packages/client/lib/commands/ZMSCORE.spec.ts +++ b/packages/client/lib/commands/ZMSCORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZMSCORE from './ZMSCORE'; diff --git a/packages/client/lib/commands/ZPOPMAX.spec.ts b/packages/client/lib/commands/ZPOPMAX.spec.ts index c18c419e81d..609ccb826b5 100644 --- a/packages/client/lib/commands/ZPOPMAX.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZPOPMAX from './ZPOPMAX'; diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts index 0806b5977d1..b653b1f3f1a 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZPOPMAX_COUNT from './ZPOPMAX_COUNT'; diff --git a/packages/client/lib/commands/ZPOPMIN.spec.ts b/packages/client/lib/commands/ZPOPMIN.spec.ts index c2f5858a58f..0b2c57d28b9 100644 --- a/packages/client/lib/commands/ZPOPMIN.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZPOPMIN from './ZPOPMIN'; diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts index 2b2f12b3487..fa3d9e2a975 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZPOPMIN_COUNT from './ZPOPMIN_COUNT'; diff --git a/packages/client/lib/commands/ZRANDMEMBER.spec.ts b/packages/client/lib/commands/ZRANDMEMBER.spec.ts index 5249399c427..519850f5eff 100644 --- a/packages/client/lib/commands/ZRANDMEMBER.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANDMEMBER from './ZRANDMEMBER'; diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts index f108eb91ba8..2d0f4b9ced8 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; diff --git a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts index 7ea438e1df3..aeeea3f6e71 100644 --- a/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANDMEMBER_COUNT_WITHSCORES from './ZRANDMEMBER_COUNT_WITHSCORES'; diff --git a/packages/client/lib/commands/ZRANGE.spec.ts b/packages/client/lib/commands/ZRANGE.spec.ts index f147cfaa1b1..db940062b2f 100644 --- a/packages/client/lib/commands/ZRANGE.spec.ts +++ b/packages/client/lib/commands/ZRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGE from './ZRANGE'; diff --git a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts index 7b0c22946c0..f3f6f4bc0e5 100644 --- a/packages/client/lib/commands/ZRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYLEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGEBYLEX from './ZRANGEBYLEX'; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts index 2ff55676b8b..61267ea7f2f 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts index 2cca62bae26..e70a97b0372 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; diff --git a/packages/client/lib/commands/ZRANGESTORE.spec.ts b/packages/client/lib/commands/ZRANGESTORE.spec.ts index 51befc4b381..51315d3463b 100644 --- a/packages/client/lib/commands/ZRANGESTORE.spec.ts +++ b/packages/client/lib/commands/ZRANGESTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGESTORE from './ZRANGESTORE'; diff --git a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts index 0d2cec9b9fa..038c150a675 100644 --- a/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGE_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANGE_WITHSCORES from './ZRANGE_WITHSCORES'; diff --git a/packages/client/lib/commands/ZRANK.spec.ts b/packages/client/lib/commands/ZRANK.spec.ts index cd3d1725b0e..9341709bda3 100644 --- a/packages/client/lib/commands/ZRANK.spec.ts +++ b/packages/client/lib/commands/ZRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANK from './ZRANK'; diff --git a/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts b/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts index 3d308d0d478..b571e0f7071 100644 --- a/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts +++ b/packages/client/lib/commands/ZRANK_WITHSCORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZRANK_WITHSCORE from './ZRANK_WITHSCORE'; diff --git a/packages/client/lib/commands/ZREM.spec.ts b/packages/client/lib/commands/ZREM.spec.ts index ac52b171a8f..4b203c9f4eb 100644 --- a/packages/client/lib/commands/ZREM.spec.ts +++ b/packages/client/lib/commands/ZREM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZREM from './ZREM'; diff --git a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts index 149aca959c8..9f29c3cdcf7 100644 --- a/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYLEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZREMRANGEBYLEX from './ZREMRANGEBYLEX'; diff --git a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts index f6030e4f081..12627083e1a 100644 --- a/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZREMRANGEBYRANK from './ZREMRANGEBYRANK'; diff --git a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts index ff819438d6f..fb3ba4e718c 100644 --- a/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts +++ b/packages/client/lib/commands/ZREMRANGEBYSCORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; diff --git a/packages/client/lib/commands/ZREVRANK.spec.ts b/packages/client/lib/commands/ZREVRANK.spec.ts index f7e104bca3b..418773b6003 100644 --- a/packages/client/lib/commands/ZREVRANK.spec.ts +++ b/packages/client/lib/commands/ZREVRANK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZREVRANK from './ZREVRANK'; diff --git a/packages/client/lib/commands/ZSCAN.spec.ts b/packages/client/lib/commands/ZSCAN.spec.ts index d4d5f565465..ebeaad2a4d0 100644 --- a/packages/client/lib/commands/ZSCAN.spec.ts +++ b/packages/client/lib/commands/ZSCAN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZSCAN from './ZSCAN'; diff --git a/packages/client/lib/commands/ZSCORE.spec.ts b/packages/client/lib/commands/ZSCORE.spec.ts index 55c6d51cd05..3d8df6640c8 100644 --- a/packages/client/lib/commands/ZSCORE.spec.ts +++ b/packages/client/lib/commands/ZSCORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZSCORE from './ZSCORE'; diff --git a/packages/client/lib/commands/ZUNION.spec.ts b/packages/client/lib/commands/ZUNION.spec.ts index 54542aaa81d..f66bb7abc63 100644 --- a/packages/client/lib/commands/ZUNION.spec.ts +++ b/packages/client/lib/commands/ZUNION.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZUNION from './ZUNION'; diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index 979cd384e1b..7a01e80f0c0 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZUNIONSTORE from './ZUNIONSTORE'; diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index 75283c0bc3a..bbf3ec676e8 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ZUNION_WITHSCORES from './ZUNION_WITHSCORES'; diff --git a/packages/client/lib/commands/generic-transformers.spec.ts b/packages/client/lib/commands/generic-transformers.spec.ts index 6bd1bcc8012..5f990d4e34d 100644 --- a/packages/client/lib/commands/generic-transformers.spec.ts +++ b/packages/client/lib/commands/generic-transformers.spec.ts @@ -1,4 +1,4 @@ -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import { // transformBooleanReply, // transformBooleanArrayReply, diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index ab3711ab3a7..af46502c908 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -127,7 +127,7 @@ import FUNCTION_LIST_WITHCODE from './FUNCTION_LIST_WITHCODE'; import FUNCTION_LIST from './FUNCTION_LIST'; import FUNCTION_LOAD from './FUNCTION_LOAD'; import FUNCTION_RESTORE from './FUNCTION_RESTORE'; -// import FUNCTION_STATS from './FUNCTION_STATS'; +import FUNCTION_STATS from './FUNCTION_STATS'; import HDEL from './HDEL'; import HELLO from './HELLO'; import HEXISTS from './HEXISTS'; @@ -537,8 +537,8 @@ export default { functionLoad: FUNCTION_LOAD, FUNCTION_RESTORE, functionRestore: FUNCTION_RESTORE, - // FUNCTION_STATS, - // functionStats: FUNCTION_STATS, + FUNCTION_STATS, + functionStats: FUNCTION_STATS, GEOADD, geoAdd: GEOADD, GEODIST, diff --git a/packages/client/lib/lua-script.ts b/packages/client/lib/lua-script.ts index 8d20735a5f0..6d395b71232 100644 --- a/packages/client/lib/lua-script.ts +++ b/packages/client/lib/lua-script.ts @@ -1,4 +1,4 @@ -import { createHash } from 'crypto'; +import { createHash } from 'node:crypto'; import { Command } from './RESP/types'; export type RedisScriptConfig = Command & { diff --git a/packages/client/lib/multi-command.spec.ts b/packages/client/lib/multi-command.spec.ts index eebb29f7985..02230060415 100644 --- a/packages/client/lib/multi-command.spec.ts +++ b/packages/client/lib/multi-command.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import RedisMultiCommand from './multi-command'; import { SQUARE_SCRIPT } from './client/index.spec'; diff --git a/packages/graph/lib/commands/CONFIG_GET.spec.ts b/packages/graph/lib/commands/CONFIG_GET.spec.ts index c9bf44503ba..42c7739f5d7 100644 --- a/packages/graph/lib/commands/CONFIG_GET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_GET from './CONFIG_GET'; diff --git a/packages/graph/lib/commands/CONFIG_SET.spec.ts b/packages/graph/lib/commands/CONFIG_SET.spec.ts index aa44be8717b..5ed51e78a29 100644 --- a/packages/graph/lib/commands/CONFIG_SET.spec.ts +++ b/packages/graph/lib/commands/CONFIG_SET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_SET from './CONFIG_SET'; diff --git a/packages/graph/lib/commands/DELETE.spec.ts b/packages/graph/lib/commands/DELETE.spec.ts index 45d5ddaa50c..6fe24fd827a 100644 --- a/packages/graph/lib/commands/DELETE.spec.ts +++ b/packages/graph/lib/commands/DELETE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DELETE from './DELETE'; diff --git a/packages/graph/lib/commands/EXPLAIN.spec.ts b/packages/graph/lib/commands/EXPLAIN.spec.ts index 1fc824ad364..04bf838a4de 100644 --- a/packages/graph/lib/commands/EXPLAIN.spec.ts +++ b/packages/graph/lib/commands/EXPLAIN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import EXPLAIN from './EXPLAIN'; diff --git a/packages/graph/lib/commands/LIST.spec.ts b/packages/graph/lib/commands/LIST.spec.ts index 697b9906123..36745efc470 100644 --- a/packages/graph/lib/commands/LIST.spec.ts +++ b/packages/graph/lib/commands/LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import LIST from './LIST'; diff --git a/packages/graph/lib/commands/PROFILE.spec.ts b/packages/graph/lib/commands/PROFILE.spec.ts index ec950d505e7..a758365d56e 100644 --- a/packages/graph/lib/commands/PROFILE.spec.ts +++ b/packages/graph/lib/commands/PROFILE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import PROFILE from './PROFILE'; diff --git a/packages/graph/lib/commands/QUERY.spec.ts b/packages/graph/lib/commands/QUERY.spec.ts index 389374b5d30..fef9ccad478 100644 --- a/packages/graph/lib/commands/QUERY.spec.ts +++ b/packages/graph/lib/commands/QUERY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import QUERY from './QUERY'; diff --git a/packages/graph/lib/commands/RO_QUERY.spec.ts b/packages/graph/lib/commands/RO_QUERY.spec.ts index b85c33be63b..13829543552 100644 --- a/packages/graph/lib/commands/RO_QUERY.spec.ts +++ b/packages/graph/lib/commands/RO_QUERY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RO_QUERY from './RO_QUERY'; diff --git a/packages/graph/lib/commands/SLOWLOG.spec.ts b/packages/graph/lib/commands/SLOWLOG.spec.ts index 5f8d1107527..a0201109861 100644 --- a/packages/graph/lib/commands/SLOWLOG.spec.ts +++ b/packages/graph/lib/commands/SLOWLOG.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SLOWLOG from './SLOWLOG'; diff --git a/packages/graph/lib/graph.spec.ts b/packages/graph/lib/graph.spec.ts index 13b8e6145bb..ab506c43a4b 100644 --- a/packages/graph/lib/graph.spec.ts +++ b/packages/graph/lib/graph.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from './test-utils'; import Graph from './graph'; diff --git a/packages/json/lib/commands/ARRAPPEND.spec.ts b/packages/json/lib/commands/ARRAPPEND.spec.ts index 8261a125f00..3bdd967e237 100644 --- a/packages/json/lib/commands/ARRAPPEND.spec.ts +++ b/packages/json/lib/commands/ARRAPPEND.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRAPPEND from './ARRAPPEND'; diff --git a/packages/json/lib/commands/ARRINDEX.spec.ts b/packages/json/lib/commands/ARRINDEX.spec.ts index 42d98c15329..cb946b62515 100644 --- a/packages/json/lib/commands/ARRINDEX.spec.ts +++ b/packages/json/lib/commands/ARRINDEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRINDEX from './ARRINDEX'; diff --git a/packages/json/lib/commands/ARRINSERT.spec.ts b/packages/json/lib/commands/ARRINSERT.spec.ts index c9f4c36a1ea..efa824b3738 100644 --- a/packages/json/lib/commands/ARRINSERT.spec.ts +++ b/packages/json/lib/commands/ARRINSERT.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRINSERT from './ARRINSERT'; diff --git a/packages/json/lib/commands/ARRLEN.spec.ts b/packages/json/lib/commands/ARRLEN.spec.ts index 743c6fa0bce..5ecb01b2ce5 100644 --- a/packages/json/lib/commands/ARRLEN.spec.ts +++ b/packages/json/lib/commands/ARRLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRLEN from './ARRLEN'; diff --git a/packages/json/lib/commands/ARRPOP.spec.ts b/packages/json/lib/commands/ARRPOP.spec.ts index 91d8c962816..1b069ba3928 100644 --- a/packages/json/lib/commands/ARRPOP.spec.ts +++ b/packages/json/lib/commands/ARRPOP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRPOP from './ARRPOP'; diff --git a/packages/json/lib/commands/ARRTRIM.spec.ts b/packages/json/lib/commands/ARRTRIM.spec.ts index 03cd80a0e7c..4c2f72aaa50 100644 --- a/packages/json/lib/commands/ARRTRIM.spec.ts +++ b/packages/json/lib/commands/ARRTRIM.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ARRTRIM from './ARRTRIM'; diff --git a/packages/json/lib/commands/CLEAR.spec.ts b/packages/json/lib/commands/CLEAR.spec.ts index a58e16868e7..983e6bec2d9 100644 --- a/packages/json/lib/commands/CLEAR.spec.ts +++ b/packages/json/lib/commands/CLEAR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLEAR from './CLEAR'; diff --git a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts index 88e59e13293..c41d07cb27e 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.spec.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEBUG_MEMORY from './DEBUG_MEMORY'; diff --git a/packages/json/lib/commands/DEL.spec.ts b/packages/json/lib/commands/DEL.spec.ts index 11e817af182..18f6a8f2db6 100644 --- a/packages/json/lib/commands/DEL.spec.ts +++ b/packages/json/lib/commands/DEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEL from './DEL'; diff --git a/packages/json/lib/commands/FORGET.spec.ts b/packages/json/lib/commands/FORGET.spec.ts index e60e5355ad3..04066ec43a9 100644 --- a/packages/json/lib/commands/FORGET.spec.ts +++ b/packages/json/lib/commands/FORGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import FORGET from './FORGET'; diff --git a/packages/json/lib/commands/GET.spec.ts b/packages/json/lib/commands/GET.spec.ts index dec66dbb365..6d6ff14f67f 100644 --- a/packages/json/lib/commands/GET.spec.ts +++ b/packages/json/lib/commands/GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GET from './GET'; diff --git a/packages/json/lib/commands/MERGE.spec.ts b/packages/json/lib/commands/MERGE.spec.ts index c4d37e32c72..56f5d25e7d5 100644 --- a/packages/json/lib/commands/MERGE.spec.ts +++ b/packages/json/lib/commands/MERGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MERGE from './MERGE'; diff --git a/packages/json/lib/commands/MGET.spec.ts b/packages/json/lib/commands/MGET.spec.ts index 49845d20eda..1bfaecd6da9 100644 --- a/packages/json/lib/commands/MGET.spec.ts +++ b/packages/json/lib/commands/MGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MGET from './MGET'; diff --git a/packages/json/lib/commands/MSET.spec.ts b/packages/json/lib/commands/MSET.spec.ts index 88803c56a83..360890234c8 100644 --- a/packages/json/lib/commands/MSET.spec.ts +++ b/packages/json/lib/commands/MSET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MSET from './MSET'; diff --git a/packages/json/lib/commands/NUMINCRBY.spec.ts b/packages/json/lib/commands/NUMINCRBY.spec.ts index d2b21df4cac..d0bffd2bd2a 100644 --- a/packages/json/lib/commands/NUMINCRBY.spec.ts +++ b/packages/json/lib/commands/NUMINCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import NUMINCRBY from './NUMINCRBY'; diff --git a/packages/json/lib/commands/NUMMULTBY.spec.ts b/packages/json/lib/commands/NUMMULTBY.spec.ts index a02a8f75cc9..9767c2b0979 100644 --- a/packages/json/lib/commands/NUMMULTBY.spec.ts +++ b/packages/json/lib/commands/NUMMULTBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import NUMMULTBY from './NUMMULTBY'; diff --git a/packages/json/lib/commands/OBJKEYS.spec.ts b/packages/json/lib/commands/OBJKEYS.spec.ts index 8c3222d671b..dc984cb2ce9 100644 --- a/packages/json/lib/commands/OBJKEYS.spec.ts +++ b/packages/json/lib/commands/OBJKEYS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJKEYS from './OBJKEYS'; diff --git a/packages/json/lib/commands/OBJLEN.spec.ts b/packages/json/lib/commands/OBJLEN.spec.ts index c646d3a4f0d..8f616107fd5 100644 --- a/packages/json/lib/commands/OBJLEN.spec.ts +++ b/packages/json/lib/commands/OBJLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import OBJLEN from './OBJLEN'; diff --git a/packages/json/lib/commands/RESP.spec.ts b/packages/json/lib/commands/RESP.spec.ts index 8b70962d1c5..6dfc3360326 100644 --- a/packages/json/lib/commands/RESP.spec.ts +++ b/packages/json/lib/commands/RESP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './RESP'; diff --git a/packages/json/lib/commands/SET.spec.ts b/packages/json/lib/commands/SET.spec.ts index d65b562be27..15e27073281 100644 --- a/packages/json/lib/commands/SET.spec.ts +++ b/packages/json/lib/commands/SET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SET from './SET'; diff --git a/packages/json/lib/commands/STRAPPEND.spec.ts b/packages/json/lib/commands/STRAPPEND.spec.ts index 8927ce84613..0d8bdb57185 100644 --- a/packages/json/lib/commands/STRAPPEND.spec.ts +++ b/packages/json/lib/commands/STRAPPEND.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import STRAPPEND from './STRAPPEND'; diff --git a/packages/json/lib/commands/STRLEN.spec.ts b/packages/json/lib/commands/STRLEN.spec.ts index 5bb0548ffaf..e058e48a635 100644 --- a/packages/json/lib/commands/STRLEN.spec.ts +++ b/packages/json/lib/commands/STRLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import STRLEN from './STRLEN'; diff --git a/packages/json/lib/commands/TOGGLE.spec.ts b/packages/json/lib/commands/TOGGLE.spec.ts index 90a456b9209..c8a78877906 100644 --- a/packages/json/lib/commands/TOGGLE.spec.ts +++ b/packages/json/lib/commands/TOGGLE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TOGGLE from './TOGGLE'; diff --git a/packages/json/lib/commands/TYPE.spec.ts b/packages/json/lib/commands/TYPE.spec.ts index e0edf9c825e..103ce59de6e 100644 --- a/packages/json/lib/commands/TYPE.spec.ts +++ b/packages/json/lib/commands/TYPE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TYPE from './TYPE'; diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index d1e4565339a..08e8a87f231 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { AggregateGroupByReducers, AggregateSteps, transformArguments } from './AGGREGATE'; import { SchemaFieldTypes } from '.'; diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts index 65396f3f790..bd60965e7db 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './AGGREGATE_WITHCURSOR'; import { SchemaFieldTypes } from '.'; diff --git a/packages/search/lib/commands/ALIASADD.spec.ts b/packages/search/lib/commands/ALIASADD.spec.ts index 22a895cae68..3a5d02175f9 100644 --- a/packages/search/lib/commands/ALIASADD.spec.ts +++ b/packages/search/lib/commands/ALIASADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ALIASADD from './ALIASADD'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/ALIASDEL.spec.ts b/packages/search/lib/commands/ALIASDEL.spec.ts index 0a308bd7691..3842d01b145 100644 --- a/packages/search/lib/commands/ALIASDEL.spec.ts +++ b/packages/search/lib/commands/ALIASDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ALIASDEL from './ALIASDEL'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/ALIASUPDATE.spec.ts b/packages/search/lib/commands/ALIASUPDATE.spec.ts index cc0d1439ac9..a0e7431af6b 100644 --- a/packages/search/lib/commands/ALIASUPDATE.spec.ts +++ b/packages/search/lib/commands/ALIASUPDATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ALIASUPDATE from './ALIASUPDATE'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/ALTER.spec.ts b/packages/search/lib/commands/ALTER.spec.ts index 26f5d48de1c..6cac0be40c8 100644 --- a/packages/search/lib/commands/ALTER.spec.ts +++ b/packages/search/lib/commands/ALTER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ALTER from './ALTER'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/CONFIG_GET.spec.ts b/packages/search/lib/commands/CONFIG_GET.spec.ts index 8614f443426..44ab78d9da3 100644 --- a/packages/search/lib/commands/CONFIG_GET.spec.ts +++ b/packages/search/lib/commands/CONFIG_GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './CONFIG_GET'; diff --git a/packages/search/lib/commands/CONFIG_SET.spec.ts b/packages/search/lib/commands/CONFIG_SET.spec.ts index 263c99c2327..3b20f2eac5d 100644 --- a/packages/search/lib/commands/CONFIG_SET.spec.ts +++ b/packages/search/lib/commands/CONFIG_SET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CONFIG_SET from './CONFIG_SET'; diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 0c0b3e89a22..dad983c0038 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CREATE, { SCHEMA_FIELD_TYPE, SCHEMA_TEXT_FIELD_PHONETIC, SCHEMA_VECTOR_FIELD_ALGORITHM, REDISEARCH_LANGUAGE } from './CREATE'; diff --git a/packages/search/lib/commands/CURSOR_DEL.spec.ts b/packages/search/lib/commands/CURSOR_DEL.spec.ts index c5fad7e8e89..b7bfe11b19f 100644 --- a/packages/search/lib/commands/CURSOR_DEL.spec.ts +++ b/packages/search/lib/commands/CURSOR_DEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CURSOR_DEL from './CURSOR_DEL'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/CURSOR_READ.spec.ts b/packages/search/lib/commands/CURSOR_READ.spec.ts index bb68e2b6396..e8ef2c30912 100644 --- a/packages/search/lib/commands/CURSOR_READ.spec.ts +++ b/packages/search/lib/commands/CURSOR_READ.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './CURSOR_READ'; diff --git a/packages/search/lib/commands/DICTADD.spec.ts b/packages/search/lib/commands/DICTADD.spec.ts index 6baeb6299a6..c18502ea4d0 100644 --- a/packages/search/lib/commands/DICTADD.spec.ts +++ b/packages/search/lib/commands/DICTADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTADD from './DICTADD'; diff --git a/packages/search/lib/commands/DICTDEL.spec.ts b/packages/search/lib/commands/DICTDEL.spec.ts index 328cc98a34e..a7ca1b35cd3 100644 --- a/packages/search/lib/commands/DICTDEL.spec.ts +++ b/packages/search/lib/commands/DICTDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDEL from './DICTDEL'; diff --git a/packages/search/lib/commands/DICTDUMP.spec.ts b/packages/search/lib/commands/DICTDUMP.spec.ts index bb7eb3db313..fe8e9441189 100644 --- a/packages/search/lib/commands/DICTDUMP.spec.ts +++ b/packages/search/lib/commands/DICTDUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDUMP from './DICTDUMP'; diff --git a/packages/search/lib/commands/DROPINDEX.spec.ts b/packages/search/lib/commands/DROPINDEX.spec.ts index 67742c16a1a..5fcbaca08ce 100644 --- a/packages/search/lib/commands/DROPINDEX.spec.ts +++ b/packages/search/lib/commands/DROPINDEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DROPINDEX from './DROPINDEX'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/EXPLAIN.spec.ts b/packages/search/lib/commands/EXPLAIN.spec.ts index 6b3c72507df..107ae84b20f 100644 --- a/packages/search/lib/commands/EXPLAIN.spec.ts +++ b/packages/search/lib/commands/EXPLAIN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import EXPLAIN from './EXPLAIN'; describe('EXPLAIN', () => { diff --git a/packages/search/lib/commands/EXPLAINCLI.spec.ts b/packages/search/lib/commands/EXPLAINCLI.spec.ts index 720f91a8499..3bffcf5fe5b 100644 --- a/packages/search/lib/commands/EXPLAINCLI.spec.ts +++ b/packages/search/lib/commands/EXPLAINCLI.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import EXPLAINCLI from './EXPLAINCLI'; describe('EXPLAINCLI', () => { diff --git a/packages/search/lib/commands/INFO.spec.ts b/packages/search/lib/commands/INFO.spec.ts index e026b44e264..e299837a49b 100644 --- a/packages/search/lib/commands/INFO.spec.ts +++ b/packages/search/lib/commands/INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './INFO'; diff --git a/packages/search/lib/commands/PROFILE_AGGREGATE.spec.ts b/packages/search/lib/commands/PROFILE_AGGREGATE.spec.ts index c3d6f990ff7..1e36a702d67 100644 --- a/packages/search/lib/commands/PROFILE_AGGREGATE.spec.ts +++ b/packages/search/lib/commands/PROFILE_AGGREGATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; import { transformArguments } from './PROFILE_AGGREGATE'; diff --git a/packages/search/lib/commands/PROFILE_SEARCH.spec.ts b/packages/search/lib/commands/PROFILE_SEARCH.spec.ts index 6d7c5adda1e..e2f9e2728f9 100644 --- a/packages/search/lib/commands/PROFILE_SEARCH.spec.ts +++ b/packages/search/lib/commands/PROFILE_SEARCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; import { transformArguments } from './PROFILE_SEARCH'; diff --git a/packages/search/lib/commands/SEARCH.spec.ts b/packages/search/lib/commands/SEARCH.spec.ts index 931458b3a25..d3d9bf9ae37 100644 --- a/packages/search/lib/commands/SEARCH.spec.ts +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { RedisSearchLanguages, SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SEARCH'; diff --git a/packages/search/lib/commands/SPELLCHECK.spec.ts b/packages/search/lib/commands/SPELLCHECK.spec.ts index a2261004dc8..89ef0dfc1b7 100644 --- a/packages/search/lib/commands/SPELLCHECK.spec.ts +++ b/packages/search/lib/commands/SPELLCHECK.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; import SPELLCHECK from './SPELLCHECK'; diff --git a/packages/search/lib/commands/SUGADD.spec.ts b/packages/search/lib/commands/SUGADD.spec.ts index 2196ce89e79..24e03d37796 100644 --- a/packages/search/lib/commands/SUGADD.spec.ts +++ b/packages/search/lib/commands/SUGADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGADD from './SUGADD'; diff --git a/packages/search/lib/commands/SUGDEL.spec.ts b/packages/search/lib/commands/SUGDEL.spec.ts index 5f86ea80b63..ea92c2a1a49 100644 --- a/packages/search/lib/commands/SUGDEL.spec.ts +++ b/packages/search/lib/commands/SUGDEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGDEL from './SUGDEL'; diff --git a/packages/search/lib/commands/SUGGET.spec.ts b/packages/search/lib/commands/SUGGET.spec.ts index 2553077dc6c..6ea4c03f325 100644 --- a/packages/search/lib/commands/SUGGET.spec.ts +++ b/packages/search/lib/commands/SUGGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGGET from './SUGGET'; diff --git a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts index a4a87ebe895..2151c678c6b 100644 --- a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SUGGET_WITHPAYLOADS'; diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts index e60daa917a9..41ee055ae76 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SUGGET_WITHSCORES'; diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts index 0900d91b8d9..8adc9ba2b13 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './SUGGET_WITHSCORES_WITHPAYLOADS'; diff --git a/packages/search/lib/commands/SUGLEN.spec.ts b/packages/search/lib/commands/SUGLEN.spec.ts index 6238b7a3241..6e6d5e1fc5c 100644 --- a/packages/search/lib/commands/SUGLEN.spec.ts +++ b/packages/search/lib/commands/SUGLEN.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGLEN from './SUGLEN'; diff --git a/packages/search/lib/commands/SYNDUMP.spec.ts b/packages/search/lib/commands/SYNDUMP.spec.ts index 4b9a3dfae02..0fd9148ae8c 100644 --- a/packages/search/lib/commands/SYNDUMP.spec.ts +++ b/packages/search/lib/commands/SYNDUMP.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SYNDUMP from './SYNDUMP'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/SYNUPDATE.spec.ts b/packages/search/lib/commands/SYNUPDATE.spec.ts index 1dfde97521f..e901ae9fe3f 100644 --- a/packages/search/lib/commands/SYNUPDATE.spec.ts +++ b/packages/search/lib/commands/SYNUPDATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import SYNUPDATE from './SYNUPDATE'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/TAGVALS.spec.ts b/packages/search/lib/commands/TAGVALS.spec.ts index 5962beecfeb..dbc6203f93e 100644 --- a/packages/search/lib/commands/TAGVALS.spec.ts +++ b/packages/search/lib/commands/TAGVALS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import TAGVALS from './TAGVALS'; import { SCHEMA_FIELD_TYPE } from './CREATE'; diff --git a/packages/search/lib/commands/_LIST.spec.ts b/packages/search/lib/commands/_LIST.spec.ts index 1b468db0d7e..a7f13b011ac 100644 --- a/packages/search/lib/commands/_LIST.spec.ts +++ b/packages/search/lib/commands/_LIST.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import _LIST from './_LIST'; diff --git a/packages/search/lib/commands/index.spec.ts b/packages/search/lib/commands/index.spec.ts index 4c54a0dfdf2..b0ec6aa1479 100644 --- a/packages/search/lib/commands/index.spec.ts +++ b/packages/search/lib/commands/index.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { pushArgumentsWithLength, pushSortByArguments } from '.'; describe('pushSortByArguments', () => { diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index 917bd2992ef..c34f8aab368 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -1,11 +1,11 @@ -import { createConnection } from 'net'; -import { once } from 'events'; +import { createConnection } from 'node:net'; +import { once } from 'node:events'; import { createClient } from '@redis/client/index'; import { setTimeout } from 'timers/promises'; // import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; -import * as path from 'path'; -import { promisify } from 'util'; -import { exec } from 'child_process'; +import * as path from 'node:path'; +import { promisify } from 'node:util'; +import { exec } from 'node:child_process'; const execAsync = promisify(exec); interface ErrorWithCode extends Error { diff --git a/packages/time-series/lib/commands/ADD.spec.ts b/packages/time-series/lib/commands/ADD.spec.ts index 0c0e588aa7c..e9831d21d02 100644 --- a/packages/time-series/lib/commands/ADD.spec.ts +++ b/packages/time-series/lib/commands/ADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ADD from './ADD'; import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.'; diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index d09d40db66e..b60bdece62e 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import ALTER from './ALTER'; import { TIME_SERIES_DUPLICATE_POLICIES } from '.'; diff --git a/packages/time-series/lib/commands/CREATE.spec.ts b/packages/time-series/lib/commands/CREATE.spec.ts index d77c4117ebb..d400be8a035 100644 --- a/packages/time-series/lib/commands/CREATE.spec.ts +++ b/packages/time-series/lib/commands/CREATE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CREATE from './CREATE'; import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.'; diff --git a/packages/time-series/lib/commands/CREATERULE.spec.ts b/packages/time-series/lib/commands/CREATERULE.spec.ts index c06d27671a9..f1e5b934506 100644 --- a/packages/time-series/lib/commands/CREATERULE.spec.ts +++ b/packages/time-series/lib/commands/CREATERULE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CREATERULE, { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; diff --git a/packages/time-series/lib/commands/DECRBY.spec.ts b/packages/time-series/lib/commands/DECRBY.spec.ts index 0f7679b794c..f9e482bcae6 100644 --- a/packages/time-series/lib/commands/DECRBY.spec.ts +++ b/packages/time-series/lib/commands/DECRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DECRBY from './DECRBY'; diff --git a/packages/time-series/lib/commands/DEL.spec.ts b/packages/time-series/lib/commands/DEL.spec.ts index d6f90d2e2ac..afe6be77c4b 100644 --- a/packages/time-series/lib/commands/DEL.spec.ts +++ b/packages/time-series/lib/commands/DEL.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DEL from './DEL'; diff --git a/packages/time-series/lib/commands/DELETERULE.spec.ts b/packages/time-series/lib/commands/DELETERULE.spec.ts index 1ee0de3993b..8c8568c8567 100644 --- a/packages/time-series/lib/commands/DELETERULE.spec.ts +++ b/packages/time-series/lib/commands/DELETERULE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import DELETERULE from './DELETERULE'; import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; diff --git a/packages/time-series/lib/commands/GET.spec.ts b/packages/time-series/lib/commands/GET.spec.ts index 4c0925e014c..a1f47346bc2 100644 --- a/packages/time-series/lib/commands/GET.spec.ts +++ b/packages/time-series/lib/commands/GET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import GET from './GET'; diff --git a/packages/time-series/lib/commands/INCRBY.spec.ts b/packages/time-series/lib/commands/INCRBY.spec.ts index 8cd57ee4a2a..463bf930104 100644 --- a/packages/time-series/lib/commands/INCRBY.spec.ts +++ b/packages/time-series/lib/commands/INCRBY.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import INCRBY from './INCRBY'; diff --git a/packages/time-series/lib/commands/INFO.spec.ts b/packages/time-series/lib/commands/INFO.spec.ts index a03049f03b6..be22b00528a 100644 --- a/packages/time-series/lib/commands/INFO.spec.ts +++ b/packages/time-series/lib/commands/INFO.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { InfoReply, transformArguments } from './INFO'; diff --git a/packages/time-series/lib/commands/INFO_DEBUG.spec.ts b/packages/time-series/lib/commands/INFO_DEBUG.spec.ts index caff0e177f6..5f00d64256c 100644 --- a/packages/time-series/lib/commands/INFO_DEBUG.spec.ts +++ b/packages/time-series/lib/commands/INFO_DEBUG.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; import testUtils, { GLOBAL } from '../test-utils'; import { assertInfo } from './INFO.spec'; diff --git a/packages/time-series/lib/commands/MADD.spec.ts b/packages/time-series/lib/commands/MADD.spec.ts index d9585ffbe7c..bbe358e5438 100644 --- a/packages/time-series/lib/commands/MADD.spec.ts +++ b/packages/time-series/lib/commands/MADD.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MADD from './MADD'; import { SimpleError } from '@redis/client/lib/errors'; diff --git a/packages/time-series/lib/commands/MGET.spec.ts b/packages/time-series/lib/commands/MGET.spec.ts index 810e54068bd..1ddf11670a1 100644 --- a/packages/time-series/lib/commands/MGET.spec.ts +++ b/packages/time-series/lib/commands/MGET.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MGET from './MGET'; diff --git a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts index 1a2d223cb7e..70a837a00fe 100644 --- a/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MGET_WITHLABELS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MGET_WITHLABELS from './MGET_WITHLABELS'; diff --git a/packages/time-series/lib/commands/MRANGE.spec.ts b/packages/time-series/lib/commands/MRANGE.spec.ts index 32cdd37c6f2..b976368d21b 100644 --- a/packages/time-series/lib/commands/MRANGE.spec.ts +++ b/packages/time-series/lib/commands/MRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MRANGE from './MRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts index 4997634958e..116d318f8cc 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; diff --git a/packages/time-series/lib/commands/MREVRANGE.spec.ts b/packages/time-series/lib/commands/MREVRANGE.spec.ts index 69937fe4d53..334569f19aa 100644 --- a/packages/time-series/lib/commands/MREVRANGE.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './MREVRANGE'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts index 5371a009837..0a56ee32dff 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; diff --git a/packages/time-series/lib/commands/QUERYINDEX.spec.ts b/packages/time-series/lib/commands/QUERYINDEX.spec.ts index 86160ebd7d5..74f201bb74b 100644 --- a/packages/time-series/lib/commands/QUERYINDEX.spec.ts +++ b/packages/time-series/lib/commands/QUERYINDEX.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import QUERYINDEX from './QUERYINDEX'; diff --git a/packages/time-series/lib/commands/RANGE.spec.ts b/packages/time-series/lib/commands/RANGE.spec.ts index 2c6c27f7a21..bc5d38d740b 100644 --- a/packages/time-series/lib/commands/RANGE.spec.ts +++ b/packages/time-series/lib/commands/RANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import RANGE from './RANGE'; import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE'; diff --git a/packages/time-series/lib/commands/REVRANGE.spec.ts b/packages/time-series/lib/commands/REVRANGE.spec.ts index 3138e9327eb..00194aaf3cf 100644 --- a/packages/time-series/lib/commands/REVRANGE.spec.ts +++ b/packages/time-series/lib/commands/REVRANGE.spec.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './REVRANGE'; import { TimeSeriesAggregationType } from '.'; diff --git a/packages/time-series/lib/commands/index.spec.ts b/packages/time-series/lib/commands/index.spec.ts index ba71ce777ca..a6a87ebdf4a 100644 --- a/packages/time-series/lib/commands/index.spec.ts +++ b/packages/time-series/lib/commands/index.spec.ts @@ -1,5 +1,5 @@ // import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -// import { strict as assert } from 'assert'; +// import { strict as assert } from 'node:assert'; // import { // transformTimestampArgument, // pushRetentionArgument, From d009de1acf06424badf18b9bf94506344632eb97 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 15:35:45 -0400 Subject: [PATCH 225/325] upgrade `tsconfig/node16` to `tsconfig/node18` --- package-lock.json | 10 +++++----- package.json | 2 +- tsconfig.base.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16520dc8c6d..93a1539a192 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ ], "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node16": "^16.1.1", + "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.1", "@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/parser": "^6.6.0", @@ -915,10 +915,10 @@ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, - "node_modules/@tsconfig/node16": { - "version": "16.1.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-16.1.1.tgz", - "integrity": "sha512-+pio93ejHN4nINX4pXqfnR/fPLRtJBaT4ORaa5RH0Oc1zoYmo2B2koG+M328CQhHKn1Wj6FcOxCDFXAot9NhvA==", + "node_modules/@tsconfig/node18": { + "version": "18.2.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.2.tgz", + "integrity": "sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==", "dev": true }, "node_modules/@types/json-schema": { diff --git a/package.json b/package.json index 92e005a102d..89535a4e4db 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node16": "^16.1.1", + "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.1", "@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/parser": "^6.6.0", diff --git a/tsconfig.base.json b/tsconfig.base.json index 8e9d90d31cb..cb4c5026393 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,5 +1,5 @@ { - "extends": "@tsconfig/node16/tsconfig.json", + "extends": "@tsconfig/node18/tsconfig.json", "compilerOptions": { "composite": true, "declaration": true, From 67900a50fa0aec7cb41ef1ca313cbccf9c09c5d3 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 17:15:28 -0400 Subject: [PATCH 226/325] fix some missing `node:` prefix --- packages/client/lib/client/socket.ts | 2 +- packages/client/lib/test-utils.ts | 2 +- packages/test-utils/lib/dockers.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 93d128dbe14..a82e9be35a3 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'node:events'; import * as net from 'node:net'; import * as tls from 'node:tls'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError, ReconnectStrategyError } from '../errors'; -import { setTimeout } from 'timers/promises'; +import { setTimeout } from 'node:timers/promises'; import { RedisArgument } from '../RESP/types'; export interface RedisSocketCommonOptions { diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts index e4c86c2f4c9..ebdec826f6b 100644 --- a/packages/client/lib/test-utils.ts +++ b/packages/client/lib/test-utils.ts @@ -1,6 +1,6 @@ import TestUtils from '@redis/test-utils'; import { SinonSpy } from 'sinon'; -import { setTimeout } from 'timers/promises'; +import { setTimeout } from 'node:timers/promises'; const utils = new TestUtils({ dockerImageName: 'redis', diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index c34f8aab368..c2d76838945 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -1,7 +1,7 @@ import { createConnection } from 'node:net'; import { once } from 'node:events'; import { createClient } from '@redis/client/index'; -import { setTimeout } from 'timers/promises'; +import { setTimeout } from 'node:timers/promises'; // import { ClusterSlotsReply } from '@redis/client/dist/lib/commands/CLUSTER_SLOTS'; import * as path from 'node:path'; import { promisify } from 'node:util'; From 4be30ccd0f861cbf2d132a39f05c8ab5be0fbb62 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 17:16:41 -0400 Subject: [PATCH 227/325] comment cluster request & response policies (keep v4 behaver) --- docs/clustering.md | 2 - packages/client/index.ts | 2 +- packages/client/lib/RESP/types.ts | 162 ++-- packages/client/lib/client/index.spec.ts | 40 +- packages/client/lib/cluster/index.spec.ts | 708 +++++++++--------- packages/client/lib/cluster/index.ts | 158 ++-- packages/client/lib/commands/CLUSTER_INFO.ts | 2 +- packages/client/lib/commands/CLUSTER_NODES.ts | 2 +- .../client/lib/commands/CLUSTER_REPLICAS.ts | 2 +- packages/client/lib/commands/FCALL.spec.ts | 15 +- packages/client/lib/commands/FCALL_RO.spec.ts | 15 +- .../client/lib/commands/FUNCTION_LOAD.spec.ts | 12 +- packages/client/lib/commands/PUBLISH.ts | 1 + packages/test-utils/lib/index.ts | 39 +- 14 files changed, 607 insertions(+), 553 deletions(-) diff --git a/docs/clustering.md b/docs/clustering.md index b5594e49a76..7b8b66a9ad4 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -105,8 +105,6 @@ createCluster({ ## Command Routing -TODO request response policy - ### Commands that operate on Redis Keys Commands such as `GET`, `SET`, etc. are routed by the first key specified. For example `MGET 1 2 3` will be routed by the key `1`. diff --git a/packages/client/index.ts b/packages/client/index.ts index 06392e970ef..8864cf65f2d 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -1,4 +1,4 @@ -export { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, CommandPolicies } from './lib/RESP/types'; +export { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping/*, CommandPolicies*/ } from './lib/RESP/types'; export { RESP_TYPES } from './lib/RESP/decoder'; export { VerbatimString } from './lib/RESP/verbatim-string'; export { defineScript } from './lib/lua-script'; diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index 004da46756e..c4ad18e1a1f 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -200,9 +200,8 @@ export type ReplyWithTypeMapping< REPLY extends Array ? Array> : REPLY extends Set ? Set> : REPLY extends Map ? Map, ReplyWithTypeMapping> : - // `Date` & `Buffer` are supersets of `Record`, so they need to be checked first - REPLY extends Date ? REPLY : - REPLY extends Buffer ? REPLY : + // `Date | Buffer | Error` are supersets of `Record`, so they need to be checked first + REPLY extends Date | Buffer | Error ? REPLY : REPLY extends Record ? { [P in keyof REPLY]: ReplyWithTypeMapping; } : @@ -222,57 +221,62 @@ export type RedisArgument = string | Buffer; export type CommandArguments = Array & { preserve?: unknown }; -export const REQUEST_POLICIES = { - /** - * TODO - */ - ALL_NODES: 'all_nodes', - /** - * TODO - */ - ALL_SHARDS: 'all_shards', - /** - * TODO - */ - SPECIAL: 'special' -} as const; - -export type REQUEST_POLICIES = typeof REQUEST_POLICIES; - -export type RequestPolicies = REQUEST_POLICIES[keyof REQUEST_POLICIES]; - -export const RESPONSE_POLICIES = { - /** - * TODO - */ - ONE_SUCCEEDED: 'one_succeeded', - /** - * TODO - */ - ALL_SUCCEEDED: 'all_succeeded', - /** - * TODO - */ - LOGICAL_AND: 'agg_logical_and', - /** - * TODO - */ - SPECIAL: 'special' -} as const; - -export type RESPONSE_POLICIES = typeof RESPONSE_POLICIES; - -export type ResponsePolicies = RESPONSE_POLICIES[keyof RESPONSE_POLICIES]; - -export type CommandPolicies = { - request?: RequestPolicies | null; - response?: ResponsePolicies | null; -}; +// export const REQUEST_POLICIES = { +// /** +// * TODO +// */ +// ALL_NODES: 'all_nodes', +// /** +// * TODO +// */ +// ALL_SHARDS: 'all_shards', +// /** +// * TODO +// */ +// SPECIAL: 'special' +// } as const; + +// export type REQUEST_POLICIES = typeof REQUEST_POLICIES; + +// export type RequestPolicies = REQUEST_POLICIES[keyof REQUEST_POLICIES]; + +// export const RESPONSE_POLICIES = { +// /** +// * TODO +// */ +// ONE_SUCCEEDED: 'one_succeeded', +// /** +// * TODO +// */ +// ALL_SUCCEEDED: 'all_succeeded', +// /** +// * TODO +// */ +// LOGICAL_AND: 'agg_logical_and', +// /** +// * TODO +// */ +// SPECIAL: 'special' +// } as const; + +// export type RESPONSE_POLICIES = typeof RESPONSE_POLICIES; + +// export type ResponsePolicies = RESPONSE_POLICIES[keyof RESPONSE_POLICIES]; + +// export type CommandPolicies = { +// request?: RequestPolicies | null; +// response?: ResponsePolicies | null; +// }; export type Command = { FIRST_KEY_INDEX?: number | ((this: void, ...args: Array) => RedisArgument | undefined); IS_READ_ONLY?: boolean; - POLICIES?: CommandPolicies; + /** + * @internal + * TODO: remove once `POLICIES` is implemented + */ + IS_FORWARD_COMMAND?: boolean; + // POLICIES?: CommandPolicies; transformArguments(this: void, ...args: Array): CommandArguments; TRANSFORM_LEGACY_REPLY?: boolean; transformReply: TransformReply | Record; @@ -355,32 +359,32 @@ export type CommandSignature< TYPE_MAPPING extends TypeMapping > = (...args: Parameters) => Promise, TYPE_MAPPING>>; -export type CommandWithPoliciesSignature< - COMMAND extends Command, - RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies -> = (...args: Parameters) => Promise< - ReplyWithPolicy< - ReplyWithTypeMapping, TYPE_MAPPING>, - MergePolicies - > ->; - -export type MergePolicies< - COMMAND extends Command, - POLICIES extends CommandPolicies -> = Omit & POLICIES; - -type ReplyWithPolicy< - REPLY, - POLICIES extends CommandPolicies, -> = ( - POLICIES['request'] extends REQUEST_POLICIES['SPECIAL'] ? never : - POLICIES['request'] extends null | undefined ? REPLY : - unknown extends POLICIES['request'] ? REPLY : - POLICIES['response'] extends RESPONSE_POLICIES['SPECIAL'] ? never : - POLICIES['response'] extends RESPONSE_POLICIES['ALL_SUCCEEDED' | 'ONE_SUCCEEDED' | 'LOGICAL_AND'] ? REPLY : - // otherwise, return array of replies - Array -); +// export type CommandWithPoliciesSignature< +// COMMAND extends Command, +// RESP extends RespVersions, +// TYPE_MAPPING extends TypeMapping, +// POLICIES extends CommandPolicies +// > = (...args: Parameters) => Promise< +// ReplyWithPolicy< +// ReplyWithTypeMapping, TYPE_MAPPING>, +// MergePolicies +// > +// >; + +// export type MergePolicies< +// COMMAND extends Command, +// POLICIES extends CommandPolicies +// > = Omit & POLICIES; + +// type ReplyWithPolicy< +// REPLY, +// POLICIES extends CommandPolicies, +// > = ( +// POLICIES['request'] extends REQUEST_POLICIES['SPECIAL'] ? never : +// POLICIES['request'] extends null | undefined ? REPLY : +// unknown extends POLICIES['request'] ? REPLY : +// POLICIES['response'] extends RESPONSE_POLICIES['SPECIAL'] ? never : +// POLICIES['response'] extends RESPONSE_POLICIES['ALL_SUCCEEDED' | 'ONE_SUCCEEDED' | 'LOGICAL_AND'] ? REPLY : +// // otherwise, return array of replies +// Array +// ); diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 4c77a257cd8..60e776b0ddb 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -11,15 +11,19 @@ import { once } from 'node:events'; // import { promisify } from 'node:util'; import { MATH_FUNCTION, loadMathFunction } from '../commands/FUNCTION_LOAD.spec'; import { RESP_TYPES } from '../RESP/decoder'; +import { NumberReply } from '../RESP/types'; import { SortedSetMember } from '../commands/generic-transformers'; export const SQUARE_SCRIPT = defineScript({ - SCRIPT: 'return ARGV[1] * ARGV[1];', - NUMBER_OF_KEYS: 0, - transformArguments(number: number): Array { - return [number.toString()]; + SCRIPT: + `local number = redis.call('GET', KEYS[1]) + return number * number`, + NUMBER_OF_KEYS: 1, + FIRST_KEY_INDEX: 0, + transformArguments(key: string) { + return [key]; }, - transformReply: undefined as unknown as () => number + transformReply: undefined as unknown as () => NumberReply }); describe('Client', () => { @@ -214,9 +218,10 @@ describe('Client', () => { testUtils.testWithClient('with script', async client => { assert.deepEqual( await client.multi() - .square(2) + .set('key', '2') + .square('key') .exec(), - [4] + ['OK', 4] ); }, { ...GLOBAL.SERVERS.OPEN, @@ -280,10 +285,12 @@ describe('Client', () => { }); testUtils.testWithClient('scripts', async client => { - assert.equal( - await client.square(2), - 4 - ); + const [, reply] = await Promise.all([ + client.set('key', '2'), + client.square('key') + ]); + + assert.equal(reply, 4); }, { ...GLOBAL.SERVERS.OPEN, clientOptions: { @@ -319,12 +326,13 @@ describe('Client', () => { }); testUtils.testWithClient('functions', async client => { - await loadMathFunction(client); + const [,, reply] = await Promise.all([ + loadMathFunction(client), + client.set('key', '2'), + client.math.square('key') + ]); - assert.equal( - await client.math.square(2), - 4 - ); + assert.equal(reply, 4); }, { ...GLOBAL.SERVERS.OPEN, minimumDockerVersion: [7, 0], diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index 4a50f7f801a..f1630863573 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -1,362 +1,348 @@ -// import { strict as assert } from 'node:assert'; -// import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; -// import RedisCluster from '.'; +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; +import RedisCluster from '.'; // import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; -// import { commandOptions } from '../command-options'; -// import { SQUARE_SCRIPT } from '../client/index.spec'; -// import { RootNodesUnavailableError } from '../errors'; -// import { spy } from 'sinon'; -// import { setTimeout } from 'timers/promises'; -// import RedisClient from '../client'; - -// describe('Cluster', () => { -// testUtils.testWithCluster('sendCommand', async cluster => { -// assert.equal( -// await cluster.sendCommand(undefined, true, ['PING']), -// 'PONG' -// ); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('isOpen', async cluster => { -// assert.equal(cluster.isOpen, true); -// await cluster.disconnect(); -// assert.equal(cluster.isOpen, false); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('connect should throw if already connected', async cluster => { -// await assert.rejects(cluster.connect()); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('multi', async cluster => { -// const key = 'key'; -// assert.deepEqual( -// await cluster.multi() -// .set(key, 'value') -// .get(key) -// .exec(), -// ['OK', 'value'] -// ); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('scripts', async cluster => { -// assert.equal( -// await cluster.square(2), -// 4 -// ); -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// scripts: { -// square: SQUARE_SCRIPT -// } -// } -// }); - -// it('should throw RootNodesUnavailableError', async () => { -// const cluster = RedisCluster.create({ -// rootNodes: [] -// }); - -// try { -// await assert.rejects( -// cluster.connect(), -// RootNodesUnavailableError -// ); -// } catch (err) { -// await cluster.disconnect(); -// throw err; -// } -// }); - -// testUtils.testWithCluster('should handle live resharding', async cluster => { -// const slot = 12539, -// key = 'key', -// value = 'value'; -// await cluster.set(key, value); - -// const importing = cluster.slots[0].master, -// migrating = cluster.slots[slot].master, -// [ importingClient, migratingClient ] = await Promise.all([ -// cluster.nodeClient(importing), -// cluster.nodeClient(migrating) -// ]); - -// await Promise.all([ -// importingClient.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, migrating.id), -// migratingClient.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, importing.id) -// ]); - -// // should be able to get the key from the migrating node -// assert.equal( -// await cluster.get(key), -// value -// ); - -// await migratingClient.migrate( -// importing.host, -// importing.port, -// key, -// 0, -// 10 -// ); - -// // should be able to get the key from the importing node using `ASKING` -// assert.equal( -// await cluster.get(key), -// value -// ); - -// await Promise.all([ -// importingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), -// migratingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), -// ]); - -// // should handle `MOVED` errors -// assert.equal( -// await cluster.get(key), -// value -// ); -// }, { -// serverArguments: [], -// numberOfMasters: 2 -// }); - -// testUtils.testWithCluster('getRandomNode should spread the the load evenly', async cluster => { -// const totalNodes = cluster.masters.length + cluster.replicas.length, -// ids = new Set(); -// for (let i = 0; i < totalNodes; i++) { -// ids.add(cluster.getRandomNode().id); -// } - -// assert.equal(ids.size, totalNodes); -// }, GLOBAL.CLUSTERS.WITH_REPLICAS); - -// testUtils.testWithCluster('getSlotRandomNode should spread the the load evenly', async cluster => { -// const totalNodes = 1 + cluster.slots[0].replicas!.length, -// ids = new Set(); -// for (let i = 0; i < totalNodes; i++) { -// ids.add(cluster.getSlotRandomNode(0).id); -// } - -// assert.equal(ids.size, totalNodes); -// }, GLOBAL.CLUSTERS.WITH_REPLICAS); - -// testUtils.testWithCluster('cluster topology', async cluster => { -// assert.equal(cluster.slots.length, 16384); -// const { numberOfMasters, numberOfReplicas } = GLOBAL.CLUSTERS.WITH_REPLICAS; -// assert.equal(cluster.shards.length, numberOfMasters); -// assert.equal(cluster.masters.length, numberOfMasters); -// assert.equal(cluster.replicas.length, numberOfReplicas * numberOfMasters); -// assert.equal(cluster.nodeByAddress.size, numberOfMasters + numberOfMasters * numberOfReplicas); -// }, GLOBAL.CLUSTERS.WITH_REPLICAS); - -// testUtils.testWithCluster('getMasters should be backwards competiable (without `minimizeConnections`)', async cluster => { -// const masters = cluster.getMasters(); -// assert.ok(Array.isArray(masters)); -// for (const master of masters) { -// assert.equal(typeof master.id, 'string'); -// assert.ok(master.client instanceof RedisClient); -// } -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// minimizeConnections: undefined // reset to default -// } -// }); - -// testUtils.testWithCluster('getSlotMaster should be backwards competiable (without `minimizeConnections`)', async cluster => { -// const master = cluster.getSlotMaster(0); -// assert.equal(typeof master.id, 'string'); -// assert.ok(master.client instanceof RedisClient); -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// minimizeConnections: undefined // reset to default -// } -// }); - -// testUtils.testWithCluster('should throw CROSSSLOT error', async cluster => { -// await assert.rejects(cluster.mGet(['a', 'b'])); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('should send commands with commandOptions to correct cluster slot (without redirections)', async cluster => { -// // 'a' and 'b' hash to different cluster slots (see previous unit test) -// // -> maxCommandRedirections 0: rejects on MOVED/ASK reply -// await cluster.set(commandOptions({ isolated: true }), 'a', '1'), -// await cluster.set(commandOptions({ isolated: true }), 'b', '2'), - -// assert.equal(await cluster.get('a'), '1'); -// assert.equal(await cluster.get('b'), '2'); -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// maxCommandRedirections: 0 -// } -// }); - -// describe('minimizeConnections', () => { -// testUtils.testWithCluster('false', async cluster => { -// for (const master of cluster.masters) { -// assert.ok(master.client instanceof RedisClient); -// } -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// minimizeConnections: false -// } -// }); - -// testUtils.testWithCluster('true', async cluster => { -// for (const master of cluster.masters) { -// assert.equal(master.client, undefined); -// } -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// clusterConfiguration: { -// minimizeConnections: true -// } -// }); -// }); - -// describe('PubSub', () => { -// testUtils.testWithCluster('subscribe & unsubscribe', async cluster => { -// const listener = spy(); - -// await cluster.subscribe('channel', listener); - -// await Promise.all([ -// waitTillBeenCalled(listener), -// cluster.publish('channel', 'message') -// ]); - -// assert.ok(listener.calledOnceWithExactly('message', 'channel')); - -// await cluster.unsubscribe('channel', listener); - -// assert.equal(cluster.pubSubNode, undefined); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('psubscribe & punsubscribe', async cluster => { -// const listener = spy(); - -// await cluster.pSubscribe('channe*', listener); - -// await Promise.all([ -// waitTillBeenCalled(listener), -// cluster.publish('channel', 'message') -// ]); - -// assert.ok(listener.calledOnceWithExactly('message', 'channel')); - -// await cluster.pUnsubscribe('channe*', listener); - -// assert.equal(cluster.pubSubNode, undefined); -// }, GLOBAL.CLUSTERS.OPEN); - -// testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { -// const listener = spy(); -// await cluster.subscribe('channel', listener); - -// assert.ok(cluster.pubSubNode); -// const [ migrating, importing ] = cluster.masters[0].address === cluster.pubSubNode.address ? -// cluster.masters : -// [cluster.masters[1], cluster.masters[0]], -// [ migratingClient, importingClient ] = await Promise.all([ -// cluster.nodeClient(migrating), -// cluster.nodeClient(importing) -// ]); - -// const range = cluster.slots[0].master === migrating ? { -// key: 'bar', // 5061 -// start: 0, -// end: 8191 -// } : { -// key: 'foo', // 12182 -// start: 8192, -// end: 16383 -// }; - -// await Promise.all([ -// migratingClient.clusterDelSlotsRange(range), -// importingClient.clusterDelSlotsRange(range), -// importingClient.clusterAddSlotsRange(range) -// ]); - -// // wait for migrating node to be notified about the new topology -// while ((await migratingClient.clusterInfo()).state !== 'ok') { -// await setTimeout(50); -// } - -// // make sure to cause `MOVED` error -// await cluster.get(range.key); - -// await Promise.all([ -// cluster.publish('channel', 'message'), -// waitTillBeenCalled(listener) -// ]); - -// assert.ok(listener.calledOnceWithExactly('message', 'channel')); -// }, { -// serverArguments: [], -// numberOfMasters: 2, -// minimumDockerVersion: [7] -// }); - -// testUtils.testWithCluster('ssubscribe & sunsubscribe', async cluster => { -// const listener = spy(); - -// await cluster.sSubscribe('channel', listener); - -// await Promise.all([ -// waitTillBeenCalled(listener), -// cluster.sPublish('channel', 'message') -// ]); - -// assert.ok(listener.calledOnceWithExactly('message', 'channel')); - -// await cluster.sUnsubscribe('channel', listener); - -// // 10328 is the slot of `channel` -// assert.equal(cluster.slots[10328].master.pubSubClient, undefined); -// }, { -// ...GLOBAL.CLUSTERS.OPEN, -// minimumDockerVersion: [7] -// }); - -// testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { -// const SLOT = 10328, -// migrating = cluster.slots[SLOT].master, -// importing = cluster.masters.find(master => master !== migrating)!, -// [ migratingClient, importingClient ] = await Promise.all([ -// cluster.nodeClient(migrating), -// cluster.nodeClient(importing) -// ]); - -// await Promise.all([ -// migratingClient.clusterDelSlots(SLOT), -// importingClient.clusterDelSlots(SLOT), -// importingClient.clusterAddSlots(SLOT) -// ]); - -// // wait for migrating node to be notified about the new topology -// while ((await migratingClient.clusterInfo()).state !== 'ok') { -// await setTimeout(50); -// } - -// const listener = spy(); - -// // will trigger `MOVED` error -// await cluster.sSubscribe('channel', listener); - -// await Promise.all([ -// waitTillBeenCalled(listener), -// cluster.sPublish('channel', 'message') -// ]); - -// assert.ok(listener.calledOnceWithExactly('message', 'channel')); -// }, { -// serverArguments: [], -// minimumDockerVersion: [7] -// }); -// }); -// }); +import { SQUARE_SCRIPT } from '../client/index.spec'; +import { RootNodesUnavailableError } from '../errors'; +import { spy } from 'sinon'; +// import { setTimeout } from 'node:timers/promises'; +import RedisClient from '../client'; + +describe('Cluster', () => { + testUtils.testWithCluster('sendCommand', async cluster => { + assert.equal( + await cluster.sendCommand(undefined, true, ['PING']), + 'PONG' + ); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('isOpen', async cluster => { + assert.equal(cluster.isOpen, true); + await cluster.destroy(); + assert.equal(cluster.isOpen, false); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('connect should throw if already connected', async cluster => { + await assert.rejects(cluster.connect()); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('multi', async cluster => { + const key = 'key'; + assert.deepEqual( + await cluster.multi() + .set(key, 'value') + .get(key) + .exec(), + ['OK', 'value'] + ); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('scripts', async cluster => { + const [, reply] = await Promise.all([ + cluster.set('key', '2'), + cluster.square('key') + ]); + + assert.equal(reply, 4); + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + scripts: { + square: SQUARE_SCRIPT + } + } + }); + + it('should throw RootNodesUnavailableError', async () => { + const cluster = RedisCluster.create({ + rootNodes: [] + }); + + try { + await assert.rejects( + cluster.connect(), + RootNodesUnavailableError + ); + } catch (err) { + await cluster.disconnect(); + throw err; + } + }); + + // testUtils.testWithCluster('should handle live resharding', async cluster => { + // const slot = 12539, + // key = 'key', + // value = 'value'; + // await cluster.set(key, value); + + // const importing = cluster.slots[0].master, + // migrating = cluster.slots[slot].master, + // [importingClient, migratingClient] = await Promise.all([ + // cluster.nodeClient(importing), + // cluster.nodeClient(migrating) + // ]); + + // await Promise.all([ + // importingClient.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, migrating.id), + // migratingClient.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, importing.id) + // ]); + + // // should be able to get the key from the migrating node + // assert.equal( + // await cluster.get(key), + // value + // ); + + // await migratingClient.migrate( + // importing.host, + // importing.port, + // key, + // 0, + // 10 + // ); + + // // should be able to get the key from the importing node using `ASKING` + // assert.equal( + // await cluster.get(key), + // value + // ); + + // await Promise.all([ + // importingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), + // migratingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), + // ]); + + // // should handle `MOVED` errors + // assert.equal( + // await cluster.get(key), + // value + // ); + // }, { + // serverArguments: [], + // numberOfMasters: 2 + // }); + + testUtils.testWithCluster('getRandomNode should spread the the load evenly', async cluster => { + const totalNodes = cluster.masters.length + cluster.replicas.length, + ids = new Set(); + for (let i = 0; i < totalNodes; i++) { + ids.add(cluster.getRandomNode().id); + } + + assert.equal(ids.size, totalNodes); + }, GLOBAL.CLUSTERS.WITH_REPLICAS); + + testUtils.testWithCluster('getSlotRandomNode should spread the the load evenly', async cluster => { + const totalNodes = 1 + cluster.slots[0].replicas!.length, + ids = new Set(); + for (let i = 0; i < totalNodes; i++) { + ids.add(cluster.getSlotRandomNode(0).id); + } + + assert.equal(ids.size, totalNodes); + }, GLOBAL.CLUSTERS.WITH_REPLICAS); + + testUtils.testWithCluster('cluster topology', async cluster => { + assert.equal(cluster.slots.length, 16384); + const { numberOfMasters, numberOfReplicas } = GLOBAL.CLUSTERS.WITH_REPLICAS; + assert.equal(cluster.shards.length, numberOfMasters); + assert.equal(cluster.masters.length, numberOfMasters); + assert.equal(cluster.replicas.length, numberOfReplicas * numberOfMasters); + assert.equal(cluster.nodeByAddress.size, numberOfMasters + numberOfMasters * numberOfReplicas); + }, GLOBAL.CLUSTERS.WITH_REPLICAS); + + testUtils.testWithCluster('getMasters should be backwards competiable (without `minimizeConnections`)', async cluster => { + const masters = cluster.getMasters(); + assert.ok(Array.isArray(masters)); + for (const master of masters) { + assert.equal(typeof master.id, 'string'); + assert.ok(master.client instanceof RedisClient); + } + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + minimizeConnections: undefined // reset to default + } + }); + + testUtils.testWithCluster('getSlotMaster should be backwards competiable (without `minimizeConnections`)', async cluster => { + const master = cluster.getSlotMaster(0); + assert.equal(typeof master.id, 'string'); + assert.ok(master.client instanceof RedisClient); + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + minimizeConnections: undefined // reset to default + } + }); + + testUtils.testWithCluster('should throw CROSSSLOT error', async cluster => { + await assert.rejects(cluster.mGet(['a', 'b'])); + }, GLOBAL.CLUSTERS.OPEN); + + describe('minimizeConnections', () => { + testUtils.testWithCluster('false', async cluster => { + for (const master of cluster.masters) { + assert.ok(master.client instanceof RedisClient); + } + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + minimizeConnections: false + } + }); + + testUtils.testWithCluster('true', async cluster => { + for (const master of cluster.masters) { + assert.equal(master.client, undefined); + } + }, { + ...GLOBAL.CLUSTERS.OPEN, + clusterConfiguration: { + minimizeConnections: true + } + }); + }); + + describe('PubSub', () => { + testUtils.testWithCluster('subscribe & unsubscribe', async cluster => { + const listener = spy(); + + await cluster.subscribe('channel', listener); + + await Promise.all([ + waitTillBeenCalled(listener), + cluster.publish('channel', 'message') + ]); + + assert.ok(listener.calledOnceWithExactly('message', 'channel')); + + await cluster.unsubscribe('channel', listener); + + assert.equal(cluster.pubSubNode, undefined); + }, GLOBAL.CLUSTERS.OPEN); + + testUtils.testWithCluster('psubscribe & punsubscribe', async cluster => { + const listener = spy(); + + await cluster.pSubscribe('channe*', listener); + + await Promise.all([ + waitTillBeenCalled(listener), + cluster.publish('channel', 'message') + ]); + + assert.ok(listener.calledOnceWithExactly('message', 'channel')); + + await cluster.pUnsubscribe('channe*', listener); + + assert.equal(cluster.pubSubNode, undefined); + }, GLOBAL.CLUSTERS.OPEN); + + // testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { + // const listener = spy(); + // await cluster.subscribe('channel', listener); + + // assert.ok(cluster.pubSubNode); + // const [migrating, importing] = cluster.masters[0].address === cluster.pubSubNode.address ? + // cluster.masters : + // [cluster.masters[1], cluster.masters[0]], + // [migratingClient, importingClient] = await Promise.all([ + // cluster.nodeClient(migrating), + // cluster.nodeClient(importing) + // ]); + + // const range = cluster.slots[0].master === migrating ? { + // key: 'bar', // 5061 + // start: 0, + // end: 8191 + // } : { + // key: 'foo', // 12182 + // start: 8192, + // end: 16383 + // }; + + // await Promise.all([ + // migratingClient.clusterDelSlotsRange(range), + // importingClient.clusterDelSlotsRange(range), + // importingClient.clusterAddSlotsRange(range) + // ]); + + // // wait for migrating node to be notified about the new topology + // while ((await migratingClient.clusterInfo()).state !== 'ok') { + // await setTimeout(50); + // } + + // // make sure to cause `MOVED` error + // await cluster.get(range.key); + + // await Promise.all([ + // cluster.publish('channel', 'message'), + // waitTillBeenCalled(listener) + // ]); + + // assert.ok(listener.calledOnceWithExactly('message', 'channel')); + // }, { + // serverArguments: [], + // numberOfMasters: 2, + // minimumDockerVersion: [7] + // }); + + testUtils.testWithCluster('ssubscribe & sunsubscribe', async cluster => { + const listener = spy(); + + await cluster.sSubscribe('channel', listener); + + await Promise.all([ + waitTillBeenCalled(listener), + cluster.sPublish('channel', 'message') + ]); + + assert.ok(listener.calledOnceWithExactly('message', 'channel')); + + await cluster.sUnsubscribe('channel', listener); + + // 10328 is the slot of `channel` + assert.equal(cluster.slots[10328].master.pubSubClient, undefined); + }, { + ...GLOBAL.CLUSTERS.OPEN, + minimumDockerVersion: [7] + }); + + // testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { + // const SLOT = 10328, + // migrating = cluster.slots[SLOT].master, + // importing = cluster.masters.find(master => master !== migrating)!, + // [migratingClient, importingClient] = await Promise.all([ + // cluster.nodeClient(migrating), + // cluster.nodeClient(importing) + // ]); + + // await Promise.all([ + // migratingClient.clusterDelSlots(SLOT), + // importingClient.clusterDelSlots(SLOT), + // importingClient.clusterAddSlots(SLOT) + // ]); + + // // wait for migrating node to be notified about the new topology + // while ((await migratingClient.clusterInfo()).state !== 'ok') { + // await setTimeout(50); + // } + + // const listener = spy(); + + // // will trigger `MOVED` error + // await cluster.sSubscribe('channel', listener); + + // await Promise.all([ + // waitTillBeenCalled(listener), + // cluster.sPublish('channel', 'message') + // ]); + + // assert.ok(listener.calledOnceWithExactly('message', 'channel')); + // }, { + // serverArguments: [], + // minimumDockerVersion: [7] + // }); + }); +}); diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index d52ad944975..cc0e895ade0 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -1,6 +1,6 @@ import { RedisClientOptions, RedisClientType } from '../client'; import { CommandOptions } from '../client/commands-queue'; -import { Command, CommandArguments, CommanderConfig, CommandPolicies, CommandWithPoliciesSignature, TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; +import { Command, CommandArguments, CommanderConfig, CommandSignature, /*CommandPolicies, CommandWithPoliciesSignature,*/ TypeMapping, RedisArgument, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions } from '../RESP/types'; import COMMANDS from '../commands'; import { EventEmitter } from 'node:events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; @@ -65,12 +65,48 @@ export interface RedisClusterOptions< nodeAddressMap?: NodeAddressMap; } +// remove once request & response policies are ready +type ClusterCommand< + NAME extends PropertyKey, + COMMAND extends Command +> = COMMAND['FIRST_KEY_INDEX'] extends undefined ? ( + COMMAND['IS_FORWARD_COMMAND'] extends true ? NAME : never +) : NAME; + +// CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING, POLICIES> type WithCommands< RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping, - // POLICIES extends CommandPolicies + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof typeof COMMANDS as ClusterCommand]: CommandSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING>; +}; + +type WithModules< + M extends RedisModules, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping > = { -[P in keyof typeof COMMANDS]: CommandWithPoliciesSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING, POLICIES>; + [P in keyof M]: { + [C in keyof M[P] as ClusterCommand]: CommandSignature; + }; +}; + +type WithFunctions< + F extends RedisFunctions, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [L in keyof F]: { + [C in keyof F[L] as ClusterCommand]: CommandSignature; + }; +}; + +type WithScripts< + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof S as ClusterCommand]: CommandSignature; }; export type RedisClusterType< @@ -80,17 +116,22 @@ export type RedisClusterType< RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {}, // POLICIES extends CommandPolicies = {} -> = RedisCluster & WithCommands; -// & WithModules & WithFunctions & WithScripts +> = ( + RedisCluster & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); export interface ClusterCommandOptions< - TYPE_MAPPING extends TypeMapping = TypeMapping, - POLICIES extends CommandPolicies = CommandPolicies + TYPE_MAPPING extends TypeMapping = TypeMapping + // POLICIES extends CommandPolicies = CommandPolicies > extends CommandOptions { - policies?: POLICIES; + // policies?: POLICIES; } -type ProxyCluster = RedisCluster; +type ProxyCluster = RedisCluster; type NamespaceProxyCluster = { self: ProxyCluster }; @@ -100,20 +141,30 @@ export default class RedisCluster< S extends RedisScripts, RESP extends RespVersions, TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + // POLICIES extends CommandPolicies > extends EventEmitter { static extractFirstKey( command: C, args: Parameters, redisArgs: Array - ): RedisArgument | undefined { - if (command.FIRST_KEY_INDEX === undefined) { - return undefined; - } else if (typeof command.FIRST_KEY_INDEX === 'number') { - return redisArgs[command.FIRST_KEY_INDEX]; + ) { + let key: RedisArgument | undefined; + switch (typeof command.FIRST_KEY_INDEX) { + case 'number': + key = redisArgs[command.FIRST_KEY_INDEX]; + break; + + case 'function': + key = command.FIRST_KEY_INDEX(...args); + break; + } + + // TODO: remove once request & response policies are ready + if (key === undefined && !command.IS_FORWARD_COMMAND) { + throw new Error('TODO'); } - return command.FIRST_KEY_INDEX(...args); + return key; } private static _createCommand(command: Command, resp: RespVersions) { @@ -130,7 +181,7 @@ export default class RedisCluster< command.IS_READ_ONLY, redisArgs, this._commandOptions, - command.POLICIES + // command.POLICIES ); return transformReply ? @@ -153,7 +204,7 @@ export default class RedisCluster< command.IS_READ_ONLY, redisArgs, this.self._commandOptions, - command.POLICIES + // command.POLICIES ); return transformReply ? @@ -167,18 +218,18 @@ export default class RedisCluster< transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyCluster, ...args: Array) { const fnArgs = fn.transformArguments(...args), - redisArgs = prefix.concat(fnArgs), firstKey = RedisCluster.extractFirstKey( fn, - fnArgs, - redisArgs + args, + fnArgs ), + redisArgs = prefix.concat(fnArgs), reply = await this.self.sendCommand( firstKey, fn.IS_READ_ONLY, redisArgs, this.self._commandOptions, - fn.POLICIES + // fn.POLICIES ); return transformReply ? @@ -192,18 +243,19 @@ export default class RedisCluster< transformReply = getTransformReply(script, resp); return async function (this: ProxyCluster, ...args: Array) { const scriptArgs = script.transformArguments(...args), - redisArgs = prefix.concat(scriptArgs), firstKey = RedisCluster.extractFirstKey( script, - scriptArgs, - redisArgs + args, + scriptArgs ), - reply = await this.sendCommand( + redisArgs = prefix.concat(scriptArgs), + reply = await this.executeScript( + script, firstKey, script.IS_READ_ONLY, redisArgs, this._commandOptions, - script.POLICIES + // script.POLICIES ); return transformReply ? @@ -218,8 +270,8 @@ export default class RedisCluster< S extends RedisScripts = {}, RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {}, - POLICIES extends CommandPolicies = {} - >(config?: ClusterCommander) { + // POLICIES extends CommandPolicies = {} + >(config?: ClusterCommander) { const Cluster = attachConfig({ BaseClass: RedisCluster, commands: COMMANDS, @@ -234,7 +286,7 @@ export default class RedisCluster< return (options?: Omit>) => { // returning a "proxy" to prevent the namespaces.self to leak between "proxies" - return Object.create(new Cluster(options)) as RedisClusterType; + return Object.create(new Cluster(options)) as RedisClusterType; }; } @@ -244,16 +296,16 @@ export default class RedisCluster< S extends RedisScripts = {}, RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {}, - POLICIES extends CommandPolicies = {} - >(options?: RedisClusterOptions) { + // POLICIES extends CommandPolicies = {} + >(options?: RedisClusterOptions) { return RedisCluster.factory(options)(options); } - private readonly _options: RedisClusterOptions; + private readonly _options: RedisClusterOptions; private readonly _slots: RedisClusterSlots; - private _commandOptions?: ClusterCommandOptions; + private _commandOptions?: ClusterCommandOptions; /** * An array of the cluster slots, each slot contain its `master` and `replicas`. @@ -306,7 +358,7 @@ export default class RedisCluster< return this._slots.isOpen; } - constructor(options: RedisClusterOptions) { + constructor(options: RedisClusterOptions) { super(); this._options = options; @@ -336,9 +388,9 @@ export default class RedisCluster< } withCommandOptions< - OPTIONS extends ClusterCommandOptions, + OPTIONS extends ClusterCommandOptions, TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + // POLICIES extends CommandPolicies >(options: OPTIONS) { const proxy = Object.create(this); proxy._commandOptions = options; @@ -347,8 +399,8 @@ export default class RedisCluster< F, S, RESP, - TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {}, - POLICIES extends CommandPolicies ? POLICIES : {} + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {} + // POLICIES extends CommandPolicies ? POLICIES : {} >; } @@ -367,8 +419,8 @@ export default class RedisCluster< F, S, RESP, - K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING, - K extends 'policies' ? V extends CommandPolicies ? V : {} : POLICIES + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING + // K extends 'policies' ? V extends CommandPolicies ? V : {} : POLICIES >; } @@ -379,15 +431,15 @@ export default class RedisCluster< return this._commandOptionsProxy('typeMapping', typeMapping); } - /** - * Override the `policies` command option - * TODO - */ - withPolicies (policies: POLICIES) { - return this._commandOptionsProxy('policies', policies); - } + // /** + // * Override the `policies` command option + // * TODO + // */ + // withPolicies (policies: POLICIES) { + // return this._commandOptionsProxy('policies', policies); + // } - async #execute( + private async _execute( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, fn: (client: RedisClientType) => Promise @@ -437,9 +489,9 @@ export default class RedisCluster< isReadonly: boolean | undefined, args: CommandArguments, options?: ClusterCommandOptions, - defaultPolicies?: CommandPolicies + // defaultPolicies?: CommandPolicies ): Promise { - return this.#execute( + return this._execute( firstKey, isReadonly, client => client.sendCommand(args, options) @@ -453,7 +505,7 @@ export default class RedisCluster< args: Array, options?: CommandOptions ) { - return this.#execute( + return this._execute( firstKey, isReadonly, client => client.executeScript(script, args, options) diff --git a/packages/client/lib/commands/CLUSTER_INFO.ts b/packages/client/lib/commands/CLUSTER_INFO.ts index c541de17294..4605efbe81a 100644 --- a/packages/client/lib/commands/CLUSTER_INFO.ts +++ b/packages/client/lib/commands/CLUSTER_INFO.ts @@ -1,4 +1,4 @@ -import { VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { VerbatimStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/CLUSTER_NODES.ts b/packages/client/lib/commands/CLUSTER_NODES.ts index 9166ce52f08..64dd5056232 100644 --- a/packages/client/lib/commands/CLUSTER_NODES.ts +++ b/packages/client/lib/commands/CLUSTER_NODES.ts @@ -1,4 +1,4 @@ -import { VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { VerbatimStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.ts index 7cb0eaae437..831c6bc5058 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, VerbatimStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/FCALL.spec.ts b/packages/client/lib/commands/FCALL.spec.ts index 06616ba1db3..35ae8c87c2b 100644 --- a/packages/client/lib/commands/FCALL.spec.ts +++ b/packages/client/lib/commands/FCALL.spec.ts @@ -17,13 +17,14 @@ describe('FCALL', () => { }); testUtils.testWithClient('client.fCall', async client => { - await loadMathFunction(client); + const [,, reply] = await Promise.all([ + loadMathFunction(client), + client.set('key', '2'), + client.fCall(MATH_FUNCTION.library.square.NAME, { + arguments: ['key'] + }) + ]); - assert.equal( - await client.fCall(MATH_FUNCTION.library.square.NAME, { - arguments: ['2'] - }), - 4 - ); + assert.equal(reply, 4); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FCALL_RO.spec.ts b/packages/client/lib/commands/FCALL_RO.spec.ts index 114430eb588..0b172d1e210 100644 --- a/packages/client/lib/commands/FCALL_RO.spec.ts +++ b/packages/client/lib/commands/FCALL_RO.spec.ts @@ -17,13 +17,14 @@ describe('FCALL_RO', () => { }); testUtils.testWithClient('client.fCallRo', async client => { - await loadMathFunction(client); + const [,, reply] = await Promise.all([ + loadMathFunction(client), + client.set('key', '2'), + client.fCallRo(MATH_FUNCTION.library.square.NAME, { + arguments: ['key'] + }) + ]); - assert.equal( - await client.fCallRo(MATH_FUNCTION.library.square.NAME, { - arguments: ['2'] - }), - 4 - ); + assert.equal(reply, 4); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts index a739d8f7f46..657f6d03257 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts @@ -11,16 +11,20 @@ export const MATH_FUNCTION = { `#!LUA name=math redis.register_function { function_name = "square", - callback = function(keys, args) return args[1] * args[1] end, + callback = function(keys, args) { + local number = redis.call('GET', keys[1]) + return number * number + }, flags = { "no-writes" } }`, library: { square: { NAME: 'square', IS_READ_ONLY: true, - NUMBER_OF_KEYS: 0, - transformArguments(number: number) { - return [number.toString()]; + NUMBER_OF_KEYS: 1, + FIRST_KEY_INDEX: 0, + transformArguments(key: string) { + return [key]; }, transformReply: undefined as unknown as () => NumberReply } diff --git a/packages/client/lib/commands/PUBLISH.ts b/packages/client/lib/commands/PUBLISH.ts index 1566651d9f1..e790ff16c4d 100644 --- a/packages/client/lib/commands/PUBLISH.ts +++ b/packages/client/lib/commands/PUBLISH.ts @@ -3,6 +3,7 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, + IS_FORWARD_COMMAND: true, transformArguments(channel: RedisArgument, message: RedisArgument) { return ['PUBLISH', channel, message]; }, diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 7ccc2a2d488..68e96307691 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -4,14 +4,13 @@ import { RedisScripts, RespVersions, TypeMapping, - CommandPolicies, + // CommandPolicies, createClient, RedisClientOptions, RedisClientType, createCluster, RedisClusterOptions, - RedisClusterType, - RESP_TYPES + RedisClusterType } from '@redis/client/index'; import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers'; import yargs from 'yargs'; @@ -44,11 +43,11 @@ interface ClusterTestOptions< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + TYPE_MAPPING extends TypeMapping + // POLICIES extends CommandPolicies > extends CommonTestOptions { serverArguments: Array; - clusterConfiguration?: Partial>; + clusterConfiguration?: Partial>; numberOfMasters?: number; numberOfReplicas?: number; } @@ -58,11 +57,11 @@ interface AllTestOptions< F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies + TYPE_MAPPING extends TypeMapping + // POLICIES extends CommandPolicies > { client: ClientTestOptions; - cluster: ClusterTestOptions; + cluster: ClusterTestOptions; } interface Version { @@ -197,9 +196,9 @@ export default class TestUtils { F extends RedisFunctions, S extends RedisScripts, RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping, - POLICIES extends CommandPolicies - >(cluster: RedisClusterType): Promise { + TYPE_MAPPING extends TypeMapping + // POLICIES extends CommandPolicies + >(cluster: RedisClusterType): Promise { return Promise.all( cluster.masters.map(async ({ client }) => { if (client) { @@ -214,12 +213,12 @@ export default class TestUtils { F extends RedisFunctions = {}, S extends RedisScripts = {}, RESP extends RespVersions = 2, - TYPE_MAPPING extends TypeMapping = {}, - POLICIES extends CommandPolicies = {} + TYPE_MAPPING extends TypeMapping = {} + // POLICIES extends CommandPolicies = {} >( title: string, - fn: (cluster: RedisClusterType) => unknown, - options: ClusterTestOptions + fn: (cluster: RedisClusterType) => unknown, + options: ClusterTestOptions ): void { let dockersPromise: ReturnType; if (this.isVersionGreaterThan(options.minimumDockerVersion)) { @@ -267,12 +266,12 @@ export default class TestUtils { F extends RedisFunctions = {}, S extends RedisScripts = {}, RESP extends RespVersions = 2, - TYPE_MAPPING extends TypeMapping = {}, - POLICIES extends CommandPolicies = {} + TYPE_MAPPING extends TypeMapping = {} + // POLICIES extends CommandPolicies = {} >( title: string, - fn: (client: RedisClientType | RedisClusterType) => unknown, - options: AllTestOptions + fn: (client: RedisClientType | RedisClusterType) => unknown, + options: AllTestOptions ) { this.testWithClient(`client.${title}`, fn, options.client); this.testWithCluster(`cluster.${title}`, fn, options.cluster); From 98ab197ee774b80d4508610eddfa1882507b9254 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 17:20:09 -0400 Subject: [PATCH 228/325] update package.json engines.node version to 18 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index a79e51a2652..d3f30474089 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -21,7 +21,7 @@ "sinon": "^15.2.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "repository": { "type": "git", From 0e51765475b874498b00417ebccf6f8adc755356 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 17:52:09 -0400 Subject: [PATCH 229/325] Update tests.yml --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ee937625c3b..4a43dbebf06 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: node-version: ['18', '20'] - redis-version: ['5', '6.0', '6.2', '7.0', '7.2-rc'] + redis-version: ['5', '6.0', '6.2', '7.0', '7.2'] steps: - uses: actions/checkout@v3 with: From b5d580c3995cf7d1332b949c1a6c0da5b26f592b Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Sep 2023 19:08:29 -0400 Subject: [PATCH 230/325] Upgrade actions/checkout --- .github/workflows/codeql.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3004337c278..47c82baea2c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -38,7 +38,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 8f1a1cec945..a8c22752423 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -10,7 +10,7 @@ jobs: documentation: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 - name: Use Node.js diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4a43dbebf06..d99eb2adf81 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: node-version: ['18', '20'] redis-version: ['5', '6.0', '6.2', '7.0', '7.2'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 1 - name: Use Node.js ${{ matrix.node-version }} From 099f16e45fbb88a7f3744e61c0823c8f2c14fcbd Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 19 Sep 2023 19:23:24 -0400 Subject: [PATCH 231/325] "forward port" changes from 4.6.9 --- examples/dump-and-restore.js | 22 +-- .../lib/commands/CLIENT_NO-TOUCH.spec.ts | 42 +++--- .../client/lib/commands/CLIENT_NO-TOUCH.ts | 18 ++- .../lib/commands/CLUSTER_MYSHARDID.spec.ts | 30 ++-- .../client/lib/commands/CLUSTER_MYSHARDID.ts | 12 +- .../client/lib/commands/LATENCY_GRAPH.spec.ts | 10 +- packages/client/lib/commands/LATENCY_GRAPH.ts | 2 +- .../lib/commands/LATENCY_HISTORY.spec.ts | 44 +++--- .../client/lib/commands/LATENCY_HISTORY.ts | 52 ++++--- .../lib/commands/LATENCY_LATEST.spec.ts | 10 +- .../lib/commands/PUBSUB_SHARDNUMSUB.spec.ts | 76 +++++----- .../client/lib/commands/PUBSUB_SHARDNUMSUB.ts | 32 ++--- packages/client/lib/commands/RESTORE.spec.ts | 132 ++++++++++-------- packages/client/lib/commands/RESTORE.ts | 39 +++--- packages/client/lib/commands/index.ts | 21 +++ packages/redis/README.md | 8 +- 16 files changed, 298 insertions(+), 252 deletions(-) diff --git a/examples/dump-and-restore.js b/examples/dump-and-restore.js index 081e44f9f9a..c2ee7f1e199 100644 --- a/examples/dump-and-restore.js +++ b/examples/dump-and-restore.js @@ -1,22 +1,26 @@ // This example demonstrates the use of the DUMP and RESTORE commands -import { commandOptions, createClient } from 'redis'; +import { createClient, RESP_TYPES } from 'redis'; -const client = createClient(); -await client.connect(); +const client = await createClient({ + commandOptions: { + typeMapping: { + [RESP_TYPES.BLOB_STRING]: Buffer + } + } +}).on('error', err => { + console.log('Redis Client Error', err); +}).connect(); // DUMP a specific key into a local variable -const dump = await client.dump( - commandOptions({ returnBuffers: true }), - 'source' -); +const dump = await client.dump('source'); // RESTORE into a new key await client.restore('destination', 0, dump); // RESTORE and REPLACE an existing key await client.restore('destination', 0, dump, { - REPLACE: true + REPLACE: true }); -await client.quit(); +await client.close(); diff --git a/packages/client/lib/commands/CLIENT_NO-TOUCH.spec.ts b/packages/client/lib/commands/CLIENT_NO-TOUCH.spec.ts index 80ee0ada1fd..e58c22d9c6e 100644 --- a/packages/client/lib/commands/CLIENT_NO-TOUCH.spec.ts +++ b/packages/client/lib/commands/CLIENT_NO-TOUCH.spec.ts @@ -1,30 +1,30 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLIENT_NO-TOUCH'; +import CLIENT_NO_TOUCH from './CLIENT_NO-TOUCH'; describe('CLIENT NO-TOUCH', () => { - testUtils.isVersionGreaterThanHook([7, 2]); + testUtils.isVersionGreaterThanHook([7, 2]); - describe('transformArguments', () => { - it('true', () => { - assert.deepEqual( - transformArguments(true), - ['CLIENT', 'NO-TOUCH', 'ON'] - ); - }); + describe('transformArguments', () => { + it('true', () => { + assert.deepEqual( + CLIENT_NO_TOUCH.transformArguments(true), + ['CLIENT', 'NO-TOUCH', 'ON'] + ); + }); - it('false', () => { - assert.deepEqual( - transformArguments(false), - ['CLIENT', 'NO-TOUCH', 'OFF'] - ); - }); + it('false', () => { + assert.deepEqual( + CLIENT_NO_TOUCH.transformArguments(false), + ['CLIENT', 'NO-TOUCH', 'OFF'] + ); }); + }); - testUtils.testWithClient('client.clientNoTouch', async client => { - assert.equal( - await client.clientNoTouch(true), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.clientNoTouch', async client => { + assert.equal( + await client.clientNoTouch(true), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/CLIENT_NO-TOUCH.ts b/packages/client/lib/commands/CLIENT_NO-TOUCH.ts index d11f693dbab..e526be17667 100644 --- a/packages/client/lib/commands/CLIENT_NO-TOUCH.ts +++ b/packages/client/lib/commands/CLIENT_NO-TOUCH.ts @@ -1,11 +1,15 @@ -import { RedisCommandArguments } from '.'; +import { SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments(value: boolean): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(value: boolean) { return [ - 'CLIENT', - 'NO-TOUCH', - value ? 'ON' : 'OFF' + 'CLIENT', + 'NO-TOUCH', + value ? 'ON' : 'OFF' ]; -} + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; -export declare function transformReply(): 'OK' | Buffer; diff --git a/packages/client/lib/commands/CLUSTER_MYSHARDID.spec.ts b/packages/client/lib/commands/CLUSTER_MYSHARDID.spec.ts index 180289870ca..e64f2e3777a 100644 --- a/packages/client/lib/commands/CLUSTER_MYSHARDID.spec.ts +++ b/packages/client/lib/commands/CLUSTER_MYSHARDID.spec.ts @@ -1,22 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CLUSTER_MYSHARDID'; +import CLUSTER_MYSHARDID from './CLUSTER_MYSHARDID'; describe('CLUSTER MYSHARDID', () => { - testUtils.isVersionGreaterThanHook([7, 2]); + testUtils.isVersionGreaterThanHook([7, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments(), - ['CLUSTER', 'MYSHARDID'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + CLUSTER_MYSHARDID.transformArguments(), + ['CLUSTER', 'MYSHARDID'] + ); + }); - testUtils.testWithCluster('clusterNode.clusterMyShardId', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterMyShardId(), - 'string' - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testWithCluster('clusterNode.clusterMyShardId', async cluster => { + const client = await cluster.nodeClient(cluster.masters[0]); + assert.equal( + typeof await client.clusterMyShardId(), + 'string' + ); + }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_MYSHARDID.ts b/packages/client/lib/commands/CLUSTER_MYSHARDID.ts index 1c4f8b82f56..5e59b7221a8 100644 --- a/packages/client/lib/commands/CLUSTER_MYSHARDID.ts +++ b/packages/client/lib/commands/CLUSTER_MYSHARDID.ts @@ -1,7 +1,11 @@ -export const IS_READ_ONLY = true; +import { BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export function transformArguments() { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments() { return ['CLUSTER', 'MYSHARDID']; -} + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; -export declare function transformReply(): string | Buffer; diff --git a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts index 55d98d38234..03ad8e2c886 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.spec.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.spec.ts @@ -15,14 +15,12 @@ describe('LATENCY GRAPH', () => { }); testUtils.testWithClient('client.latencyGraph', async client => { - await Promise.all([ + const [,, reply] = await Promise.all([ client.configSet('latency-monitor-threshold', '1'), - client.sendCommand(['DEBUG', 'SLEEP', '0.001']) + client.sendCommand(['DEBUG', 'SLEEP', '0.001']), + client.latencyGraph('command') ]); - assert.equal( - typeof await client.latencyGraph('command'), - 'string' - ); + assert.equal(typeof reply, 'string'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LATENCY_GRAPH.ts b/packages/client/lib/commands/LATENCY_GRAPH.ts index c2fdbbd187e..7d5f54288b6 100644 --- a/packages/client/lib/commands/LATENCY_GRAPH.ts +++ b/packages/client/lib/commands/LATENCY_GRAPH.ts @@ -1,4 +1,4 @@ -import { SimpleStringReply, Command, BlobStringReply } from '../RESP/types'; +import { BlobStringReply, Command } from '../RESP/types'; export const LATENCY_EVENTS = { ACTIVE_DEFRAG_CYCLE: 'active-defrag-cycle', diff --git a/packages/client/lib/commands/LATENCY_HISTORY.spec.ts b/packages/client/lib/commands/LATENCY_HISTORY.spec.ts index e79e969b261..509c856e28f 100644 --- a/packages/client/lib/commands/LATENCY_HISTORY.spec.ts +++ b/packages/client/lib/commands/LATENCY_HISTORY.spec.ts @@ -1,26 +1,26 @@ -import {strict as assert} from 'assert'; -import testUtils, {GLOBAL} from '../test-utils'; -import { transformArguments } from './LATENCY_HISTORY'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import LATENCY_HISTORY from './LATENCY_HISTORY'; describe('LATENCY HISTORY', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('command'), - ['LATENCY', 'HISTORY', 'command'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + LATENCY_HISTORY.transformArguments('command'), + ['LATENCY', 'HISTORY', 'command'] + ); + }); - testUtils.testWithClient('client.latencyHistory', async client => { - await Promise.all([ - client.configSet('latency-monitor-threshold', '100'), - client.sendCommand(['DEBUG', 'SLEEP', '1']) - ]); - - const latencyHisRes = await client.latencyHistory('command'); - assert.ok(Array.isArray(latencyHisRes)); - for (const [timestamp, latency] of latencyHisRes) { - assert.equal(typeof timestamp, 'number'); - assert.equal(typeof latency, 'number'); - } - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.latencyHistory', async client => { + const [,, reply] = await Promise.all([ + client.configSet('latency-monitor-threshold', '100'), + client.sendCommand(['DEBUG', 'SLEEP', '1']), + client.latencyHistory('command') + ]); + + assert.ok(Array.isArray(reply)); + for (const [timestamp, latency] of reply) { + assert.equal(typeof timestamp, 'number'); + assert.equal(typeof latency, 'number'); + } + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/LATENCY_HISTORY.ts b/packages/client/lib/commands/LATENCY_HISTORY.ts index c0b1964553e..df5b1772b2d 100644 --- a/packages/client/lib/commands/LATENCY_HISTORY.ts +++ b/packages/client/lib/commands/LATENCY_HISTORY.ts @@ -1,27 +1,33 @@ -export type EventType = ( - 'active-defrag-cycle' | - 'aof-fsync-always' | - 'aof-stat' | - 'aof-rewrite-diff-write' | - 'aof-rename' | - 'aof-write' | - 'aof-write-active-child' | - 'aof-write-alone' | - 'aof-write-pending-fsync' | - 'command' | - 'expire-cycle' | - 'eviction-cycle' | - 'eviction-del' | - 'fast-command' | - 'fork' | - 'rdb-unlink-temp-file' +import { ArrayReply, TuplesReply, NumberReply, Command } from '../RESP/types'; + +export type LatencyEventType = ( + 'active-defrag-cycle' | + 'aof-fsync-always' | + 'aof-stat' | + 'aof-rewrite-diff-write' | + 'aof-rename' | + 'aof-write' | + 'aof-write-active-child' | + 'aof-write-alone' | + 'aof-write-pending-fsync' | + 'command' | + 'expire-cycle' | + 'eviction-cycle' | + 'eviction-del' | + 'fast-command' | + 'fork' | + 'rdb-unlink-temp-file' ); -export function transformArguments(event: EventType) { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(event: LatencyEventType) { return ['LATENCY', 'HISTORY', event]; -} + }, + transformReply: undefined as unknown as () => ArrayReply> +} as const satisfies Command; -export declare function transformReply(): Array<[ - timestamp: number, - latency: number, -]>; diff --git a/packages/client/lib/commands/LATENCY_LATEST.spec.ts b/packages/client/lib/commands/LATENCY_LATEST.spec.ts index 58b3a6de64d..f85a3ccc8bd 100644 --- a/packages/client/lib/commands/LATENCY_LATEST.spec.ts +++ b/packages/client/lib/commands/LATENCY_LATEST.spec.ts @@ -11,13 +11,13 @@ describe('LATENCY LATEST', () => { }); testUtils.testWithClient('client.latencyLatest', async client => { - await Promise.all([ + const [,, reply] = await Promise.all([ client.configSet('latency-monitor-threshold', '100'), - client.sendCommand(['DEBUG', 'SLEEP', '1']) + client.sendCommand(['DEBUG', 'SLEEP', '1']), + client.latencyLatest() ]); - const latency = await client.latencyLatest(); - assert.ok(Array.isArray(latency)); - for (const [name, timestamp, latestLatency, allTimeLatency] of latency) { + assert.ok(Array.isArray(reply)); + for (const [name, timestamp, latestLatency, allTimeLatency] of reply) { assert.equal(typeof name, 'string'); assert.equal(typeof timestamp, 'number'); assert.equal(typeof latestLatency, 'number'); diff --git a/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.spec.ts b/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.spec.ts index fea1373b55d..e036a6eae5b 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.spec.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.spec.ts @@ -1,48 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './PUBSUB_SHARDNUMSUB'; +import PUBSUB_SHARDNUMSUB from './PUBSUB_SHARDNUMSUB'; describe('PUBSUB SHARDNUMSUB', () => { - testUtils.isVersionGreaterThanHook([7]); + testUtils.isVersionGreaterThanHook([7]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['PUBSUB', 'SHARDNUMSUB'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + PUBSUB_SHARDNUMSUB.transformArguments(), + ['PUBSUB', 'SHARDNUMSUB'] + ); + }); - it('string', () => { - assert.deepEqual( - transformArguments('channel'), - ['PUBSUB', 'SHARDNUMSUB', 'channel'] - ); - }); + it('string', () => { + assert.deepEqual( + PUBSUB_SHARDNUMSUB.transformArguments('channel'), + ['PUBSUB', 'SHARDNUMSUB', 'channel'] + ); + }); - it('array', () => { - assert.deepEqual( - transformArguments(['1', '2']), - ['PUBSUB', 'SHARDNUMSUB', '1', '2'] - ); - }); + it('array', () => { + assert.deepEqual( + PUBSUB_SHARDNUMSUB.transformArguments(['1', '2']), + ['PUBSUB', 'SHARDNUMSUB', '1', '2'] + ); }); + }); - testUtils.testWithClient('client.pubSubShardNumSub', async client => { - assert.deepEqual( - await client.pubSubShardNumSub(['foo', 'bar']), - Object.create(null, { - foo: { - value: 0, - configurable: true, - enumerable: true - }, - bar: { - value: 0, - configurable: true, - enumerable: true - } - }) - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.pubSubShardNumSub', async client => { + assert.deepEqual( + await client.pubSubShardNumSub(['foo', 'bar']), + Object.create(null, { + foo: { + value: 0, + configurable: true, + enumerable: true + }, + bar: { + value: 0, + configurable: true, + enumerable: true + } + }) + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.ts b/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.ts index 4d7f4d8a71e..0ef82477006 100644 --- a/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.ts +++ b/packages/client/lib/commands/PUBSUB_SHARDNUMSUB.ts @@ -1,24 +1,24 @@ -import { pushVerdictArguments } from './generic-transformers'; -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ArrayReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '../RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; -export const IS_READ_ONLY = true; - -export function transformArguments( - channels?: Array | RedisCommandArgument -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(channels?: RedisVariadicArgument) { const args = ['PUBSUB', 'SHARDNUMSUB']; - if (channels) return pushVerdictArguments(args, channels); + if (channels) return pushVariadicArguments(args, channels); return args; -} - -export function transformReply(rawReply: Array): Record { - const transformedReply = Object.create(null); + }, + transformReply(reply: UnwrapReply>) { + const transformedReply: Record = Object.create(null); - for (let i = 0; i < rawReply.length; i += 2) { - transformedReply[rawReply[i]] = rawReply[i + 1]; + for (let i = 0; i < reply.length; i += 2) { + transformedReply[(reply[i] as BlobStringReply).toString()] = reply[i + 1] as NumberReply; } - + return transformedReply; -} + } +} as const satisfies Command; + diff --git a/packages/client/lib/commands/RESTORE.spec.ts b/packages/client/lib/commands/RESTORE.spec.ts index 89d42f3d4de..6b814e7325a 100644 --- a/packages/client/lib/commands/RESTORE.spec.ts +++ b/packages/client/lib/commands/RESTORE.spec.ts @@ -1,74 +1,84 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './RESTORE'; +import RESTORE from './RESTORE'; +import { RESP_TYPES } from '../RESP/decoder'; describe('RESTORE', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', 0, 'value'), - ['RESTORE', 'key', '0', 'value'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value'), + ['RESTORE', 'key', '0', 'value'] + ); + }); - it('with REPLACE', () => { - assert.deepEqual( - transformArguments('key', 0, 'value', { - REPLACE: true - }), - ['RESTORE', 'key', '0', 'value', 'REPLACE'] - ); - }); + it('with REPLACE', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value', { + REPLACE: true + }), + ['RESTORE', 'key', '0', 'value', 'REPLACE'] + ); + }); - it('with ABSTTL', () => { - assert.deepEqual( - transformArguments('key', 0, 'value', { - ABSTTL: true - }), - ['RESTORE', 'key', '0', 'value', 'ABSTTL'] - ); - }); + it('with ABSTTL', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value', { + ABSTTL: true + }), + ['RESTORE', 'key', '0', 'value', 'ABSTTL'] + ); + }); - it('with IDLETIME', () => { - assert.deepEqual( - transformArguments('key', 0, 'value', { - IDLETIME: 1 - }), - ['RESTORE', 'key', '0', 'value', 'IDLETIME', '1'] - ); - }); + it('with IDLETIME', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value', { + IDLETIME: 1 + }), + ['RESTORE', 'key', '0', 'value', 'IDLETIME', '1'] + ); + }); - it('with FREQ', () => { - assert.deepEqual( - transformArguments('key', 0, 'value', { - FREQ: 1 - }), - ['RESTORE', 'key', '0', 'value', 'FREQ', '1'] - ); - }); + it('with FREQ', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value', { + FREQ: 1 + }), + ['RESTORE', 'key', '0', 'value', 'FREQ', '1'] + ); + }); - it('with REPLACE, ABSTTL, IDLETIME and FREQ', () => { - assert.deepEqual( - transformArguments('key', 0, 'value', { - REPLACE: true, - ABSTTL: true, - IDLETIME: 1, - FREQ: 2 - }), - ['RESTORE', 'key', '0', 'value', 'REPLACE', 'ABSTTL', 'IDLETIME', '1', 'FREQ', '2'] - ); - }); + it('with REPLACE, ABSTTL, IDLETIME and FREQ', () => { + assert.deepEqual( + RESTORE.transformArguments('key', 0, 'value', { + REPLACE: true, + ABSTTL: true, + IDLETIME: 1, + FREQ: 2 + }), + ['RESTORE', 'key', '0', 'value', 'REPLACE', 'ABSTTL', 'IDLETIME', '1', 'FREQ', '2'] + ); }); + }); - testUtils.testWithClient('client.restore', async client => { - const [, dump] = await Promise.all([ - client.set('source', 'value'), - client.dump(client.commandOptions({ returnBuffers: true }), 'source') - ]); + testUtils.testWithClient('client.restore', async client => { + const [, dump] = await Promise.all([ + client.set('source', 'value'), + client.dump('source') + ]); - assert.equal( - await client.restore('destination', 0, dump), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.restore('destination', 0, dump), + 'OK' + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + commandOptions: { + typeMapping: { + [RESP_TYPES.BLOB_STRING]: Buffer + } + } + } + }); }); diff --git a/packages/client/lib/commands/RESTORE.ts b/packages/client/lib/commands/RESTORE.ts index d9ac11c424b..b24c5b569f9 100644 --- a/packages/client/lib/commands/RESTORE.ts +++ b/packages/client/lib/commands/RESTORE.ts @@ -1,39 +1,40 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -export const FIRST_KEY_INDEX = 1; - -interface RestoreOptions { - REPLACE?: true; - ABSTTL?: true; - IDLETIME?: number; - FREQ?: number; +export interface RestoreOptions { + REPLACE?: boolean; + ABSTTL?: boolean; + IDLETIME?: number; + FREQ?: number; } -export function transformArguments( - key: RedisCommandArgument, +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + key: RedisArgument, ttl: number, - serializedValue: RedisCommandArgument, + serializedValue: RedisArgument, options?: RestoreOptions -): RedisCommandArguments { + ) { const args = ['RESTORE', key, ttl.toString(), serializedValue]; if (options?.REPLACE) { - args.push('REPLACE'); + args.push('REPLACE'); } if (options?.ABSTTL) { - args.push('ABSTTL'); + args.push('ABSTTL'); } if (options?.IDLETIME) { - args.push('IDLETIME', options.IDLETIME.toString()); + args.push('IDLETIME', options.IDLETIME.toString()); } if (options?.FREQ) { - args.push('FREQ', options.FREQ.toString()); + args.push('FREQ', options.FREQ.toString()); } return args; -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index af46502c908..30782981ab1 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -38,6 +38,7 @@ import CLIENT_INFO from './CLIENT_INFO'; import CLIENT_KILL from './CLIENT_KILL'; import CLIENT_LIST from './CLIENT_LIST'; import CLIENT_NO_EVICT from './CLIENT_NO-EVICT'; +import CLIENT_NO_TOUCH from './CLIENT_NO-TOUCH'; import CLIENT_PAUSE from './CLIENT_PAUSE'; import CLIENT_SETNAME from './CLIENT_SETNAME'; import CLIENT_TRACKING from './CLIENT_TRACKING'; @@ -59,6 +60,7 @@ import CLUSTER_KEYSLOT from './CLUSTER_KEYSLOT'; import CLUSTER_LINKS from './CLUSTER_LINKS'; import CLUSTER_MEET from './CLUSTER_MEET'; import CLUSTER_MYID from './CLUSTER_MYID'; +import CLUSTER_MYSHARDID from './CLUSTER_MYSHARDID'; import CLUSTER_NODES from './CLUSTER_NODES'; import CLUSTER_REPLICAS from './CLUSTER_REPLICAS'; import CLUSTER_REPLICATE from './CLUSTER_REPLICATE'; @@ -154,6 +156,7 @@ import KEYS from './KEYS'; import LASTSAVE from './LASTSAVE'; import LATENCY_DOCTOR from './LATENCY_DOCTOR'; import LATENCY_GRAPH from './LATENCY_GRAPH'; +import LATENCY_HISTORY from './LATENCY_HISTORY'; import LATENCY_LATEST from './LATENCY_LATEST'; import LCS_IDX_WITHMATCHLEN from './LCS_IDX_WITHMATCHLEN'; import LCS_IDX from './LCS_IDX'; @@ -205,11 +208,15 @@ import PUBLISH from './PUBLISH'; import PUBSUB_CHANNELS from './PUBSUB_CHANNELS'; import PUBSUB_NUMPAT from './PUBSUB_NUMPAT'; import PUBSUB_NUMSUB from './PUBSUB_NUMSUB'; +import PUBSUB_SHARDNUMSUB from './PUBSUB_SHARDNUMSUB'; import PUBSUB_SHARDCHANNELS from './PUBSUB_SHARDCHANNELS'; import RANDOMKEY from './RANDOMKEY'; import READONLY from './READONLY'; import RENAME from './RENAME'; import RENAMENX from './RENAMENX'; +import REPLICAOF from './REPLICAOF'; +import RESTORE_ASKING from './RESTORE-ASKING'; +import RESTORE from './RESTORE'; import ROLE from './ROLE'; import RPOP_COUNT from './RPOP_COUNT'; import RPOP from './RPOP'; @@ -405,6 +412,8 @@ export default { clientList: CLIENT_LIST, 'CLIENT_NO-EVICT': CLIENT_NO_EVICT, clientNoEvict: CLIENT_NO_EVICT, + 'CLIENT_NO-TOUCH': CLIENT_NO_TOUCH, + clientNoTouch: CLIENT_NO_TOUCH, CLIENT_PAUSE, clientPause: CLIENT_PAUSE, CLIENT_SETNAME, @@ -447,6 +456,8 @@ export default { clusterMeet: CLUSTER_MEET, CLUSTER_MYID, clusterMyId: CLUSTER_MYID, + CLUSTER_MYSHARDID, + clusterMyShardId: CLUSTER_MYSHARDID, CLUSTER_NODES, clusterNodes: CLUSTER_NODES, CLUSTER_REPLICAS, @@ -637,6 +648,8 @@ export default { latencyDoctor: LATENCY_DOCTOR, LATENCY_GRAPH, latencyGraph: LATENCY_GRAPH, + LATENCY_HISTORY, + latencyHistory: LATENCY_HISTORY, LATENCY_LATEST, latencyLatest: LATENCY_LATEST, LCS_IDX_WITHMATCHLEN, @@ -741,6 +754,8 @@ export default { pubSubNumPat: PUBSUB_NUMPAT, PUBSUB_NUMSUB, pubSubNumSub: PUBSUB_NUMSUB, + PUBSUB_SHARDNUMSUB, + pubSubShardNumSub: PUBSUB_SHARDNUMSUB, PUBSUB_SHARDCHANNELS, pubSubShardChannels: PUBSUB_SHARDCHANNELS, RANDOMKEY, @@ -751,6 +766,12 @@ export default { rename: RENAME, RENAMENX, renameNX: RENAMENX, + REPLICAOF, + replicaOf: REPLICAOF, + 'RESTORE-ASKING': RESTORE_ASKING, + restoreAsking: RESTORE_ASKING, + RESTORE, + restore: RESTORE, RPOP_COUNT, rPopCount: RPOP_COUNT, ROLE, diff --git a/packages/redis/README.md b/packages/redis/README.md index 3f05d8dc5a4..ce8b618e9b8 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -34,11 +34,9 @@ Looking for a high-level library to handle object mapping? See [redis-om-node](h ```javascript import { createClient } from 'redis'; -const client = createClient(); - -client.on('error', err => console.log('Redis Client Error', err)); - -await client.connect(); +const client = await createClient() + .on('error', err => console.log('Redis Client Error', err)) + .connect(); await client.set('key', 'value'); const value = await client.get('key'); From d62e332470b330e9d07a65f6497cb15bb5f15c0e Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 19 Sep 2023 19:25:38 -0400 Subject: [PATCH 232/325] upgrade deps --- package-lock.json | 246 +++++++++++++++++------------------ package.json | 4 +- packages/client/package.json | 2 +- packages/redis/package.json | 6 +- 4 files changed, 122 insertions(+), 136 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9fb5849aba5..716c2569802 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^6.6.0", - "@typescript-eslint/parser": "^6.6.0", + "@typescript-eslint/eslint-plugin": "^6.7.2", + "@typescript-eslint/parser": "^6.7.2", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", @@ -140,21 +140,21 @@ } }, "node_modules/@babel/core": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz", - "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", + "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", "@babel/generator": "^7.22.15", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.15", + "@babel/helper-module-transforms": "^7.22.20", "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.15", + "@babel/parser": "^7.22.16", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15", + "@babel/traverse": "^7.22.20", + "@babel/types": "^7.22.19", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -265,16 +265,16 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz", - "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", + "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.15" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -317,9 +317,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz", - "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -349,9 +349,9 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -434,9 +434,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.15.tgz", - "integrity": "sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -460,19 +460,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz", - "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz", + "integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", "@babel/generator": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15", + "@babel/parser": "^7.22.16", + "@babel/types": "^7.22.19", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -490,13 +490,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz", - "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==", + "version": "7.22.19", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", + "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.15", + "@babel/helper-validator-identifier": "^7.22.19", "to-fast-properties": "^2.0.0" }, "engines": { @@ -541,9 +541,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", + "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -574,9 +574,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", + "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", "dev": true, "peer": true, "engines": { @@ -915,6 +915,12 @@ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, "node_modules/@tsconfig/node18": { "version": "18.2.2", "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.2.tgz", @@ -934,16 +940,16 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==", + "version": "20.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz", + "integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==", "dev": true, "peer": true }, "node_modules/@types/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==", "dev": true }, "node_modules/@types/sinon": { @@ -977,16 +983,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", - "integrity": "sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", + "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/type-utils": "6.6.0", - "@typescript-eslint/utils": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/type-utils": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1012,15 +1018,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.6.0.tgz", - "integrity": "sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4" }, "engines": { @@ -1040,13 +1046,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz", - "integrity": "sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0" + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1057,13 +1063,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz", - "integrity": "sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", + "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.6.0", - "@typescript-eslint/utils": "6.6.0", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/utils": "6.7.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1084,9 +1090,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.6.0.tgz", - "integrity": "sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1097,13 +1103,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz", - "integrity": "sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/visitor-keys": "6.6.0", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1124,17 +1130,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.6.0", - "@typescript-eslint/types": "6.6.0", - "@typescript-eslint/typescript-estree": "6.6.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", "semver": "^7.5.4" }, "engines": { @@ -1149,12 +1155,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz", - "integrity": "sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.6.0", + "@typescript-eslint/types": "6.7.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1448,9 +1454,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001527", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001527.tgz", - "integrity": "sha512-YkJi7RwPgWtXVSgK4lG9AHH57nSzvvOp9MesgXmw4Q7n0C3H04L0foHqfxcmSAm5AcWb8dW9AYj2tR7/5GnddQ==", + "version": "1.0.30001538", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", + "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", "dev": true, "funding": [ { @@ -1698,9 +1704,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.508", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz", - "integrity": "sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==", + "version": "1.4.525", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.525.tgz", + "integrity": "sha512-GIZ620hDK4YmIqAWkscG4W6RwY6gOx1y5J6f4JUQwctiJrqH2oxZYU4mXHi35oV32tr630UcepBzSBGJ/WYcZA==", "dev": true }, "node_modules/email-addresses": { @@ -1743,17 +1749,17 @@ } }, "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", + "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.49.0", + "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -2070,9 +2076,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true, "peer": true }, @@ -3734,20 +3740,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4063,12 +4055,6 @@ } } }, - "node_modules/ts-node/node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -4442,10 +4428,10 @@ "devDependencies": { "@redis/test-utils": "*", "@types/sinon": "^10.0.16", - "sinon": "^15.2.0" + "sinon": "^16.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "packages/graph": { @@ -4475,24 +4461,24 @@ "license": "MIT", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.9", + "@redis/client": "1.5.10", "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.3", + "@redis/json": "1.0.5", + "@redis/search": "1.1.4", "@redis/time-series": "1.0.5" } }, "packages/redis/node_modules/@redis/client": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.9.tgz", - "integrity": "sha512-SffgN+P1zdWJWSXBvJeynvEnmnZrYmtKSRW00xl8pOPFOMJjxRR9u0frSxJpPR6Y4V+k54blJjGW7FgxbTI7bQ==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.10.tgz", + "integrity": "sha512-JqhVeW6ojVL0Jp6MVISPrGRAx6OUZBaYTIMukkiGYvs5gxI8lEKgjSmu+6UvV+Mi/hXzlOAJXTjseeQu0ARnaA==", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", "yallist": "4.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "packages/redis/node_modules/yallist": { diff --git a/package.json b/package.json index 89535a4e4db..777df03e6f2 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^6.6.0", - "@typescript-eslint/parser": "^6.6.0", + "@typescript-eslint/eslint-plugin": "^6.7.2", + "@typescript-eslint/parser": "^6.7.2", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", diff --git a/packages/client/package.json b/packages/client/package.json index d3f30474089..dba7f8a9d20 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -18,7 +18,7 @@ "devDependencies": { "@redis/test-utils": "*", "@types/sinon": "^10.0.16", - "sinon": "^15.2.0" + "sinon": "^16.0.0" }, "engines": { "node": ">=18" diff --git a/packages/redis/package.json b/packages/redis/package.json index e60de2b3028..a65c5c37f90 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,10 +10,10 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.9", + "@redis/client": "1.5.10", "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.3", + "@redis/json": "1.0.5", + "@redis/search": "1.1.4", "@redis/time-series": "1.0.5" }, "repository": { From 225efc0b4365d3a2aa5dd0c16e59639076531f56 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 2 Oct 2023 12:03:04 -0400 Subject: [PATCH 233/325] cluster --- packages/client/lib/client/index.ts | 25 +- packages/client/lib/cluster/cluster-slots.ts | 332 ++++++++---------- packages/client/lib/cluster/index.spec.ts | 272 +++++++------- packages/client/lib/cluster/index.ts | 16 +- .../client/lib/commands/CLIENT_NO-TOUCH.ts | 2 +- .../client/lib/commands/CLUSTER_MYSHARDID.ts | 2 +- .../lib/commands/CLUSTER_REPLICAS.spec.ts | 11 +- .../client/lib/commands/CLUSTER_REPLICAS.ts | 4 +- packages/client/lib/commands/FCALL.spec.ts | 2 +- packages/client/lib/commands/FCALL_RO.spec.ts | 2 +- .../client/lib/commands/FUNCTION_LOAD.spec.ts | 6 +- packages/client/lib/commands/MIGRATE.spec.ts | 132 +++---- packages/client/lib/commands/MIGRATE.ts | 5 +- packages/client/lib/commands/RENAME.ts | 2 +- packages/client/lib/commands/RENAMENX.ts | 2 +- packages/client/lib/commands/ZPOPMAX_COUNT.ts | 2 +- packages/client/lib/commands/index.ts | 3 + packages/client/lib/multi-command.spec.ts | 4 +- packages/test-utils/lib/index.ts | 8 +- 19 files changed, 398 insertions(+), 434 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 60b814e3ea8..4979c905b2a 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -15,23 +15,13 @@ import { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; import { RedisPoolOptions, RedisClientPool } from './pool'; -interface ClientCommander< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts, - RESP extends RespVersions, - TYPE_MAPPING extends TypeMapping -> extends CommanderConfig { - commandOptions?: CommandOptions; -} - export interface RedisClientOptions< M extends RedisModules = RedisModules, F extends RedisFunctions = RedisFunctions, S extends RedisScripts = RedisScripts, RESP extends RespVersions = RespVersions, TYPE_MAPPING extends TypeMapping = TypeMapping -> extends ClientCommander { +> extends CommanderConfig { /** * `redis[s]://[[username][:password]@][host][:port][/db-number]` * See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details @@ -75,6 +65,10 @@ export interface RedisClientOptions< * Useful with Redis deployments that do not honor TCP Keep-Alive. */ pingInterval?: number; + /** + * TODO + */ + commandOptions?: CommandOptions; } type WithCommands< @@ -205,9 +199,8 @@ export default class RedisClient< M extends RedisModules = {}, F extends RedisFunctions = {}, S extends RedisScripts = {}, - RESP extends RespVersions = 2, - TYPE_MAPPING extends TypeMapping = {} - >(config?: ClientCommander) { + RESP extends RespVersions = 2 + >(config?: CommanderConfig) { const Client = attachConfig({ BaseClass: RedisClient, commands: COMMANDS, @@ -220,7 +213,9 @@ export default class RedisClient< Client.prototype.Multi = RedisClientMultiCommand.extend(config); - return (options?: Omit>) => { + return ( + options?: Omit, keyof Exclude> + ) => { // returning a "proxy" to prevent the namespaces.self to leak between "proxies" return Object.create(new Client(options)) as RedisClientType; }; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 19ce00735fa..79fd2e2aeb0 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -4,7 +4,7 @@ import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; import { types } from 'node:util'; import { EventEmitter } from 'node:stream'; import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; -import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; +import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; // TODO: ?! // We need to use 'require', because it's not possible with Typescript to import @@ -21,34 +21,26 @@ export type NodeAddressMap = { [address: string]: NodeAddress; } | ((address: string) => NodeAddress | undefined); -type ValueOrPromise = T | Promise; - -type ClientOrPromise< - M extends RedisModules, - F extends RedisFunctions, - S extends RedisScripts, - RESP extends RespVersions = 2 -> = ValueOrPromise>; - export interface Node< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping > { address: string; - client?: ClientOrPromise; + client?: RedisClientType; + connectPromise?: Promise>; } export interface ShardNode< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions -> extends Node { + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends Node, NodeAddress { id: string; - host: string; - port: number; readonly: boolean; } @@ -56,35 +48,45 @@ export interface MasterNode< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions -> extends ShardNode { - pubSubClient?: ClientOrPromise; + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends ShardNode { + pubSub?: { + connectPromise?: Promise>; + client: RedisClientType; + }; } export interface Shard< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping > { - master: MasterNode; - replicas?: Array>; - nodesIterator?: IterableIterator>; + master: MasterNode; + replicas?: Array>; + nodesIterator?: IterableIterator>; } type ShardWithReplicas< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions -> = Shard & Required, 'replicas'>>; + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = Shard & Required, 'replicas'>>; -export type PubSubNode< +type PubSubNode< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions -> = Required>; + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = ( + Exclude, 'client'> & + Required, 'client'>> +); type PubSubToResubscribe = Record< PubSubType.CHANNELS | PubSubType.PATTERNS, @@ -101,19 +103,19 @@ export default class RedisClusterSlots< M extends RedisModules, F extends RedisFunctions, S extends RedisScripts, - RESP extends RespVersions + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping > { private static _SLOTS = 16384; - private readonly _options: RedisClusterOptions; + private readonly _options: RedisClusterOptions; private readonly _clientFactory: ReturnType>; private readonly _emit: EventEmitter['emit']; - slots = new Array>(RedisClusterSlots._SLOTS); - shards = new Array>(); - masters = new Array>(); - replicas = new Array>(); - readonly nodeByAddress = new Map | ShardNode>(); - pubSubNode?: PubSubNode; + slots = new Array>(RedisClusterSlots._SLOTS); + masters = new Array>(); + replicas = new Array>(); + readonly nodeByAddress = new Map | ShardNode>(); + pubSubNode?: PubSubNode; private _isOpen = false; @@ -122,7 +124,7 @@ export default class RedisClusterSlots< } constructor( - options: RedisClusterOptions, + options: RedisClusterOptions, emit: EventEmitter['emit'] ) { this._options = options; @@ -147,10 +149,12 @@ export default class RedisClusterSlots< private async _discoverWithRootNodes() { let start = Math.floor(Math.random() * this._options.rootNodes.length); for (let i = start; i < this._options.rootNodes.length; i++) { + if (!this._isOpen) throw new Error('Cluster closed'); if (await this._discover(this._options.rootNodes[i])) return; } for (let i = 0; i < start; i++) { + if (!this._isOpen) throw new Error('Cluster closed'); if (await this._discover(this._options.rootNodes[i])) return; } @@ -159,7 +163,6 @@ export default class RedisClusterSlots< private _resetSlots() { this.slots = new Array(RedisClusterSlots._SLOTS); - this.shards = []; this.masters = []; this.replicas = []; this._randomNodeIterator = undefined; @@ -167,15 +170,13 @@ export default class RedisClusterSlots< private async _discover(rootNode: RedisClusterClientOptions) { this._resetSlots(); - const addressesInUse = new Set(); - try { - const shards = await this._getShards(rootNode), + const addressesInUse = new Set(), promises: Array> = [], eagerConnect = this._options.minimizeConnections !== true; - for (const { from, to, master, replicas } of shards) { - const shard: Shard = { + for (const { from, to, master, replicas } of await this._getShards(rootNode)) { + const shard: Shard = { master: this._initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) }; @@ -185,33 +186,24 @@ export default class RedisClusterSlots< ); } - this.shards.push(shard); - for (let i = from; i <= to; i++) { this.slots[i] = shard; } } if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { - if (types.isPromise(this.pubSubNode.client)) { + const channelsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.CHANNELS), + patternsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.PATTERNS); + + this.pubSubNode.client.destroy(); + + if (channelsListeners.size || patternsListeners.size) { promises.push( - this.pubSubNode.client.then(client => client.disconnect()) + this._initiatePubSubClient({ + [PubSubType.CHANNELS]: channelsListeners, + [PubSubType.PATTERNS]: patternsListeners + }) ); - this.pubSubNode = undefined; - } else { - promises.push(this.pubSubNode.client.disconnect()); - - const channelsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.CHANNELS), - patternsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.PATTERNS); - - if (channelsListeners.size || patternsListeners.size) { - promises.push( - this._initiatePubSubClient({ - [PubSubType.CHANNELS]: channelsListeners, - [PubSubType.PATTERNS]: patternsListeners - }) - ); - } } } @@ -219,16 +211,12 @@ export default class RedisClusterSlots< if (addressesInUse.has(address)) continue; if (node.client) { - promises.push( - this._execOnNodeClient(node.client, client => client.disconnect()) - ); + node.client.destroy(); } - const { pubSubClient } = node as MasterNode; - if (pubSubClient) { - promises.push( - this._execOnNodeClient(pubSubClient, client => client.disconnect()) - ); + const { pubSub } = node as MasterNode; + if (pubSub) { + pubSub.client.destroy(); } this.nodeByAddress.delete(address); @@ -248,12 +236,12 @@ export default class RedisClusterSlots< options.socket ??= {}; options.socket.reconnectStrategy = false; options.RESP = this._options.RESP; + options.commandOptions = undefined; - const client = RedisClient.factory(this._options)(options); - - client.on('error', err => this._emit('error', err)); - - await client.connect(); + // TODO: find a way to avoid type casting + const client = await this._clientFactory(options as RedisClientOptions) + .on('error', err => this._emit('error', err)) + .connect(); try { // switch to `CLUSTER SHARDS` when Redis 7.0 will be the minimum supported version @@ -273,7 +261,7 @@ export default class RedisClusterSlots< } } - private _clientOptionsDefaults(options?: RedisClientOptions): RedisClientOptions | undefined { + private _clientOptionsDefaults(options?: RedisClientOptions) { if (!this._options.defaults) return options; let socket; @@ -301,7 +289,6 @@ export default class RedisClusterSlots< promises: Array> ) { const address = `${shard.host}:${shard.port}`; - addressesInUse.add(address); let node = this.nodeByAddress.get(address); if (!node) { @@ -309,7 +296,8 @@ export default class RedisClusterSlots< ...shard, address, readonly, - client: undefined + client: undefined, + connectPromise: undefined }; if (eagerConnent) { @@ -319,16 +307,16 @@ export default class RedisClusterSlots< this.nodeByAddress.set(address, node); } - (readonly ? this.replicas : this.masters).push(node); + if (!addressesInUse.has(address)) { + addressesInUse.add(address); + (readonly ? this.replicas : this.masters).push(node); + } return node; } - private async _createClient( - node: ShardNode, - readonly = node.readonly - ) { - const client = this._clientFactory( + private _createClient(node: ShardNode, readonly = node.readonly) { + return this._clientFactory( this._clientOptionsDefaults({ socket: this._getNodeAddress(node.address) ?? { host: node.host, @@ -337,38 +325,29 @@ export default class RedisClusterSlots< readonly, RESP: this._options.RESP }) - ); - client.on('error', err => this._emit('error', err)); - - await client.connect(); - - return client; + ).on('error', err => console.error(err)); } - private _createNodeClient(node: ShardNode) { - const promise = this._createClient(node) - .then(client => { - node.client = client; - return client; - }) - .catch(err => { - node.client = undefined; - throw err; - }); - node.client = promise; - return promise; + private _createNodeClient(node: ShardNode, readonly?: boolean) { + const client = node.client = this._createClient(node, readonly); + return node.connectPromise = client.connect() + .finally(() => node.connectPromise = undefined); } - nodeClient(node: ShardNode) { - return node.client ?? this._createNodeClient(node); + nodeClient(node: ShardNode) { + return ( + node.connectPromise ?? // if the node is connecting + node.client ?? // if the node is connected + this._createNodeClient(node) // if the not is disconnected + ); } - #runningRediscoverPromise?: Promise; + private _runningRediscoverPromise?: Promise; async rediscover(startWith: RedisClientType): Promise { - this.#runningRediscoverPromise ??= this._rediscover(startWith) - .finally(() => this.#runningRediscoverPromise = undefined); - return this.#runningRediscoverPromise; + this._runningRediscoverPromise ??= this._rediscover(startWith) + .finally(() => this._runningRediscoverPromise = undefined); + return this._runningRediscoverPromise; } private async _rediscover(startWith: RedisClientType): Promise { @@ -399,11 +378,11 @@ export default class RedisClusterSlots< this._isOpen = false; for (const client of this._clients()) { - this._execOnNodeClient(client, client => client.destroy()); + client.destroy(); } if (this.pubSubNode) { - this._execOnNodeClient(this.pubSubNode.client, client => client.destroy()); + this.pubSubNode.client.destroy(); this.pubSubNode = undefined; } @@ -412,21 +391,19 @@ export default class RedisClusterSlots< } private *_clients() { - for (const { master, replicas } of this.shards) { + for (const master of this.masters) { if (master.client) { yield master.client; } - if (master.pubSubClient) { - yield master.pubSubClient; + if (master.pubSub) { + yield master.pubSub.client; } + } - if (replicas) { - for (const { client } of replicas) { - if (client) { - yield client; - } - } + for (const replica of this.replicas) { + if (replica.client) { + yield replica.client; } } } @@ -436,11 +413,11 @@ export default class RedisClusterSlots< const promises = []; for (const client of this._clients()) { - promises.push(this._execOnNodeClient(client, fn)); + promises.push(fn(client)); } if (this.pubSubNode) { - promises.push(this._execOnNodeClient(this.pubSubNode.client, fn)); + promises.push(fn(this.pubSubNode.client)); this.pubSubNode = undefined; } @@ -450,19 +427,10 @@ export default class RedisClusterSlots< await Promise.allSettled(promises); } - private _execOnNodeClient( - client: ClientOrPromise, - fn: (client: RedisClientType) => T - ): T | Promise { - return types.isPromise(client) ? - client.then(fn) : - fn(client); - } - getClient( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined - ): ClientOrPromise { + ) { if (!firstKey) { return this.nodeClient(this.getRandomNode()); } @@ -503,14 +471,14 @@ export default class RedisClusterSlots< } } - _randomNodeIterator?: IterableIterator>; + _randomNodeIterator?: IterableIterator>; getRandomNode() { this._randomNodeIterator ??= this._iterateAllNodes(); - return this._randomNodeIterator.next().value as ShardNode; + return this._randomNodeIterator.next().value as ShardNode; } - private *_slotNodesIterator(slot: ShardWithReplicas) { + private *_slotNodesIterator(slot: ShardWithReplicas) { let i = Math.floor(Math.random() * (1 + slot.replicas.length)); if (i < slot.replicas.length) { do { @@ -533,8 +501,8 @@ export default class RedisClusterSlots< return slot.master; } - slot.nodesIterator ??= this._slotNodesIterator(slot as ShardWithReplicas); - return slot.nodesIterator.next().value as ShardNode; + slot.nodesIterator ??= this._slotNodesIterator(slot as ShardWithReplicas); + return slot.nodesIterator.next().value as ShardNode; } getMasterByAddress(address: string) { @@ -545,20 +513,22 @@ export default class RedisClusterSlots< } getPubSubClient() { - return this.pubSubNode ? - this.pubSubNode.client : - this._initiatePubSubClient(); + if (!this.pubSubNode) return this._initiatePubSubClient(); + + return this.pubSubNode.connectPromise ?? this.pubSubNode.client; } private async _initiatePubSubClient(toResubscribe?: PubSubToResubscribe) { const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), node = index < this.masters.length ? this.masters[index] : - this.replicas[index - this.masters.length]; - + this.replicas[index - this.masters.length], + client = this._createClient(node, true); + this.pubSubNode = { address: node.address, - client: this._createClient(node, true) + client, + connectPromise: client.connect() .then(async client => { if (toResubscribe) { await Promise.all([ @@ -567,7 +537,7 @@ export default class RedisClusterSlots< ]); } - this.pubSubNode!.client = client; + this.pubSubNode!.connectPromise = undefined; return client; }) .catch(err => { @@ -576,7 +546,7 @@ export default class RedisClusterSlots< }) }; - return this.pubSubNode.client as Promise>; + return this.pubSubNode.connectPromise!; } async executeUnsubscribeCommand( @@ -593,52 +563,58 @@ export default class RedisClusterSlots< getShardedPubSubClient(channel: string) { const { master } = this.slots[calculateSlot(channel)]; - return master.pubSubClient ?? this.#initiateShardedPubSubClient(master); - } - - #initiateShardedPubSubClient(master: MasterNode) { - const promise = this._createClient(master, true) - .then(client => { - client.on('server-sunsubscribe', async (channel, listeners) => { - try { - await this.rediscover(client); - const redirectTo = await this.getShardedPubSubClient(channel); - redirectTo.extendPubSubChannelListeners( - PubSubType.SHARDED, - channel, - listeners - ); - } catch (err) { - this._emit('sharded-shannel-moved-error', err, channel, listeners); - } - }); - - master.pubSubClient = client; - return client; - }) - .catch(err => { - master.pubSubClient = undefined; - throw err; + if (!master.pubSub) return this._initiateShardedPubSubClient(master); + return master.pubSub.connectPromise ?? master.pubSub.client; + } + + private async _initiateShardedPubSubClient(master: MasterNode) { + const client = this._createClient(master, true) + .on('server-sunsubscribe', async (channel, listeners) => { + try { + await this.rediscover(client); + const redirectTo = await this.getShardedPubSubClient(channel); + await redirectTo.extendPubSubChannelListeners( + PubSubType.SHARDED, + channel, + listeners + ); + } catch (err) { + this._emit('sharded-shannel-moved-error', err, channel, listeners); + } }); - master.pubSubClient = promise; + master.pubSub = { + client, + connectPromise: client.connect() + .then(client => { + master.pubSub!.connectPromise = undefined; + return client; + }) + .catch(err => { + master.pubSub = undefined; + throw err; + }) + }; - return promise; + return master.pubSub.connectPromise!; } async executeShardedUnsubscribeCommand( channel: string, - unsubscribe: (client: RedisClientType) => Promise - ): Promise { + unsubscribe: (client: RedisClientType) => Promise + ) { const { master } = this.slots[calculateSlot(channel)]; - if (!master.pubSubClient) return Promise.resolve(); + if (!master.pubSub) return; + + const client = master.pubSub.connectPromise ? + await master.pubSub.connectPromise : + master.pubSub.client; - const client = await master.pubSubClient; await unsubscribe(client); if (!client.isPubSubActive) { - await client.disconnect(); - master.pubSubClient = undefined; + client.destroy(); + master.pubSub = undefined; } } } diff --git a/packages/client/lib/cluster/index.spec.ts b/packages/client/lib/cluster/index.spec.ts index f1630863573..4db5f32e853 100644 --- a/packages/client/lib/cluster/index.spec.ts +++ b/packages/client/lib/cluster/index.spec.ts @@ -1,11 +1,9 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; import RedisCluster from '.'; -// import { ClusterSlotStates } from '../commands/CLUSTER_SETSLOT'; import { SQUARE_SCRIPT } from '../client/index.spec'; import { RootNodesUnavailableError } from '../errors'; import { spy } from 'sinon'; -// import { setTimeout } from 'node:timers/promises'; import RedisClient from '../client'; describe('Cluster', () => { @@ -69,58 +67,58 @@ describe('Cluster', () => { } }); - // testUtils.testWithCluster('should handle live resharding', async cluster => { - // const slot = 12539, - // key = 'key', - // value = 'value'; - // await cluster.set(key, value); - - // const importing = cluster.slots[0].master, - // migrating = cluster.slots[slot].master, - // [importingClient, migratingClient] = await Promise.all([ - // cluster.nodeClient(importing), - // cluster.nodeClient(migrating) - // ]); - - // await Promise.all([ - // importingClient.clusterSetSlot(slot, ClusterSlotStates.IMPORTING, migrating.id), - // migratingClient.clusterSetSlot(slot, ClusterSlotStates.MIGRATING, importing.id) - // ]); - - // // should be able to get the key from the migrating node - // assert.equal( - // await cluster.get(key), - // value - // ); - - // await migratingClient.migrate( - // importing.host, - // importing.port, - // key, - // 0, - // 10 - // ); - - // // should be able to get the key from the importing node using `ASKING` - // assert.equal( - // await cluster.get(key), - // value - // ); - - // await Promise.all([ - // importingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), - // migratingClient.clusterSetSlot(slot, ClusterSlotStates.NODE, importing.id), - // ]); - - // // should handle `MOVED` errors - // assert.equal( - // await cluster.get(key), - // value - // ); - // }, { - // serverArguments: [], - // numberOfMasters: 2 - // }); + testUtils.testWithCluster('should handle live resharding', async cluster => { + const slot = 12539, + key = 'key', + value = 'value'; + await cluster.set(key, value); + + const importing = cluster.slots[0].master, + migrating = cluster.slots[slot].master, + [importingClient, migratingClient] = await Promise.all([ + cluster.nodeClient(importing), + cluster.nodeClient(migrating) + ]); + + await Promise.all([ + importingClient.clusterSetSlot(slot, 'IMPORTING', migrating.id), + migratingClient.clusterSetSlot(slot, 'MIGRATING', importing.id) + ]); + + // should be able to get the key from the migrating node + assert.equal( + await cluster.get(key), + value + ); + + await migratingClient.migrate( + importing.host, + importing.port, + key, + 0, + 10 + ); + + // should be able to get the key from the importing node using `ASKING` + assert.equal( + await cluster.get(key), + value + ); + + await Promise.all([ + importingClient.clusterSetSlot(slot, 'NODE', importing.id), + migratingClient.clusterSetSlot(slot, 'NODE', importing.id), + ]); + + // should handle `MOVED` errors + assert.equal( + await cluster.get(key), + value + ); + }, { + serverArguments: [], + numberOfMasters: 2 + }); testUtils.testWithCluster('getRandomNode should spread the the load evenly', async cluster => { const totalNodes = cluster.masters.length + cluster.replicas.length, @@ -145,7 +143,6 @@ describe('Cluster', () => { testUtils.testWithCluster('cluster topology', async cluster => { assert.equal(cluster.slots.length, 16384); const { numberOfMasters, numberOfReplicas } = GLOBAL.CLUSTERS.WITH_REPLICAS; - assert.equal(cluster.shards.length, numberOfMasters); assert.equal(cluster.masters.length, numberOfMasters); assert.equal(cluster.replicas.length, numberOfReplicas * numberOfMasters); assert.equal(cluster.nodeByAddress.size, numberOfMasters + numberOfMasters * numberOfReplicas); @@ -239,54 +236,53 @@ describe('Cluster', () => { assert.equal(cluster.pubSubNode, undefined); }, GLOBAL.CLUSTERS.OPEN); - // testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { - // const listener = spy(); - // await cluster.subscribe('channel', listener); - - // assert.ok(cluster.pubSubNode); - // const [migrating, importing] = cluster.masters[0].address === cluster.pubSubNode.address ? - // cluster.masters : - // [cluster.masters[1], cluster.masters[0]], - // [migratingClient, importingClient] = await Promise.all([ - // cluster.nodeClient(migrating), - // cluster.nodeClient(importing) - // ]); - - // const range = cluster.slots[0].master === migrating ? { - // key: 'bar', // 5061 - // start: 0, - // end: 8191 - // } : { - // key: 'foo', // 12182 - // start: 8192, - // end: 16383 - // }; - - // await Promise.all([ - // migratingClient.clusterDelSlotsRange(range), - // importingClient.clusterDelSlotsRange(range), - // importingClient.clusterAddSlotsRange(range) - // ]); - - // // wait for migrating node to be notified about the new topology - // while ((await migratingClient.clusterInfo()).state !== 'ok') { - // await setTimeout(50); - // } - - // // make sure to cause `MOVED` error - // await cluster.get(range.key); - - // await Promise.all([ - // cluster.publish('channel', 'message'), - // waitTillBeenCalled(listener) - // ]); - - // assert.ok(listener.calledOnceWithExactly('message', 'channel')); - // }, { - // serverArguments: [], - // numberOfMasters: 2, - // minimumDockerVersion: [7] - // }); + testUtils.testWithCluster('should move listeners when PubSub node disconnects from the cluster', async cluster => { + const listener = spy(); + await cluster.subscribe('channel', listener); + + assert.ok(cluster.pubSubNode); + const [migrating, importing] = cluster.masters[0].address === cluster.pubSubNode.address ? + cluster.masters : + [cluster.masters[1], cluster.masters[0]], + [migratingClient, importingClient] = await Promise.all([ + cluster.nodeClient(migrating), + cluster.nodeClient(importing) + ]); + + const range = cluster.slots[0].master === migrating ? { + key: 'bar', // 5061 + start: 0, + end: 8191 + } : { + key: 'foo', // 12182 + start: 8192, + end: 16383 + }; + + // TODO: is there a better way to migrate slots without causing CLUSTERDOWN? + const promises: Array> = []; + for (let i = range.start; i <= range.end; i++) { + promises.push( + migratingClient.clusterSetSlot(i, 'NODE', importing.id), + importingClient.clusterSetSlot(i, 'NODE', importing.id) + ); + } + await Promise.all(promises); + + // make sure to cause `MOVED` error + await cluster.get(range.key); + + await Promise.all([ + cluster.publish('channel', 'message'), + waitTillBeenCalled(listener) + ]); + + assert.ok(listener.calledOnceWithExactly('message', 'channel')); + }, { + serverArguments: [], + numberOfMasters: 2, + minimumDockerVersion: [7] + }); testUtils.testWithCluster('ssubscribe & sunsubscribe', async cluster => { const listener = spy(); @@ -303,46 +299,44 @@ describe('Cluster', () => { await cluster.sUnsubscribe('channel', listener); // 10328 is the slot of `channel` - assert.equal(cluster.slots[10328].master.pubSubClient, undefined); + assert.equal(cluster.slots[10328].master.pubSub, undefined); }, { ...GLOBAL.CLUSTERS.OPEN, minimumDockerVersion: [7] }); - // testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { - // const SLOT = 10328, - // migrating = cluster.slots[SLOT].master, - // importing = cluster.masters.find(master => master !== migrating)!, - // [migratingClient, importingClient] = await Promise.all([ - // cluster.nodeClient(migrating), - // cluster.nodeClient(importing) - // ]); - - // await Promise.all([ - // migratingClient.clusterDelSlots(SLOT), - // importingClient.clusterDelSlots(SLOT), - // importingClient.clusterAddSlots(SLOT) - // ]); - - // // wait for migrating node to be notified about the new topology - // while ((await migratingClient.clusterInfo()).state !== 'ok') { - // await setTimeout(50); - // } - - // const listener = spy(); - - // // will trigger `MOVED` error - // await cluster.sSubscribe('channel', listener); - - // await Promise.all([ - // waitTillBeenCalled(listener), - // cluster.sPublish('channel', 'message') - // ]); - - // assert.ok(listener.calledOnceWithExactly('message', 'channel')); - // }, { - // serverArguments: [], - // minimumDockerVersion: [7] - // }); + testUtils.testWithCluster('should handle sharded-channel-moved events', async cluster => { + const SLOT = 10328, + migrating = cluster.slots[SLOT].master, + importing = cluster.masters.find(master => master !== migrating)!, + [migratingClient, importingClient] = await Promise.all([ + cluster.nodeClient(migrating), + cluster.nodeClient(importing) + ]); + + await Promise.all([ + migratingClient.clusterDelSlots(SLOT), + importingClient.clusterDelSlots(SLOT), + importingClient.clusterAddSlots(SLOT), + // cause "topology refresh" on both nodes + migratingClient.clusterSetSlot(SLOT, 'NODE', importing.id), + importingClient.clusterSetSlot(SLOT, 'NODE', importing.id) + ]); + + const listener = spy(); + + // will trigger `MOVED` error + await cluster.sSubscribe('channel', listener); + + await Promise.all([ + waitTillBeenCalled(listener), + cluster.sPublish('channel', 'message') + ]); + + assert.ok(listener.calledOnceWithExactly('message', 'channel')); + }, { + serverArguments: [], + minimumDockerVersion: [7] + }); }); }); diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index cc0e895ade0..0b7cd210f47 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -17,7 +17,7 @@ interface ClusterCommander< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping, // POLICIES extends CommandPolicies -> extends CommanderConfig{ +> extends CommanderConfig { commandOptions?: ClusterCommandOptions; } @@ -303,7 +303,7 @@ export default class RedisCluster< private readonly _options: RedisClusterOptions; - private readonly _slots: RedisClusterSlots; + private readonly _slots: RedisClusterSlots; private _commandOptions?: ClusterCommandOptions; @@ -315,14 +315,6 @@ export default class RedisCluster< return this._slots.slots; } - /** - * An array of cluster shards, each shard contain its `master` and `replicas`. - * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). - */ - get shards() { - return this._slots.shards; - } - /** * An array of the cluster masters. * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific master node. @@ -442,7 +434,7 @@ export default class RedisCluster< private async _execute( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, - fn: (client: RedisClientType) => Promise + fn: (client: RedisClientType) => Promise ): Promise { const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; let client = await this._slots.getClient(firstKey, isReadonly), @@ -655,7 +647,7 @@ export default class RedisCluster< return this._slots.destroy(); } - nodeClient(node: ShardNode) { + nodeClient(node: ShardNode) { return this._slots.nodeClient(node); } diff --git a/packages/client/lib/commands/CLIENT_NO-TOUCH.ts b/packages/client/lib/commands/CLIENT_NO-TOUCH.ts index e526be17667..a6fc5eb1765 100644 --- a/packages/client/lib/commands/CLIENT_NO-TOUCH.ts +++ b/packages/client/lib/commands/CLIENT_NO-TOUCH.ts @@ -1,4 +1,4 @@ -import { SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { SimpleStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/CLUSTER_MYSHARDID.ts b/packages/client/lib/commands/CLUSTER_MYSHARDID.ts index 5e59b7221a8..0c38b61634f 100644 --- a/packages/client/lib/commands/CLUSTER_MYSHARDID.ts +++ b/packages/client/lib/commands/CLUSTER_MYSHARDID.ts @@ -1,4 +1,4 @@ -import { BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { BlobStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts index 5e1a0341ca8..1a48f360885 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.spec.ts @@ -11,10 +11,11 @@ describe('CLUSTER REPLICAS', () => { }); testUtils.testWithCluster('clusterNode.clusterReplicas', async cluster => { - const client = await cluster.nodeClient(cluster.masters[0]); - assert.equal( - typeof await client.clusterReplicas(cluster.masters[0].id), - 'string' - ); + const client = await cluster.nodeClient(cluster.masters[0]), + reply = await client.clusterReplicas(cluster.masters[0].id); + assert.ok(Array.isArray(reply)); + for (const replica of reply) { + assert.equal(typeof replica, 'string'); + } }, GLOBAL.CLUSTERS.OPEN); }); diff --git a/packages/client/lib/commands/CLUSTER_REPLICAS.ts b/packages/client/lib/commands/CLUSTER_REPLICAS.ts index 831c6bc5058..8e0fe2cdfd9 100644 --- a/packages/client/lib/commands/CLUSTER_REPLICAS.ts +++ b/packages/client/lib/commands/CLUSTER_REPLICAS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, VerbatimStringReply, Command } from '../RESP/types'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, @@ -6,5 +6,5 @@ export default { transformArguments(nodeId: RedisArgument) { return ['CLUSTER', 'REPLICAS', nodeId]; }, - transformReply: undefined as unknown as () => VerbatimStringReply + transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/client/lib/commands/FCALL.spec.ts b/packages/client/lib/commands/FCALL.spec.ts index 35ae8c87c2b..286f2a371bf 100644 --- a/packages/client/lib/commands/FCALL.spec.ts +++ b/packages/client/lib/commands/FCALL.spec.ts @@ -21,7 +21,7 @@ describe('FCALL', () => { loadMathFunction(client), client.set('key', '2'), client.fCall(MATH_FUNCTION.library.square.NAME, { - arguments: ['key'] + keys: ['key'] }) ]); diff --git a/packages/client/lib/commands/FCALL_RO.spec.ts b/packages/client/lib/commands/FCALL_RO.spec.ts index 0b172d1e210..57edcebebef 100644 --- a/packages/client/lib/commands/FCALL_RO.spec.ts +++ b/packages/client/lib/commands/FCALL_RO.spec.ts @@ -21,7 +21,7 @@ describe('FCALL_RO', () => { loadMathFunction(client), client.set('key', '2'), client.fCallRo(MATH_FUNCTION.library.square.NAME, { - arguments: ['key'] + keys: ['key'] }) ]); diff --git a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts index 657f6d03257..fe896bdf8c8 100644 --- a/packages/client/lib/commands/FUNCTION_LOAD.spec.ts +++ b/packages/client/lib/commands/FUNCTION_LOAD.spec.ts @@ -4,6 +4,8 @@ import FUNCTION_LOAD from './FUNCTION_LOAD'; import { RedisClientType } from '../client'; import { NumberReply, RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types'; + + export const MATH_FUNCTION = { name: 'math', engine: 'LUA', @@ -11,10 +13,10 @@ export const MATH_FUNCTION = { `#!LUA name=math redis.register_function { function_name = "square", - callback = function(keys, args) { + callback = function(keys, args) local number = redis.call('GET', keys[1]) return number * number - }, + end, flags = { "no-writes" } }`, library: { diff --git a/packages/client/lib/commands/MIGRATE.spec.ts b/packages/client/lib/commands/MIGRATE.spec.ts index 3d14df5018e..880d59a09c7 100644 --- a/packages/client/lib/commands/MIGRATE.spec.ts +++ b/packages/client/lib/commands/MIGRATE.spec.ts @@ -1,76 +1,76 @@ import { strict as assert } from 'node:assert'; -import { transformArguments } from './MIGRATE'; +import MIGRATE from './MIGRATE'; describe('MIGRATE', () => { - describe('transformArguments', () => { - it('single key', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10'] - ); - }); + describe('transformArguments', () => { + it('single key', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10'] + ); + }); + + it('multiple keys', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, ['1', '2'], 0, 10), + ['MIGRATE', '127.0.0.1', '6379', '', '0', '10', 'KEYS', '1', '2'] + ); + }); - it('multiple keys', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, ['1', '2'], 0, 10), - ['MIGRATE', '127.0.0.1', '6379', '', '0', '10', 'KEYS', '1', '2'] - ); - }); + it('with COPY', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + COPY: true + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY'] + ); + }); - it('with COPY', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10, { - COPY: true - }), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY'] - ); - }); + it('with REPLACE', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + REPLACE: true + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'REPLACE'] + ); + }); - it('with REPLACE', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10, { - REPLACE: true - }), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'REPLACE'] - ); - }); - - describe('with AUTH', () => { - it('password only', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10, { - AUTH: { - password: 'password' - } - }), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH', 'password'] - ); - }); + describe('with AUTH', () => { + it('password only', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + AUTH: { + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH', 'password'] + ); + }); - it('username & password', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10, { - AUTH: { - username: 'username', - password: 'password' - } - }), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH2', 'username', 'password'] - ); - }); - }); + it('username & password', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + AUTH: { + username: 'username', + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'AUTH2', 'username', 'password'] + ); + }); + }); - it('with COPY, REPLACE, AUTH', () => { - assert.deepEqual( - transformArguments('127.0.0.1', 6379, 'key', 0, 10, { - COPY: true, - REPLACE: true, - AUTH: { - password: 'password' - } - }), - ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE', 'AUTH', 'password'] - ); - }); + it('with COPY, REPLACE, AUTH', () => { + assert.deepEqual( + MIGRATE.transformArguments('127.0.0.1', 6379, 'key', 0, 10, { + COPY: true, + REPLACE: true, + AUTH: { + password: 'password' + } + }), + ['MIGRATE', '127.0.0.1', '6379', 'key', '0', '10', 'COPY', 'REPLACE', 'AUTH', 'password'] + ); }); + }); }); diff --git a/packages/client/lib/commands/MIGRATE.ts b/packages/client/lib/commands/MIGRATE.ts index adb1ae8d197..4821f93fcfb 100644 --- a/packages/client/lib/commands/MIGRATE.ts +++ b/packages/client/lib/commands/MIGRATE.ts @@ -1,13 +1,14 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; import { AuthOptions } from './AUTH'; -interface MigrateOptions { +export interface MigrateOptions { COPY?: true; REPLACE?: true; AUTH?: AuthOptions; } export default { + IS_READ_ONLY: false, transformArguments( host: RedisArgument, port: number, @@ -62,5 +63,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/client/lib/commands/RENAME.ts b/packages/client/lib/commands/RENAME.ts index 484eb350692..16e883d0532 100644 --- a/packages/client/lib/commands/RENAME.ts +++ b/packages/client/lib/commands/RENAME.ts @@ -1,7 +1,7 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAME', key, newKey]; diff --git a/packages/client/lib/commands/RENAMENX.ts b/packages/client/lib/commands/RENAMENX.ts index 0048515d44c..3a4f155d5a7 100644 --- a/packages/client/lib/commands/RENAMENX.ts +++ b/packages/client/lib/commands/RENAMENX.ts @@ -1,7 +1,7 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, newKey: RedisArgument) { return ['RENAMENX', key, newKey]; diff --git a/packages/client/lib/commands/ZPOPMAX_COUNT.ts b/packages/client/lib/commands/ZPOPMAX_COUNT.ts index 6ca002cca1e..00d39536ae1 100644 --- a/packages/client/lib/commands/ZPOPMAX_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMAX_COUNT.ts @@ -2,7 +2,7 @@ import { RedisArgument, Command } from '../RESP/types'; import { transformSortedSetReply } from './generic-transformers'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, transformArguments(key: RedisArgument, count: number) { return ['ZPOPMAX', key, count.toString()]; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 30782981ab1..84a726d26e3 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -184,6 +184,7 @@ import MEMORY_PURGE from './MEMORY_PURGE'; import MEMORY_STATS from './MEMORY_STATS'; import MEMORY_USAGE from './MEMORY_USAGE'; import MGET from './MGET'; +import MIGRATE from './MIGRATE'; import MODULE_LIST from './MODULE_LIST'; import MODULE_LOAD from './MODULE_LOAD'; import MODULE_UNLOAD from './MODULE_UNLOAD'; @@ -703,6 +704,8 @@ export default { memoryUsage: MEMORY_USAGE, MGET, mGet: MGET, + MIGRATE, + migrate: MIGRATE, MODULE_LIST, moduleList: MODULE_LIST, MODULE_LOAD, diff --git a/packages/client/lib/multi-command.spec.ts b/packages/client/lib/multi-command.spec.ts index 02230060415..7e77f88d10b 100644 --- a/packages/client/lib/multi-command.spec.ts +++ b/packages/client/lib/multi-command.spec.ts @@ -20,7 +20,7 @@ describe('Multi Command', () => { multi.addScript(SQUARE_SCRIPT, ['1']); assert.deepEqual( Array.from(multi.queue.at(-1).args), - ['EVAL', SQUARE_SCRIPT.SCRIPT, '0', '1'] + ['EVAL', SQUARE_SCRIPT.SCRIPT, '1', '1'] ); }); @@ -28,7 +28,7 @@ describe('Multi Command', () => { multi.addScript(SQUARE_SCRIPT, ['2']); assert.deepEqual( Array.from(multi.queue.at(-1).args), - ['EVALSHA', SQUARE_SCRIPT.SHA1, '0', '2'] + ['EVALSHA', SQUARE_SCRIPT.SHA1, '1', '2'] ); }); diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 68e96307691..ab9da32a946 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -200,9 +200,9 @@ export default class TestUtils { // POLICIES extends CommandPolicies >(cluster: RedisClusterType): Promise { return Promise.all( - cluster.masters.map(async ({ client }) => { - if (client) { - await (await client).flushAll(); + cluster.masters.map(async master => { + if (master.client) { + (await cluster.nodeClient(master)).flushAll(); } }) ); @@ -256,7 +256,7 @@ export default class TestUtils { await fn(cluster); } finally { await TestUtils.#clusterFlushAll(cluster); - await cluster.disconnect(); + cluster.destroy(); } }); } From 52772858b4a91c58d5a740fa0295a58417e9ae0e Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 2 Oct 2023 14:04:02 -0400 Subject: [PATCH 234/325] fix FUNCTION STATS --- .../lib/commands/FUNCTION_STATS.spec.ts | 42 +++--- .../client/lib/commands/FUNCTION_STATS.ts | 137 ++++++++---------- 2 files changed, 81 insertions(+), 98 deletions(-) diff --git a/packages/client/lib/commands/FUNCTION_STATS.spec.ts b/packages/client/lib/commands/FUNCTION_STATS.spec.ts index 76c1ddafc18..b48b012614f 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.spec.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.spec.ts @@ -1,25 +1,25 @@ -// import { strict as assert } from 'node:assert'; +import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './FUNCTION_STATS'; +import FUNCTION_STATS from './FUNCTION_STATS'; -// describe('FUNCTION STATS', () => { -// testUtils.isVersionGreaterThanHook([7]); +describe('FUNCTION STATS', () => { + testUtils.isVersionGreaterThanHook([7]); -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments(), -// ['FUNCTION', 'STATS'] -// ); -// }); + it('transformArguments', () => { + assert.deepEqual( + FUNCTION_STATS.transformArguments(), + ['FUNCTION', 'STATS'] + ); + }); -// testUtils.testWithClient('client.functionStats', async client => { -// const stats = await client.functionStats(); -// assert.equal(stats.runningScript, null); -// assert.equal(typeof stats.engines, 'object'); -// for (const [engine, { librariesCount, functionsCount }] of Object.entries(stats.engines)) { -// assert.equal(typeof engine, 'string'); -// assert.equal(typeof librariesCount, 'number'); -// assert.equal(typeof functionsCount, 'number'); -// } -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.functionStats', async client => { + const stats = await client.functionStats(); + assert.equal(stats.running_script, null); + assert.equal(typeof stats.engines, 'object'); + for (const [engine, { libraries_count, functions_count }] of Object.entries(stats.engines)) { + assert.equal(typeof engine, 'string'); + assert.equal(typeof libraries_count, 'number'); + assert.equal(typeof functions_count, 'number'); + } + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/FUNCTION_STATS.ts b/packages/client/lib/commands/FUNCTION_STATS.ts index 6175d7775ef..138d1fb82d5 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.ts @@ -1,87 +1,70 @@ -// // import { RedisCommandArguments } from '.'; +import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply, Resp2Reply, UnwrapReply } from '../RESP/types'; +import { isNullReply } from './generic-transformers'; -// // export function transformArguments(): RedisCommandArguments { -// // return ['FUNCTION', 'STATS']; -// // } +type RunningScript = NullReply | TuplesToMapReply<[ + [BlobStringReply<'name'>, BlobStringReply], + [BlobStringReply<'command'>, BlobStringReply], + [BlobStringReply<'duration_ms'>, NumberReply] +]>; -// // type FunctionStatsRawReply = [ -// // 'running_script', -// // null | [ -// // 'name', -// // string, -// // 'command', -// // string, -// // 'duration_ms', -// // number -// // ], -// // 'engines', -// // Array // "flat tuples" (there is no way to type that) -// // // ...[string, [ -// // // 'libraries_count', -// // // number, -// // // 'functions_count', -// // // number -// // // ]] -// // ]; +type Engine = TuplesToMapReply<[ + [BlobStringReply<'libraries_count'>, NumberReply], + [BlobStringReply<'functions_count'>, NumberReply] +]>; -// // interface FunctionStatsReply { -// // runningScript: null | { -// // name: string; -// // command: string; -// // durationMs: number; -// // }; -// // engines: Record; -// // } +type Engines = MapReply; -// // export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { -// // const engines = Object.create(null); -// // for (let i = 0; i < reply[3].length; i++) { -// // engines[reply[3][i]] = { -// // librariesCount: reply[3][++i][1], -// // functionsCount: reply[3][i][3] -// // }; -// // } +type FunctionStatsReply = TuplesToMapReply<[ + [BlobStringReply<'running_script'>, RunningScript], + [BlobStringReply<'engines'>, Engines] +]>; -// // return { -// // runningScript: reply[1] === null ? null : { -// // name: reply[1][1], -// // command: reply[1][3], -// // durationMs: reply[1][5] -// // }, -// // engines -// // }; -// // } +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['FUNCTION', 'STATS']; + }, + transformReply: { + 2: (reply: UnwrapReply>) => { + return { + running_script: transformRunningScript(reply[1]), + engines: transformEngines(reply[3]) + }; + }, + 3: undefined as unknown as () => FunctionStatsReply + } +} as const satisfies Command; +function transformRunningScript(reply: Resp2Reply) { + if (isNullReply(reply)) { + return null; + } -// // #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } + const unwraped = reply as unknown as UnwrapReply; + return { + name: unwraped[1], + command: unwraped[3], + duration_ms: unwraped[5] + }; +} -// import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; +function transformEngines(reply: Resp2Reply) { + const unwraped = reply as unknown as UnwrapReply; -// type FunctionStatsReply = TuplesToMapReply<[ -// [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ -// [BlobStringReply<'name'>, BlobStringReply], -// [BlobStringReply<'command'>, BlobStringReply], -// [BlobStringReply<'duration_ms'>, NumberReply] -// ]>], -// [BlobStringReply<'engines'>, MapReply, NumberReply], -// [BlobStringReply<'functions_count'>, NumberReply] -// ]>>] -// ]>; + const engines: Record = Object.create(null); + for (let i = 0; i < unwraped.length; i++) { + const name = unwraped[i] as BlobStringReply, + stats = unwraped[++i] as Resp2Reply, + unwrapedStats = stats as unknown as UnwrapReply; + engines[name.toString()] = { + libraries_count: unwrapedStats[1], + functions_count: unwrapedStats[3] + }; + } -// export default { -// IS_READ_ONLY: true, -// FIRST_KEY_INDEX: undefined, -// transformArguments() { -// return ['FUNCTION', 'STATS']; -// }, -// transformReply: { -// 2: (reply) => { - -// }, -// 3: undefined as unknown as () => -// } -// } as const satisfies Command; + return engines; +} From 7b4d12bdb333174d2095ac7d96b82c9591d145c8 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 2 Oct 2023 14:13:35 -0400 Subject: [PATCH 235/325] FUNCTION STATS migration guide --- docs/v4-to-v5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 4130c659395..897b04bbef7 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -164,6 +164,7 @@ Some command arguments/replies have changed to align more closely to data types - `CLIENT TRACKINGINFO`: `flags` in RESP2 - `Set` -> `Array` (to match RESP3 default type mapping) - `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] - `FUNCTION RESTORE`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `FUNCTION STATS`: `runningScript` -> `running_script`, `durationMs` -> `duration_ms`, `librariesCount` -> `libraries_count`, `functionsCount` -> `functions_count` [^map-keys] - `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] From 69cf68b20b33fb9ac3950b8534f8803328285cce Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 2 Oct 2023 14:13:44 -0400 Subject: [PATCH 236/325] fix cluster tests flushall --- packages/test-utils/lib/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index ab9da32a946..af8ecac385b 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -202,7 +202,7 @@ export default class TestUtils { return Promise.all( cluster.masters.map(async master => { if (master.client) { - (await cluster.nodeClient(master)).flushAll(); + await (await cluster.nodeClient(master)).flushAll(); } }) ); @@ -245,7 +245,6 @@ export default class TestUtils { port } })), - minimizeConnections: true, ...options.clusterConfiguration }); From 643e0868e9b5243b2d2fe373b37af5a564f5677a Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 2 Oct 2023 14:24:13 -0400 Subject: [PATCH 237/325] use minimizeConnections for cluster tests --- packages/test-utils/lib/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index af8ecac385b..5343beb91b4 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -245,6 +245,7 @@ export default class TestUtils { port } })), + minimizeConnections: true, ...options.clusterConfiguration }); From ab3489841edb0930ce81f81d4416bdb44c50c16e Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 3 Oct 2023 13:21:53 -0400 Subject: [PATCH 238/325] FT.CONFIG GET --- .../search/lib/commands/CONFIG_GET.spec.ts | 40 +++++++++---------- packages/search/lib/commands/CONFIG_GET.ts | 20 ++++++++++ packages/search/lib/commands/index.ts | 6 +-- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/packages/search/lib/commands/CONFIG_GET.spec.ts b/packages/search/lib/commands/CONFIG_GET.spec.ts index 44ab78d9da3..7ef2a3536b9 100644 --- a/packages/search/lib/commands/CONFIG_GET.spec.ts +++ b/packages/search/lib/commands/CONFIG_GET.spec.ts @@ -1,25 +1,25 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CONFIG_GET'; +import CONFIG_GET from './CONFIG_GET'; -describe('CONFIG GET', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('TIMEOUT'), - ['FT.CONFIG', 'GET', 'TIMEOUT'] - ); - }); +describe('FT.CONFIG GET', () => { + it('transformArguments', () => { + assert.deepEqual( + CONFIG_GET.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); + 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 index fbf1f1164b9..72f1ce96c83 100644 --- a/packages/search/lib/commands/CONFIG_GET.ts +++ b/packages/search/lib/commands/CONFIG_GET.ts @@ -1,3 +1,23 @@ +import { ArrayReply, TuplesReply, BlobStringReply, NullReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(option: string) { + return ['FT.CONFIG', 'GET', option]; + }, + transformReply(reply: UnwrapReply>>) { + const transformedReply: Record = Object.create(null); + for (const item of reply) { + const [key, value] = item as unknown as UnwrapReply; + transformedReply[key.toString()] = value; + } + + return transformedReply; + } +} as const satisfies Command; + + export function transformArguments(option: string) { return ['FT.CONFIG', 'GET', option]; } diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 27bd3dfb224..7ff80743505 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -5,7 +5,7 @@ import ALTER from './ALTER'; import ALIASADD from './ALIASADD'; import ALIASDEL from './ALIASDEL'; import ALIASUPDATE from './ALIASUPDATE'; -// import CONFIG_GET from './CONFIG_GET'; +import CONFIG_GET from './CONFIG_GET'; import CONFIG_SET from './CONFIG_SET'; import CREATE from './CREATE'; import CURSOR_DEL from './CURSOR_DEL'; @@ -51,8 +51,8 @@ export default { aliasDel: ALIASDEL, ALIASUPDATE, aliasUpdate: ALIASUPDATE, - // CONFIG_GET, - // configGet: CONFIG_GET, + CONFIG_GET, + configGet: CONFIG_GET, CONFIG_SET, configSet: CONFIG_SET, CREATE, From 77308ed670d99fe6440d2f5ab9e7d2ac4c4c7cd0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 3 Oct 2023 13:24:00 -0400 Subject: [PATCH 239/325] fix for last commit --- packages/search/lib/commands/CONFIG_GET.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/search/lib/commands/CONFIG_GET.ts b/packages/search/lib/commands/CONFIG_GET.ts index 72f1ce96c83..f96461e8694 100644 --- a/packages/search/lib/commands/CONFIG_GET.ts +++ b/packages/search/lib/commands/CONFIG_GET.ts @@ -16,21 +16,3 @@ export default { return transformedReply; } } as const satisfies Command; - - -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; -} From 42b05b025bdd1eb564bfeb4ef186586bde0b3fb1 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 11 Oct 2023 17:04:13 -0400 Subject: [PATCH 240/325] fix all FT.SUGGET variations --- packages/search/lib/commands/SUGGET.ts | 4 +- .../lib/commands/SUGGET_WITHPAYLOADS.spec.ts | 54 ++++++------- .../lib/commands/SUGGET_WITHPAYLOADS.ts | 50 ++++++------ .../lib/commands/SUGGET_WITHSCORES.spec.ts | 52 ++++++------- .../search/lib/commands/SUGGET_WITHSCORES.ts | 70 +++++++++++------ .../SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts | 56 +++++++------- .../SUGGET_WITHSCORES_WITHPAYLOADS.ts | 76 +++++++++++++------ packages/search/lib/commands/index.ts | 18 ++--- 8 files changed, 218 insertions(+), 162 deletions(-) diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts index 2dc360da3e7..9359920fcb2 100644 --- a/packages/search/lib/commands/SUGGET.ts +++ b/packages/search/lib/commands/SUGGET.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { NullReply, ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; export interface FtSugGetOptions { FUZZY?: boolean; @@ -21,5 +21,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => ArrayReply + transformReply: undefined as unknown as () => NullReply | ArrayReply } as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts index 2151c678c6b..42a427ce1f4 100644 --- a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.spec.ts @@ -1,33 +1,35 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGGET_WITHPAYLOADS'; +import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; -describe('SUGGET WITHPAYLOADS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'prefix'), - ['FT.SUGGET', 'key', 'prefix', 'WITHPAYLOADS'] - ); - }); +describe('FT.SUGGET WITHPAYLOADS', () => { + it('transformArguments', () => { + assert.deepEqual( + SUGGET_WITHPAYLOADS.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); + 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' }); + testUtils.testWithClient('with suggestions', async client => { + const [, reply] = await Promise.all([ + client.ft.sugAdd('key', 'string', 1, { + PAYLOAD: 'payload' + }), + client.ft.sugGetWithPayloads('key', 'string') + ]); - assert.deepEqual( - await client.ft.sugGetWithPayloads('key', 'string'), - [{ - suggestion: 'string', - payload: 'payload' - }] - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.deepEqual(reply, [{ + 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 index 7eaff4697e1..d8b097f3dbc 100644 --- a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts @@ -1,29 +1,31 @@ -import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; +import { NullReply, ArrayReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import SUGGET from './SUGGET'; -export { IS_READ_ONLY } from './SUGGET'; +export default { + FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX, + IS_READ_ONLY: SUGGET.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const transformedArguments = SUGGET.transformArguments(...args); + transformedArguments.push('WITHPAYLOADS'); + return transformedArguments; + }, + transformReply(reply: NullReply | UnwrapReply>) { + if (isNullReply(reply)) return null; -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] - }); + const transformedReply: Array<{ + suggestion: BlobStringReply; + payload: BlobStringReply; + }> = new Array(reply.length / 2); + let replyIndex = 0, + arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + payload: reply[replyIndex++] + }; } return transformedReply; -} + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts index 41ee055ae76..6969be7729d 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES.spec.ts @@ -1,33 +1,33 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGGET_WITHSCORES'; +import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; -describe('SUGGET WITHSCORES', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'prefix'), - ['FT.SUGGET', 'key', 'prefix', 'WITHSCORES'] - ); - }); +describe('FT.SUGGET WITHSCORES', () => { + it('transformArguments', () => { + assert.deepEqual( + SUGGET_WITHSCORES.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); + 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); + testUtils.testWithClient('with suggestions', async client => { + const [, reply] = await Promise.all([ + client.ft.sugAdd('key', 'string', 1), + client.ft.sugGetWithScores('key', 's') + ]); - assert.deepEqual( - await client.ft.sugGetWithScores('key', 'string'), - [{ - suggestion: 'string', - score: 2147483648 - }] - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.ok(Array.isArray(reply)); + assert.equal(reply.length, 1); + assert.equal(reply[0].suggestion, 'string'); + assert.equal(typeof reply[0].score, 'number'); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES.ts b/packages/search/lib/commands/SUGGET_WITHSCORES.ts index bad5bff2999..ccd08de4e76 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES.ts @@ -1,29 +1,51 @@ -import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; +import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import SUGGET from './SUGGET'; -export { IS_READ_ONLY } from './SUGGET'; +export default { + FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX, + IS_READ_ONLY: SUGGET.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const transformedArguments = SUGGET.transformArguments(...args); + transformedArguments.push('WITHSCORES'); + return transformedArguments; + }, + transformReply: { + 2(reply: NullReply | UnwrapReply>) { + if (isNullReply(reply)) return null; -export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { - return [ - ...transformSugGetArguments(key, prefix, options), - 'WITHSCORES' - ]; -} + const transformedReply: Array<{ + suggestion: BlobStringReply; + score: number; + }> = new Array(reply.length / 2); + let replyIndex = 0, + arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: Number(reply[replyIndex++]) + }; + } -export interface SuggestionWithScores { - suggestion: string; - score: number; -} + return transformedReply; + }, + 3(reply: UnwrapReply>) { + if (isNullReply(reply)) return null; + + const transformedReply: Array<{ + suggestion: BlobStringReply; + score: DoubleReply; + }> = new Array(reply.length / 2); + let replyIndex = 0, + arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++] as BlobStringReply, + score: reply[replyIndex++] as DoubleReply + }; + } -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; } - - return transformedReply; -} + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts index 8adc9ba2b13..98aad1c8028 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.spec.ts @@ -1,34 +1,36 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGGET_WITHSCORES_WITHPAYLOADS'; +import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; -describe('SUGGET WITHSCORES WITHPAYLOADS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'prefix'), - ['FT.SUGGET', 'key', 'prefix', 'WITHSCORES', 'WITHPAYLOADS'] - ); - }); +describe('FT.SUGGET WITHSCORES WITHPAYLOADS', () => { + it('transformArguments', () => { + assert.deepEqual( + SUGGET_WITHSCORES_WITHPAYLOADS.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); + 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' }); + testUtils.testWithClient('with suggestions', async client => { + const [, reply] = await Promise.all([ + client.ft.sugAdd('key', 'string', 1, { + PAYLOAD: 'payload' + }), + client.ft.sugGetWithScoresWithPayloads('key', 'string') + ]); - assert.deepEqual( - await client.ft.sugGetWithScoresWithPayloads('key', 'string'), - [{ - suggestion: 'string', - score: 2147483648, - payload: 'payload' - }] - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.ok(Array.isArray(reply)); + assert.equal(reply.length, 1); + assert.equal(reply[0].suggestion, 'string'); + assert.equal(typeof reply[0].score, 'number'); + assert.equal(reply[0].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 index 3b2fe7667b7..b4b5553bc6e 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts @@ -1,30 +1,58 @@ -import { SugGetOptions, transformArguments as transformSugGetArguments } from './SUGGET'; -import { SuggestionWithPayload } from './SUGGET_WITHPAYLOADS'; -import { SuggestionWithScores } from './SUGGET_WITHSCORES'; +import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers'; +import SUGGET from './SUGGET'; -export { IS_READ_ONLY } from './SUGGET'; +export default { + FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX, + IS_READ_ONLY: SUGGET.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const transformedArguments = SUGGET.transformArguments(...args); + transformedArguments.push( + 'WITHSCORES', + 'WITHPAYLOADS' + ); + return transformedArguments; + }, + transformReply: { + 2(reply: NullReply | UnwrapReply>) { + if (isNullReply(reply)) return null; -export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { - return [ - ...transformSugGetArguments(key, prefix, options), - 'WITHSCORES', - 'WITHPAYLOADS' - ]; -} + const transformedReply: Array<{ + suggestion: BlobStringReply; + score: number; + payload: BlobStringReply; + }> = new Array(reply.length / 3); + let replyIndex = 0, + arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: Number(reply[replyIndex++]), + payload: reply[replyIndex++] + }; + } -type SuggestionWithScoresAndPayloads = SuggestionWithScores & SuggestionWithPayload; + return transformedReply; + }, + 3(reply: NullReply | UnwrapReply>) { + if (isNullReply(reply)) return null; -export function transformReply(rawReply: Array | null): Array | null { - if (rawReply === null) return null; + const transformedReply: Array<{ + suggestion: BlobStringReply; + score: DoubleReply; + payload: BlobStringReply; + }> = new Array(reply.length / 3); + let replyIndex = 0, + arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++] as BlobStringReply, + score: reply[replyIndex++] as DoubleReply, + payload: reply[replyIndex++] as BlobStringReply + }; + } - 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; } - - return transformedReply; -} + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 7ff80743505..ccf72e8f4cc 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -23,9 +23,9 @@ import EXPLAINCLI from './EXPLAINCLI'; import SPELLCHECK from './SPELLCHECK'; import SUGADD from './SUGADD'; import SUGDEL from './SUGDEL'; -// import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; -// import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; -// import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; +import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; +import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; +import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; import SUGGET from './SUGGET'; import SUGLEN from './SUGLEN'; import SYNDUMP from './SYNDUMP'; @@ -87,12 +87,12 @@ export default { sugAdd: SUGADD, SUGDEL, sugDel: SUGDEL, - // SUGGET_WITHPAYLOADS, - // sugGetWithPayloads: SUGGET_WITHPAYLOADS, - // SUGGET_WITHSCORES_WITHPAYLOADS, - // sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, - // SUGGET_WITHSCORES, - // sugGetWithScores: SUGGET_WITHSCORES, + SUGGET_WITHPAYLOADS, + sugGetWithPayloads: SUGGET_WITHPAYLOADS, + SUGGET_WITHSCORES_WITHPAYLOADS, + sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, + SUGGET_WITHSCORES, + sugGetWithScores: SUGGET_WITHSCORES, SUGGET, sugGet: SUGGET, SUGLEN, From 817818aa911186bb1713018ddc7aab443cb4e228 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 23 Oct 2023 15:05:16 -0400 Subject: [PATCH 241/325] WIP --- docs/todo.md | 2 - docs/v4-to-v5.md | 74 ++- package-lock.json | 260 ++++---- package.json | 10 +- .../lib/commands/cuckoo/LOADCHUNK.spec.ts | 2 +- packages/bloom/package.json | 4 +- packages/client/index.ts | 2 +- .../client/lib/commands/COMMAND_LIST.spec.ts | 106 +-- packages/client/lib/commands/COMMAND_LIST.ts | 66 +- packages/client/lib/commands/ZPOPMIN_COUNT.ts | 2 +- packages/client/lib/commands/index.ts | 6 +- packages/graph/lib/commands/QUERY.ts | 2 +- packages/graph/lib/commands/SLOWLOG.spec.ts | 2 +- packages/graph/lib/commands/index.ts | 6 +- packages/graph/package.json | 4 +- packages/json/package.json | 4 +- packages/redis/index.ts | 48 +- packages/redis/package.json | 2 +- .../search/lib/commands/SPELLCHECK.spec.ts | 3 +- packages/search/lib/commands/index.ts | 616 +++++++++--------- packages/search/lib/index.ts | 8 +- packages/search/package.json | 4 +- packages/time-series/lib/commands/MRANGE.ts | 3 +- .../lib/commands/MRANGE_WITHLABELS.ts | 1 - .../lib/commands/MREVRANGE_WITHLABELS.ts | 10 +- packages/time-series/lib/commands/RANGE.ts | 18 +- .../time-series/lib/commands/REVRANGE.spec.ts | 110 +--- packages/time-series/lib/commands/index.ts | 211 +----- packages/time-series/package.json | 4 +- 29 files changed, 682 insertions(+), 908 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index 5c64a699430..49163444986 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,8 +1,6 @@ -- Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie? - "Isolation Pool" -> pool - Cluster request response policies (either implement, or block "server" commands in cluster) Docs: -- [v4 to v5](./v4-to-v5.md) - Legacy mode - [Command Options](./command-options.md) - [RESP](./RESP.md) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 897b04bbef7..2c8d153b089 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -77,7 +77,11 @@ legacyClient.set('key', 'value', (err, reply) => { ## Isolation Pool -TODO +[TODO](./blocking-commands.md). + +```javascript +await client.get(client.commandOptions({ isolated: true }), 'key'); +``` ```javascript await client.sendCommand(['GET', 'key']); @@ -123,35 +127,47 @@ await cluster.multi() ## Commands -Some command arguments/replies have changed to align more closely to data types returned by Redis: +### Redis - `ACL GETUSER`: `selectors` +- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] - `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] - `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants] -- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` +- `CLIENT TRACKINGINFO`: `flags` in RESP2 - `Set` -> `Array` (to match RESP3 default type mapping) +- `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] +- `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] +- `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] +- `CLUSTER NODES`, `CLUSTER REPLICAS`, `CLUSTER INFO`: returning the raw `VerbatimStringReply` +- `EXPIRE`: `boolean` -> `number` [^boolean-to-number] +- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `HSCAN`: `tuples` has been renamed to `entries` - `HEXISTS`: `boolean` -> `number` [^boolean-to-number] - `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). -- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: `cursor` type is `string | Buffer` instead of `number` - `HSETNX`: `boolean` -> `number` [^boolean-to-number] + +- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` + + - `ZINTER`: instead of `client.ZINTER('key', { WEIGHTS: [1] })` use `client.ZINTER({ key: 'key', weight: 1 }])` - `ZINTER_WITHSCORES`: instead of `client.ZINTER_WITHSCORES('key', { WEIGHTS: [1] })` use `client.ZINTER_WITHSCORES({ key: 'key', weight: 1 }])` - `ZUNION`: instead of `client.ZUNION('key', { WEIGHTS: [1] })` use `client.ZUNION({ key: 'key', weight: 1 }])` - `ZUNION_WITHSCORES`: instead of `client.ZUNION_WITHSCORES('key', { WEIGHTS: [1] })` use `client.ZUNION_WITHSCORES({ key: 'key', weight: 1 }])` -- `SETNX`: `boolean` -> `number` [^boolean-to-number] -- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number] -- `EXPIRE`: `boolean` -> `number` [^boolean-to-number] -- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number] +- `ZMPOP`: `{ elements: Array<{ member: string; score: number; }>; }` -> `{ members: Array<{ value: string; score: number; }>; }` to match other sorted set commands (e.g. `ZRANGE`, `ZSCAN`) + - `MOVE`: `boolean` -> `number` [^boolean-to-number] - `PEXPIRE`: `boolean` -> `number` [^boolean-to-number] - `PEXPIREAT`: `boolean` -> `number` [^boolean-to-number] -- `RENAMENX`: `boolean` -> `number` [^boolean-to-number] -- `HSCAN`: `tuples` has been renamed to `entries` - `PFADD`: `boolean` -> `number` [^boolean-to-number] + +- `RENAMENX`: `boolean` -> `number` [^boolean-to-number] +- `SETNX`: `boolean` -> `number` [^boolean-to-number] +- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: `reply.cursor` will not be converted to number to avoid issues when the number is bigger than `Number.MAX_SAFE_INTEGER`. See [here](https://github.com/redis/node-redis/issues/2561). - `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] - `SISMEMBER`: `boolean` -> `number` [^boolean-to-number] - `SMISMEMBER`: `Array` -> `Array` [^boolean-to-number] - `SMOVE`: `boolean` -> `number` [^boolean-to-number] -- `TS.ADD`: `boolean` -> `number` [^boolean-to-number] + - `GEOSEARCH_WITH`/`GEORADIUS_WITH`: `GeoReplyWith` -> `GEO_REPLY_WITH` [^enum-to-constants] - `GEORADIUSSTORE` -> `GEORADIUS_STORE` - `GEORADIUSBYMEMBERSTORE` -> `GEORADIUSBYMEMBER_STORE` @@ -161,34 +177,46 @@ Some command arguments/replies have changed to align more closely to data types - `HELLO`: `protover` moved from the options object to it's own argument, `auth` -> `AUTH`, `clientName` -> `SETNAME` - `MODULE LIST`: `version` -> `ver` [^map-keys] - `MEMORY STATS`: [^map-keys] -- `CLIENT TRACKINGINFO`: `flags` in RESP2 - `Set` -> `Array` (to match RESP3 default type mapping) -- `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] - `FUNCTION RESTORE`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `FUNCTION STATS`: `runningScript` -> `running_script`, `durationMs` -> `duration_ms`, `librariesCount` -> `libraries_count`, `functionsCount` -> `functions_count` [^map-keys] -- `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] -- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] -- `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] + - `TIME`: `Date` -> `[unixTimestamp: string, microseconds: string]` -- `ZMPOP`: `{ elements: Array<{ member: string; score: number; }>; }` -> `{ members: Array<{ value: string; score: number; }>; }` to match other sorted set commands (e.g. `ZRANGE`, `ZSCAN`) + - `XGROUP_CREATECONSUMER`: [^boolean-to-number] - `XGROUP_DESTROY`: [^boolean-to-number] - `XINFO GROUPS`: `lastDeliveredId` -> `last-delivered-id` [^map-keys] - `XINFO STREAM`: `radixTreeKeys` -> `radix-tree-keys`, `radixTreeNodes` -> `radix-tree-nodes`, `lastGeneratedId` -> `last-generated-id`, `maxDeletedEntryId` -> `max-deleted-entry-id`, `entriesAdded` -> `entries-added`, `recordedFirstEntryId` -> `recorded-first-entry-id`, `firstEntry` -> `first-entry`, `lastEntry` -> `last-entry` - `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record }>; }>` -> `Record }>>` -- `FT.SUGDEL`: [^boolean-to-number] + +- `COMMAND LIST`: `enum FilterBy` -> `const COMMAND_LIST_FILTER_BY` [^enum-to-constants], the filter argument has been moved from a "top level argument" into ` { FILTERBY: { type: ; value: } }` + +### Bloom + - `TOPK.QUERY`: `Array` -> `Array` + +### Graph + - `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number` + +### JSON + - `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing] - `JSON.ARRPOP`: `path` and `index` arguments moved to `{ path: string; index: number; }` [^future-proofing] - `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRAPPEND`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing] + +### Search + +- `FT.SUGDEL`: [^boolean-to-number] + +### Time Series + +- `TS.ADD`: `boolean` -> `number` [^boolean-to-number] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` - `TS.SYNUPDATE`: `Array>` -> `Record>` -- `CLUSTER NODES`, `CLUSTER REPLICAS`, `CLUSTER INFO`: returning the raw `VerbatimStringReply` +- `TS.M[REV]RANGE[_WITHLABELS]`, `TS.MGET[_WITHLABELS]`: TODO [^enum-to-constants]: TODO -[^boolean-to-number]: TODO - -[^map-keys]: [TODO](https://github.com/redis/node-redis/discussions/2506) +[^map-keys]: To avoid unnecessary transformations and confusion, map keys will not be transformed to "js friendly" names (i.e. `number-of-keys` will not be renamed to `numberOfKeys`). See [here](https://github.com/redis/node-redis/discussions/2506). -[^future-proofing]: TODO \ No newline at end of file +[^future-proofing]: TODO diff --git a/package-lock.json b/package-lock.json index ac6d81f6478..724dae3bcef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,15 +11,15 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node18": "^18.2.2", - "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", + "@types/mocha": "^10.0.3", + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.25.1", + "typedoc": "^0.25.2", "typescript": "^5.2.2" } }, @@ -131,18 +131,18 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", - "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -150,10 +150,10 @@ "@babel/generator": "^7.23.0", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.0", + "@babel/helpers": "^7.23.2", "@babel/parser": "^7.23.0", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", + "@babel/traverse": "^7.23.2", "@babel/types": "^7.23.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -341,13 +341,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", + "@babel/traverse": "^7.23.2", "@babel/types": "^7.23.0" }, "engines": { @@ -466,9 +466,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", @@ -580,9 +580,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", - "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true, "peer": true, "engines": { @@ -934,34 +934,37 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", - "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.3.tgz", + "integrity": "sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.0.tgz", - "integrity": "sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ==", + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.17", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.17.tgz", - "integrity": "sha512-+6ILpcixQ0Ma3dHMTLv4rSycbDXkDljgKL+E0nI2RUxxhYTFyPSjt6RVMxh7jUshvyVcBvicb0Ktj+lAJcjgeA==", + "version": "10.0.19", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.19.tgz", + "integrity": "sha512-MWZNGPSchIdDfb5FL+VFi4zHsHbNOTQEgjqFQk7HazXSXwUU9PAX3z9XBqb3AJGYr9YwrtCtaSMsT3brYsN/jQ==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -974,9 +977,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.26", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", - "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", + "version": "17.0.28", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", + "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -989,16 +992,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz", - "integrity": "sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", + "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/type-utils": "6.7.4", - "@typescript-eslint/utils": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/type-utils": "6.9.0", + "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1024,15 +1027,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", + "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4" }, "engines": { @@ -1052,13 +1055,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", - "integrity": "sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", + "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4" + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1069,13 +1072,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz", - "integrity": "sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", + "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/utils": "6.7.4", + "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/utils": "6.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1096,9 +1099,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.4.tgz", - "integrity": "sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", + "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1109,13 +1112,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz", - "integrity": "sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", + "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/visitor-keys": "6.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1136,17 +1139,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.4.tgz", - "integrity": "sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", + "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", + "@typescript-eslint/scope-manager": "6.9.0", + "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/typescript-estree": "6.9.0", "semver": "^7.5.4" }, "engines": { @@ -1161,12 +1164,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz", - "integrity": "sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", + "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.4", + "@typescript-eslint/types": "6.9.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1460,9 +1463,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001542", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001542.tgz", - "integrity": "sha512-UrtAXVcj1mvPBFQ4sKd38daP8dEcXXr5sQe6QNNinaPd0iA/cxg9/l3VrSdL73jgw5sKyuQ6jNgiKO12W3SsVA==", + "version": "1.0.30001549", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", + "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", "dev": true, "funding": [ { @@ -1581,9 +1584,9 @@ "dev": true }, "node_modules/commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "engines": { "node": ">=16" @@ -1710,9 +1713,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.537", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz", - "integrity": "sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==", + "version": "1.4.556", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz", + "integrity": "sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ==", "dev": true }, "node_modules/email-addresses": { @@ -1755,16 +1758,16 @@ } }, "node_modules/eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", - "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.50.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2067,13 +2070,13 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "peer": true, "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, @@ -2274,9 +2277,9 @@ } }, "node_modules/globals": { - "version": "13.22.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", - "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "peer": true, "dependencies": { @@ -2757,9 +2760,9 @@ "dev": true }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "peer": true, "dependencies": { @@ -3768,9 +3771,9 @@ } }, "node_modules/shiki": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz", - "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -3786,9 +3789,9 @@ "dev": true }, "node_modules/sinon": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.0.0.tgz", - "integrity": "sha512-B8AaZZm9CT5pqe4l4uWJztfD/mOTa7dL8Qo0W4+s+t74xECOgSZDDQCBjNgIK3+n4kyxQrSTv2V5ul8K25qkiQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.0.tgz", + "integrity": "sha512-ZSgzF0vwmoa8pq0GEynqfdnpEDyP1PkYmEChnkjW0Vyh8IDlyFEJ+fkMhCP0il6d5cJjPl2PUsnUSAuP5sttOQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -4115,9 +4118,9 @@ } }, "node_modules/typedoc": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", - "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz", + "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -4172,6 +4175,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true, + "peer": true + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -4467,31 +4477,13 @@ "license": "MIT", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.11", + "@redis/client": "2.0.0-next.2", "@redis/graph": "1.1.0", "@redis/json": "1.0.6", "@redis/search": "1.1.5", "@redis/time-series": "1.0.5" } }, - "packages/redis/node_modules/@redis/client": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.11.tgz", - "integrity": "sha512-cV7yHcOAtNQ5x/yQl7Yw1xf53kO0FNDTdDU6bFIMbW6ljB7U7ns0YRM+QIkpoqTAt6zK5k9Fq0QWlUbLcq9AvA==", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "packages/redis/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "packages/search": { "name": "@redis/search", "version": "1.1.5", diff --git a/package.json b/package.json index 777df03e6f2..9bd08c7401d 100644 --- a/package.json +++ b/package.json @@ -6,22 +6,22 @@ ], "scripts": { "test": "npm run test -ws --if-present", - "build": "tsc --build", + "build": "NODE_OPTIONS='--max-old-space-size=8192' tsc --build", "documentation": "typedoc", "gh-pages": "gh-pages -d ./documentation -e ./documentation -u 'documentation-bot '" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@tsconfig/node18": "^18.2.2", - "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", + "@types/mocha": "^10.0.3", + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "source-map-support": "^0.5.21", "ts-node": "^10.9.1", - "typedoc": "^0.25.1", + "typedoc": "^0.25.2", "typescript": "^5.2.2" } } diff --git a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts index 4af0d24db45..5b880e0dd9d 100644 --- a/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/LOADCHUNK.spec.ts @@ -19,7 +19,7 @@ describe('CF.LOADCHUNK', () => { ]); assert.equal( - await client.cf.loadChunk('destination', iterator, chunk), + await client.cf.loadChunk('destination', iterator, chunk!), 'OK' ); }, { diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 350d742178d..f87525225b2 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -2,8 +2,8 @@ "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "files": [ "dist/", "!dist/tsconfig.tsbuildinfo" diff --git a/packages/client/index.ts b/packages/client/index.ts index 8864cf65f2d..6d6efd07725 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -1,4 +1,4 @@ -export { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping/*, CommandPolicies*/ } from './lib/RESP/types'; +export { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping/*, CommandPolicies*/, RedisArgument } from './lib/RESP/types'; export { RESP_TYPES } from './lib/RESP/decoder'; export { VerbatimString } from './lib/RESP/verbatim-string'; export { defineScript } from './lib/lua-script'; diff --git a/packages/client/lib/commands/COMMAND_LIST.spec.ts b/packages/client/lib/commands/COMMAND_LIST.spec.ts index 266dda4198d..28a9a203bc8 100644 --- a/packages/client/lib/commands/COMMAND_LIST.spec.ts +++ b/packages/client/lib/commands/COMMAND_LIST.spec.ts @@ -1,56 +1,62 @@ -// import { strict as assert } from 'node:assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments, FilterBy } from './COMMAND_LIST'; +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import COMMAND_LIST from './COMMAND_LIST'; -// describe('COMMAND LIST', () => { -// testUtils.isVersionGreaterThanHook([7]); +describe('COMMAND LIST', () => { + testUtils.isVersionGreaterThanHook([7]); -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments(), -// ['COMMAND', 'LIST'] -// ); -// }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + COMMAND_LIST.transformArguments(), + ['COMMAND', 'LIST'] + ); + }); -// describe('with FILTERBY', () => { -// it('MODULE', () => { -// assert.deepEqual( -// transformArguments({ -// filterBy: FilterBy.MODULE, -// value: 'json' -// }), -// ['COMMAND', 'LIST', 'FILTERBY', 'MODULE', 'json'] -// ); -// }); + describe('with FILTERBY', () => { + it('MODULE', () => { + assert.deepEqual( + COMMAND_LIST.transformArguments({ + FILTERBY: { + type: 'MODULE', + value: 'JSON' + } + }), + ['COMMAND', 'LIST', 'FILTERBY', 'MODULE', 'JSON'] + ); + }); -// it('ACLCAT', () => { -// assert.deepEqual( -// transformArguments({ -// filterBy: FilterBy.ACLCAT, -// value: 'admin' -// }), -// ['COMMAND', 'LIST', 'FILTERBY', 'ACLCAT', 'admin'] -// ); -// }); + it('ACLCAT', () => { + assert.deepEqual( + COMMAND_LIST.transformArguments({ + FILTERBY: { + type: 'ACLCAT', + value: 'admin' + } + }), + ['COMMAND', 'LIST', 'FILTERBY', 'ACLCAT', 'admin'] + ); + }); -// it('PATTERN', () => { -// assert.deepEqual( -// transformArguments({ -// filterBy: FilterBy.PATTERN, -// value: 'a*' -// }), -// ['COMMAND', 'LIST', 'FILTERBY', 'PATTERN', 'a*'] -// ); -// }); -// }); -// }); + it('PATTERN', () => { + assert.deepEqual( + COMMAND_LIST.transformArguments({ + FILTERBY: { + type: 'PATTERN', + value: 'a*' + } + }), + ['COMMAND', 'LIST', 'FILTERBY', 'PATTERN', 'a*'] + ); + }); + }); + }); -// testUtils.testWithClient('client.commandList', async client => { -// const commandList = await client.commandList(); -// assert.ok(Array.isArray(commandList)); -// for (const command of commandList) { -// assert.ok(typeof command === 'string'); -// } -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testWithClient('client.commandList', async client => { + const commandList = await client.commandList(); + assert.ok(Array.isArray(commandList)); + for (const command of commandList) { + assert.ok(typeof command === 'string'); + } + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/COMMAND_LIST.ts b/packages/client/lib/commands/COMMAND_LIST.ts index eabf9856dd2..e73cfdc1a0b 100644 --- a/packages/client/lib/commands/COMMAND_LIST.ts +++ b/packages/client/lib/commands/COMMAND_LIST.ts @@ -1,31 +1,35 @@ -// import { RedisCommandArguments } from '.'; - -// export const IS_READ_ONLY = true; - -// export enum FilterBy { -// MODULE = 'MODULE', -// ACLCAT = 'ACLCAT', -// PATTERN = 'PATTERN' -// } - -// interface Filter { -// filterBy: FilterBy; -// value: string; -// } - - -// export function transformArguments(filter?: Filter): RedisCommandArguments { -// const args = ['COMMAND', 'LIST']; - -// if (filter) { -// args.push( -// 'FILTERBY', -// filter.filterBy, -// filter.value -// ); -// } - -// return args; -// } - -// export declare function transformReply(): Array; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; + +export const COMMAND_LIST_FILTER_BY = { + MODULE: 'MODULE', + ACLCAT: 'ACLCAT', + PATTERN: 'PATTERN' +} as const; + +export type CommandListFilterBy = typeof COMMAND_LIST_FILTER_BY[keyof typeof COMMAND_LIST_FILTER_BY]; + +export interface CommandListOptions { + FILTERBY?: { + type: CommandListFilterBy; + value: RedisArgument; + }; +} + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(options?: CommandListOptions) { + const args: Array = ['COMMAND', 'LIST']; + + if (options?.FILTERBY) { + args.push( + 'FILTERBY', + options.FILTERBY.type, + options.FILTERBY.value + ); + } + + return args; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZPOPMIN_COUNT.ts b/packages/client/lib/commands/ZPOPMIN_COUNT.ts index 36214ab1605..2433686da56 100644 --- a/packages/client/lib/commands/ZPOPMIN_COUNT.ts +++ b/packages/client/lib/commands/ZPOPMIN_COUNT.ts @@ -2,7 +2,7 @@ import { RedisArgument, Command } from '../RESP/types'; import { transformSortedSetReply } from './generic-transformers'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: false, transformArguments(key: RedisArgument, count: number) { return ['ZPOPMIN', key, count.toString()]; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 84a726d26e3..804277b4ae3 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -73,7 +73,7 @@ import COMMAND_COUNT from './COMMAND_COUNT'; import COMMAND_GETKEYS from './COMMAND_GETKEYS'; import COMMAND_GETKEYSANDFLAGS from './COMMAND_GETKEYSANDFLAGS'; // import COMMAND_INFO from './COMMAND_INFO'; -// import COMMAND_LIST from './COMMAND_LIST'; +import COMMAND_LIST from './COMMAND_LIST'; // import COMMAND from './COMMAND'; import CONFIG_GET from './CONFIG_GET'; import CONFIG_RESETASTAT from './CONFIG_RESETSTAT'; @@ -483,8 +483,8 @@ export default { commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS, // COMMAND_INFO, // commandInfo: COMMAND_INFO, - // COMMAND_LIST, - // commandList: COMMAND_LIST, + COMMAND_LIST, + commandList: COMMAND_LIST, // COMMAND, // command: COMMAND, CONFIG_GET, diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index 8a052354610..10032fb8451 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -14,7 +14,7 @@ type QueryRawReply = TuplesReply<[ metadata: Metadata ]>; -type QueryParam = null | string | number | boolean | QueryParams | Array; +type QueryParam = null | RedisArgument | number | boolean | QueryParams | Array; type QueryParams = { [key: string]: QueryParam; diff --git a/packages/graph/lib/commands/SLOWLOG.spec.ts b/packages/graph/lib/commands/SLOWLOG.spec.ts index a0201109861..c1c77286a26 100644 --- a/packages/graph/lib/commands/SLOWLOG.spec.ts +++ b/packages/graph/lib/commands/SLOWLOG.spec.ts @@ -5,7 +5,7 @@ import SLOWLOG from './SLOWLOG'; describe('GRAPH.SLOWLOG', () => { it('transformArguments', () => { assert.deepEqual( - transformArguments('key'), + SLOWLOG.transformArguments('key'), ['GRAPH.SLOWLOG', 'key'] ); }); diff --git a/packages/graph/lib/commands/index.ts b/packages/graph/lib/commands/index.ts index cba3305a3f1..e93356aa951 100644 --- a/packages/graph/lib/commands/index.ts +++ b/packages/graph/lib/commands/index.ts @@ -7,7 +7,7 @@ import LIST from './LIST'; import PROFILE from './PROFILE'; import QUERY from './QUERY'; import RO_QUERY from './RO_QUERY'; -// import SLOWLOG from './SLOWLOG'; +import SLOWLOG from './SLOWLOG'; export default { CONFIG_GET, @@ -26,6 +26,6 @@ export default { query: QUERY, RO_QUERY, roQuery: RO_QUERY, - // SLOWLOG, - // slowLog: SLOWLOG + SLOWLOG, + slowLog: SLOWLOG } as const satisfies RedisCommands; diff --git a/packages/graph/package.json b/packages/graph/package.json index 207386f2e0b..dd5533f1bc7 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -2,8 +2,8 @@ "name": "@redis/graph", "version": "1.1.0", "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "files": [ "dist/", "!dist/tsconfig.tsbuildinfo" diff --git a/packages/json/package.json b/packages/json/package.json index ede25b229c2..7acbfc3d8d0 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -2,8 +2,8 @@ "name": "@redis/json", "version": "1.0.6", "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "files": [ "dist/" ], diff --git a/packages/redis/index.ts b/packages/redis/index.ts index 58552adf1f3..7586846d12c 100644 --- a/packages/redis/index.ts +++ b/packages/redis/index.ts @@ -2,12 +2,14 @@ import { RedisModules, RedisFunctions, RedisScripts, + RespVersions, + TypeMapping, createClient as _createClient, RedisClientOptions, RedisClientType as _RedisClientType, createCluster as _createCluster, RedisClusterOptions, - RedisClusterType as _RedisClusterType + RedisClusterType as _RedisClusterType, } from '@redis/client'; import RedisBloomModules from '@redis/bloom'; import RedisGraph from '@redis/graph'; @@ -15,12 +17,12 @@ import RedisJSON from '@redis/json'; import RediSearch from '@redis/search'; import RedisTimeSeries from '@redis/time-series'; -export * from '@redis/client'; -export * from '@redis/bloom'; -export * from '@redis/graph'; -export * from '@redis/json'; -export * from '@redis/search'; -export * from '@redis/time-series'; +// export * from '@redis/client'; +// export * from '@redis/bloom'; +// export * from '@redis/graph'; +// export * from '@redis/json'; +// export * from '@redis/search'; +// export * from '@redis/time-series'; const modules = { ...RedisBloomModules, @@ -34,17 +36,21 @@ export type RedisDefaultModules = typeof modules; export type RedisClientType< M extends RedisModules = RedisDefaultModules, - F extends RedisFunctions = Record, - S extends RedisScripts = Record -> = _RedisClientType; + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} +> = _RedisClientType; export function createClient< M extends RedisModules, F extends RedisFunctions, - S extends RedisScripts + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping >( - options?: RedisClientOptions -): _RedisClientType { + options?: RedisClientOptions +): _RedisClientType { return _createClient({ ...options, modules: { @@ -56,17 +62,21 @@ export function createClient< export type RedisClusterType< M extends RedisModules = RedisDefaultModules, - F extends RedisFunctions = Record, - S extends RedisScripts = Record -> = _RedisClusterType; + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} +> = _RedisClusterType; export function createCluster< M extends RedisModules, F extends RedisFunctions, - S extends RedisScripts + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping >( - options: RedisClusterOptions -): RedisClusterType { + options: RedisClusterOptions +): RedisClusterType { return _createCluster({ ...options, modules: { diff --git a/packages/redis/package.json b/packages/redis/package.json index c411080c163..3c7e2a1907c 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,7 +10,7 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.11", + "@redis/client": "2.0.0-next.2", "@redis/graph": "1.1.0", "@redis/json": "1.0.6", "@redis/search": "1.1.5", diff --git a/packages/search/lib/commands/SPELLCHECK.spec.ts b/packages/search/lib/commands/SPELLCHECK.spec.ts index 89ef0dfc1b7..a70ee964920 100644 --- a/packages/search/lib/commands/SPELLCHECK.spec.ts +++ b/packages/search/lib/commands/SPELLCHECK.spec.ts @@ -1,6 +1,5 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { SchemaFieldTypes } from '.'; import SPELLCHECK from './SPELLCHECK'; describe('FT.SPELLCHECK', () => { @@ -63,7 +62,7 @@ describe('FT.SPELLCHECK', () => { testUtils.testWithClient('client.ft.spellCheck', async client => { const [,, reply] = await Promise.all([ client.ft.create('index', { - field: SchemaFieldTypes.TEXT + field: 'TEXT' }), client.hSet('key', 'field', 'query'), client.ft.spellCheck('index', 'quer') diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index ccf72e8f4cc..43831c90ac5 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -14,8 +14,8 @@ import DICTADD from './DICTADD'; import DICTDEL from './DICTDEL'; import DICTDUMP from './DICTDUMP'; import DROPINDEX from './DROPINDEX'; -import EXPLAIN from './EXPLAIN'; -import EXPLAINCLI from './EXPLAINCLI'; +// import EXPLAIN from './EXPLAIN'; +// import EXPLAINCLI from './EXPLAINCLI'; // import INFO from './INFO'; // import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; @@ -32,9 +32,9 @@ import SYNDUMP from './SYNDUMP'; import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { SearchOptions } from './SEARCH'; -import { CommandArguments } from '@redis/client/dist/lib/RESP/types'; +// import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +// import { SearchOptions } from './SEARCH'; +// import { CommandArguments } from '@redis/client/dist/lib/RESP/types'; export default { _LIST, @@ -69,10 +69,10 @@ export default { dictDump: DICTDUMP, DROPINDEX, dropIndex: DROPINDEX, - EXPLAIN, - explain: EXPLAIN, - EXPLAINCLI, - explainCli: EXPLAINCLI, + // EXPLAIN, + // explain: EXPLAIN, + // EXPLAINCLI, + // explainCli: EXPLAINCLI, // INFO, // info: INFO, // PROFILESEARCH, @@ -135,41 +135,41 @@ export default { export type PropertyName = `${'@' | '$.'}${string}`; -export type SortByProperty = string | { - BY: string; - DIRECTION?: 'ASC' | 'DESC'; -}; +// export type SortByProperty = string | { +// BY: string; +// DIRECTION?: 'ASC' | 'DESC'; +// }; + +// export function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByProperty): 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: SortByProperty | Array): RedisCommandArguments { +// const lengthBefore = args.push( +// name, +// '' // will be overwritten +// ); -export function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByProperty): 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: SortByProperty | 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; -} +// 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: CommandArguments, fn: (args: CommandArguments) => void) { // const lengthIndex = args.push('') - 1; @@ -375,268 +375,268 @@ export function pushSortByArguments(args: RedisCommandArguments, name: string, s // } // } -export type Params = Record; - -export function pushParamsArgs( - args: RedisCommandArguments, - params?: Params -): RedisCommandArguments { - if (params) { - const enrties = Object.entries(params); - args.push('PARAMS', (enrties.length * 2).toString()); - for (const [key, value] of enrties) { - args.push(key, typeof value === 'number' ? value.toString() : value); - } - } - - return args; -} - -export function pushSearchOptions( - args: RedisCommandArguments, - options?: SearchOptions -): RedisCommandArguments { - if (options?.VERBATIM) { - args.push('VERBATIM'); - } - - if (options?.NOSTOPWORDS) { - args.push('NOSTOPWORDS'); - } - - // if (options?.WITHSCORES) { - // args.push('WITHSCORES'); - // } - - // if (options?.WITHPAYLOADS) { - // args.push('WITHPAYLOADS'); - // } - - pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); - pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); - pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); - - if (options?.SUMMARIZE) { - args.push('SUMMARIZE'); - - if (typeof options.SUMMARIZE === 'object') { - if (options.SUMMARIZE.FIELDS) { - args.push('FIELDS'); - pushVariadicArgument(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'); - pushVariadicArgument(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'); - pushSortByProperty(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() - ); - } - - if (options?.PARAMS) { - pushParamsArgs(args, options.PARAMS); - } - - if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); - } - - if (options?.RETURN?.length === 0) { - args.preserve = true; - } - - if (options?.TIMEOUT !== undefined) { - args.push('TIMEOUT', options.TIMEOUT.toString()); - } - - return args; -} - -interface SearchDocumentValue { - [key: string]: string | number | null | Array | SearchDocumentValue; -} - -export interface SearchReply { - total: number; - documents: Array<{ - id: string; - value: SearchDocumentValue; - }>; -} - -export interface ProfileOptions { - LIMITED?: true; -} - -export type ProfileRawReply = [ - results: T, - profile: [ - _: string, - TotalProfileTime: string, - _: string, - ParsingTime: string, - _: string, - PipelineCreationTime: string, - _: string, - IteratorsProfile: Array - ] -]; - -export interface ProfileReply { - results: SearchReply | AGGREGATE.AggregateReply; - profile: ProfileData; -} - -interface ChildIterator { - type?: string, - counter?: number, - term?: string, - size?: number, - time?: string, - childIterators?: Array -} - -interface IteratorsProfile { - type?: string, - counter?: number, - queryType?: string, - time?: string, - childIterators?: Array -} - -interface ProfileData { - totalProfileTime: string, - parsingTime: string, - pipelineCreationTime: string, - iteratorsProfile: IteratorsProfile -} - -export function transformProfile(reply: Array): ProfileData { - return { - totalProfileTime: reply[0][1], - parsingTime: reply[1][1], - pipelineCreationTime: reply[2][1], - iteratorsProfile: transformIterators(reply[3][1]) - }; -} - -function transformIterators(IteratorsProfile: Array): IteratorsProfile { - var res: IteratorsProfile = {}; - for (let i = 0; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i + 1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Query type': - res.queryType = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } - } - - return res; -} - -function transformChildIterators(IteratorsProfile: Array): ChildIterator { - var res: ChildIterator = {}; - for (let i = 1; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i + 1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Size': - res.size = value; - break; - case 'Term': - res.term = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } - } - - return res; -} +// export type Params = Record; + +// export function pushParamsArgs( +// args: RedisCommandArguments, +// params?: Params +// ): RedisCommandArguments { +// if (params) { +// const enrties = Object.entries(params); +// args.push('PARAMS', (enrties.length * 2).toString()); +// for (const [key, value] of enrties) { +// args.push(key, typeof value === 'number' ? value.toString() : value); +// } +// } + +// return args; +// } + +// export function pushSearchOptions( +// args: RedisCommandArguments, +// options?: SearchOptions +// ): RedisCommandArguments { +// if (options?.VERBATIM) { +// args.push('VERBATIM'); +// } + +// if (options?.NOSTOPWORDS) { +// args.push('NOSTOPWORDS'); +// } + +// // if (options?.WITHSCORES) { +// // args.push('WITHSCORES'); +// // } + +// // if (options?.WITHPAYLOADS) { +// // args.push('WITHPAYLOADS'); +// // } + +// pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); +// pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); +// pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); + +// if (options?.SUMMARIZE) { +// args.push('SUMMARIZE'); + +// if (typeof options.SUMMARIZE === 'object') { +// if (options.SUMMARIZE.FIELDS) { +// args.push('FIELDS'); +// pushVariadicArgument(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'); +// pushVariadicArgument(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'); +// pushSortByProperty(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() +// ); +// } + +// if (options?.PARAMS) { +// pushParamsArgs(args, options.PARAMS); +// } + +// if (options?.DIALECT) { +// args.push('DIALECT', options.DIALECT.toString()); +// } + +// if (options?.RETURN?.length === 0) { +// args.preserve = true; +// } + +// if (options?.TIMEOUT !== undefined) { +// args.push('TIMEOUT', options.TIMEOUT.toString()); +// } + +// return args; +// } + +// interface SearchDocumentValue { +// [key: string]: string | number | null | Array | SearchDocumentValue; +// } + +// export interface SearchReply { +// total: number; +// documents: Array<{ +// id: string; +// value: SearchDocumentValue; +// }>; +// } + +// export interface ProfileOptions { +// LIMITED?: true; +// } + +// export type ProfileRawReply = [ +// results: T, +// profile: [ +// _: string, +// TotalProfileTime: string, +// _: string, +// ParsingTime: string, +// _: string, +// PipelineCreationTime: string, +// _: string, +// IteratorsProfile: Array +// ] +// ]; + +// export interface ProfileReply { +// results: SearchReply | AGGREGATE.AggregateReply; +// profile: ProfileData; +// } + +// interface ChildIterator { +// type?: string, +// counter?: number, +// term?: string, +// size?: number, +// time?: string, +// childIterators?: Array +// } + +// interface IteratorsProfile { +// type?: string, +// counter?: number, +// queryType?: string, +// time?: string, +// childIterators?: Array +// } + +// interface ProfileData { +// totalProfileTime: string, +// parsingTime: string, +// pipelineCreationTime: string, +// iteratorsProfile: IteratorsProfile +// } + +// export function transformProfile(reply: Array): ProfileData { +// return { +// totalProfileTime: reply[0][1], +// parsingTime: reply[1][1], +// pipelineCreationTime: reply[2][1], +// iteratorsProfile: transformIterators(reply[3][1]) +// }; +// } + +// function transformIterators(IteratorsProfile: Array): IteratorsProfile { +// var res: IteratorsProfile = {}; +// for (let i = 0; i < IteratorsProfile.length; i += 2) { +// const value = IteratorsProfile[i + 1]; +// switch (IteratorsProfile[i]) { +// case 'Type': +// res.type = value; +// break; +// case 'Counter': +// res.counter = value; +// break; +// case 'Time': +// res.time = value; +// break; +// case 'Query type': +// res.queryType = value; +// break; +// case 'Child iterators': +// res.childIterators = value.map(transformChildIterators); +// break; +// } +// } + +// return res; +// } + +// function transformChildIterators(IteratorsProfile: Array): ChildIterator { +// var res: ChildIterator = {}; +// for (let i = 1; i < IteratorsProfile.length; i += 2) { +// const value = IteratorsProfile[i + 1]; +// switch (IteratorsProfile[i]) { +// case 'Type': +// res.type = value; +// break; +// case 'Counter': +// res.counter = value; +// break; +// case 'Time': +// res.time = value; +// break; +// case 'Size': +// res.size = value; +// break; +// case 'Term': +// res.term = value; +// break; +// case 'Child iterators': +// res.childIterators = value.map(transformChildIterators); +// break; +// } +// } + +// return res; +// } diff --git a/packages/search/lib/index.ts b/packages/search/lib/index.ts index 296136021ef..08097d0dc6e 100644 --- a/packages/search/lib/index.ts +++ b/packages/search/lib/index.ts @@ -1,5 +1,7 @@ export { default } from './commands'; -export { RediSearchSchema, SchemaFieldTypes, SchemaTextFieldPhonetics, SearchReply, VectorAlgorithms } from './commands'; -export { AggregateSteps, AggregateGroupByReducers } from './commands/AGGREGATE'; -export { SearchOptions } from './commands/SEARCH'; +export { SCHEMA_FIELD_TYPE, SchemaFieldType } from './commands/CREATE'; + +// export { RediSearchSchema, SchemaFieldTypes, SchemaTextFieldPhonetics, SearchReply, VectorAlgorithms } from './commands'; +// export { AggregateSteps, AggregateGroupByReducers } from './commands/AGGREGATE'; +// export { SearchOptions } from './commands/SEARCH'; diff --git a/packages/search/package.json b/packages/search/package.json index 71963b3cf26..ede33a6d839 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -2,8 +2,8 @@ "name": "@redis/search", "version": "1.1.5", "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "files": [ "dist/", "!dist/tsconfig.tsbuildinfo" diff --git a/packages/time-series/lib/commands/MRANGE.ts b/packages/time-series/lib/commands/MRANGE.ts index 8fbbe7cb81c..a3a3db8ab83 100644 --- a/packages/time-series/lib/commands/MRANGE.ts +++ b/packages/time-series/lib/commands/MRANGE.ts @@ -1,5 +1,5 @@ import { RedisArgument, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; -import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { Timestamp } from '.'; import { TsRangeOptions, pushRangeArguments } from './RANGE'; import { pushFilterArgument } from './MGET'; @@ -63,6 +63,5 @@ export default { IS_READ_ONLY: true, transformArguments: transformMRangeArguments.bind(undefined, 'TS.MRANGE'), // TODO - // export { transformMRangeReply as transformReply } from '.'; transformReply: undefined as unknown as () => any } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts index 06885738786..9336626ab4d 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts @@ -27,6 +27,5 @@ export default { IS_READ_ONLY: true, transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MRANGE'), // TODO - // export { transformMRangeWithLabelsReply as transformReply } from '.'; transformReply: undefined as unknown as () => any } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts index 281b3235d83..6187ec621bb 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts @@ -1,11 +1,9 @@ import { Command } from '@redis/client/dist/lib/RESP/types'; -import { transformMRangeWithLabelsArguments } from './MRANGE_WITHLABELS'; +import MRANGE_WITHLABELS, { transformMRangeWithLabelsArguments } from './MRANGE_WITHLABELS'; export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, + FIRST_KEY_INDEX: MRANGE_WITHLABELS.FIRST_KEY_INDEX, + IS_READ_ONLY: MRANGE_WITHLABELS.IS_READ_ONLY, transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MREVRANGE'), - // TODO - // export { transformMRangeWithLabelsReply as transformReply } from '.'; - transformReply: undefined as unknown as () => any + transformReply: MRANGE_WITHLABELS.transformReply } as const satisfies Command; diff --git a/packages/time-series/lib/commands/RANGE.ts b/packages/time-series/lib/commands/RANGE.ts index 0bbe55aebaf..5f6635b3b3d 100644 --- a/packages/time-series/lib/commands/RANGE.ts +++ b/packages/time-series/lib/commands/RANGE.ts @@ -1,5 +1,5 @@ -import { CommandArguments, RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -import { Timestamp, transformTimestampArgument } from '.'; +import { CommandArguments, RedisArgument, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { Timestamp, transformTimestampArgument, SampleRawReply, transformSampleReply } from '.'; import { TimeSeriesAggregationType } from './CREATERULE'; export const TIME_SERIES_BUCKET_TIMESTAMP = { @@ -107,11 +107,13 @@ export default { FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments: transformRangeArguments.bind(undefined, 'TS.RANGE'), - // TODO - // import { SampleReply, transformRangeReply } from '.'; - // export function transformReply(reply: Array): Array { - // return transformRangeReply(reply); - // } - transformReply: undefined as unknown as () => any + transformReply: { + 2(reply: UnwrapReply>) { + return reply.map(sample => transformSampleReply['2'](sample)); + }, + 3(reply: UnwrapReply>) { + return reply.map(sample => transformSampleReply['3'](sample)); + } + } } as const satisfies Command; diff --git a/packages/time-series/lib/commands/REVRANGE.spec.ts b/packages/time-series/lib/commands/REVRANGE.spec.ts index 00194aaf3cf..c371e8306b0 100644 --- a/packages/time-series/lib/commands/REVRANGE.spec.ts +++ b/packages/time-series/lib/commands/REVRANGE.spec.ts @@ -1,94 +1,33 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './REVRANGE'; -import { TimeSeriesAggregationType } from '.'; +import REVRANGE from './REVRANGE'; +import { TIME_SERIES_AGGREGATION_TYPE } from '../index'; describe('TS.REVRANGE', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', '-', '+'), - ['TS.REVRANGE', 'key', '-', '+'] - ); - }); - - it('with FILTER_BY_TS', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_TS: [0] - }), - ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0'] - ); - }); - - it('with FILTER_BY_VALUE', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_VALUE: { - min: 1, - max: 2 - } - }), - ['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2'] - ); - }); - - it('with COUNT', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - COUNT: 1 - }), - ['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1'] - ); - }); - - it('with ALIGN', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - ALIGN: '-' - }), - ['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-'] - ); - }); - - it('with AGGREGATION', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - } - }), - ['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1'] - ); - }); - - it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { - assert.deepEqual( - transformArguments('key', '-', '+', { - FILTER_BY_TS: [0], - FILTER_BY_VALUE: { - min: 1, - max: 2 - }, - COUNT: 1, - ALIGN: '-', - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 1 - } - }), - [ - 'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', - '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1' - ] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + REVRANGE.transformArguments('key', '-', '+', { + FILTER_BY_TS: [0], + FILTER_BY_VALUE: { + min: 1, + max: 2 + }, + COUNT: 1, + ALIGN: '-', + AGGREGATION: { + type: TIME_SERIES_AGGREGATION_TYPE.AVG, + timeBucket: 1 + } + }), + [ + 'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', + '1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1' + ] + ); }); testUtils.testWithClient('client.ts.revRange', async client => { - const [, , reply] = await Promise.all([ - client.ts.add('key', 0, 1), + const [, reply] = await Promise.all([ client.ts.add('key', 1, 2), client.ts.revRange('key', '-', '+') ]); @@ -96,9 +35,6 @@ describe('TS.REVRANGE', () => { assert.deepEqual(reply, [{ timestamp: 1, value: 2 - }, { - timestamp: 0, - value: 1 }]); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index ff82cb893e9..e9137a15a00 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -137,27 +137,20 @@ export function pushLabelsArgument(args: Array, labels?: Labels) return args; } -// export type RawLabelsReply = ArrayReply>; - -// export function transformLablesReply(reply: RawLabelsReply) { -// const labels: Record = {}; - -// for (const [key, value] of reply) { -// labels[key.toString()] = value; -// } - -// return labels -// } +export type SampleRawReply = { + 2: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>; + 3: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>; +}; export const transformSampleReply = { - 2(reply: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>) { + 2(reply: SampleRawReply[2]) { const [timestamp, value] = reply as unknown as UnwrapReply; return { timestamp, value: Number(value) }; }, - 3(reply: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>) { + 3(reply: SampleRawReply[3]) { const [timestamp, value] = reply as unknown as UnwrapReply; return { timestamp, @@ -166,136 +159,6 @@ export const transformSampleReply = { } }; -// export enum TimeSeriesBucketTimestamp { -// LOW = '-', -// HIGH = '+', -// MID = '~' -// } - -// export interface RangeOptions { -// LATEST?: boolean; -// FILTER_BY_TS?: Array; -// FILTER_BY_VALUE?: { -// min: number; -// max: number; -// }; -// COUNT?: number; -// ALIGN?: Timestamp; -// AGGREGATION?: { -// type: TimeSeriesAggregationType; -// timeBucket: Timestamp; -// BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp; -// EMPTY?: boolean; -// }; -// } - -// export function pushRangeArguments( -// args: RedisCommandArguments, -// fromTimestamp: Timestamp, -// toTimestamp: Timestamp, -// options?: RangeOptions -// ): RedisCommandArguments { -// args.push( -// transformTimestampArgument(fromTimestamp), -// transformTimestampArgument(toTimestamp) -// ); - -// pushLatestArgument(args, options?.LATEST); - -// if (options?.FILTER_BY_TS) { -// args.push('FILTER_BY_TS'); -// for (const ts of options.FILTER_BY_TS) { -// args.push(transformTimestampArgument(ts)); -// } -// } - -// if (options?.FILTER_BY_VALUE) { -// args.push( -// 'FILTER_BY_VALUE', -// options.FILTER_BY_VALUE.min.toString(), -// options.FILTER_BY_VALUE.max.toString() -// ); -// } - -// if (options?.COUNT) { -// args.push( -// 'COUNT', -// options.COUNT.toString() -// ); -// } - -// if (options?.ALIGN) { -// args.push( -// 'ALIGN', -// transformTimestampArgument(options.ALIGN) -// ); -// } - -// if (options?.AGGREGATION) { -// args.push( -// 'AGGREGATION', -// options.AGGREGATION.type, -// transformTimestampArgument(options.AGGREGATION.timeBucket) -// ); - -// if (options.AGGREGATION.BUCKETTIMESTAMP) { -// args.push( -// 'BUCKETTIMESTAMP', -// options.AGGREGATION.BUCKETTIMESTAMP -// ); -// } - -// if (options.AGGREGATION.EMPTY) { -// args.push('EMPTY'); -// } -// } - -// return args; -// } - -// interface MRangeGroupBy { -// label: string; -// reducer: TimeSeriesReducers; -// } - -// export function pushMRangeGroupByArguments(args: RedisCommandArguments, groupBy?: MRangeGroupBy): RedisCommandArguments { -// if (groupBy) { -// args.push( -// 'GROUPBY', -// groupBy.label, -// 'REDUCE', -// groupBy.reducer -// ); -// } - -// return args; -// } - -// export type Filter = string | Array; - -// export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array): RedisCommandArguments { -// args.push('FILTER'); -// return pushVariadicArguments(args, filter); -// } - -// export interface MRangeOptions extends RangeOptions { -// GROUPBY?: MRangeGroupBy; -// } - -// export function pushMRangeArguments( -// args: RedisCommandArguments, -// fromTimestamp: Timestamp, -// toTimestamp: Timestamp, -// filter: Filter, -// options?: MRangeOptions -// ): RedisCommandArguments { -// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); -// args = pushFilterArgument(args, filter); -// return pushMRangeGroupByArguments(args, options?.GROUPBY); -// } - -// export type SelectedLabels = string | Array; - export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: RedisVariadicArgument) { if (!selectedLabels) { args.push('WITHLABELS'); @@ -305,65 +168,3 @@ export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: return pushVariadicArguments(args, selectedLabels); } } - -// export interface MRangeWithLabelsOptions extends MRangeOptions { -// SELECTED_LABELS?: SelectedLabels; -// } - -// export function pushMRangeWithLabelsArguments( -// args: RedisCommandArguments, -// fromTimestamp: Timestamp, -// toTimestamp: Timestamp, -// filter: Filter, -// options?: MRangeWithLabelsOptions -// ): RedisCommandArguments { -// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options); -// args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); -// args = pushFilterArgument(args, filter); -// return pushMRangeGroupByArguments(args, options?.GROUPBY); -// } - -// export function transformRangeReply(reply: Array): Array { -// return reply.map(transformSampleReply); -// } - -// type MRangeRawReply = Array<[ -// key: string, -// labels: RawLabels, -// samples: Array -// ]>; - -// interface MRangeReplyItem { -// key: string; -// samples: Array; -// } - -// export function transformMRangeReply(reply: MRangeRawReply): Array { -// const args = []; - -// for (const [key, _, sample] of reply) { -// args.push({ -// key, -// samples: sample.map(transformSampleReply) -// }); -// } - -// return args; -// } -// export interface MRangeWithLabelsReplyItem extends MRangeReplyItem { -// labels: Labels; -// } - -// export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array { -// const args = []; - -// for (const [key, labels, samples] of reply) { -// args.push({ -// key, -// labels: transformLablesReply(labels), -// samples: samples.map(transformSampleReply) -// }); -// } - -// return args; -// } diff --git a/packages/time-series/package.json b/packages/time-series/package.json index d340080266c..1ffa3bd1038 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -2,8 +2,8 @@ "name": "@redis/time-series", "version": "1.0.5", "license": "MIT", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", + "main": "./dist/lib/index.js", + "types": "./dist/lib/index.d.ts", "files": [ "dist/", "!dist/tsconfig.tsbuildinfo" From ebca66d6f6afb88bab6dc2fae6d38e9fff89bc07 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 1 Nov 2023 14:09:58 -0400 Subject: [PATCH 242/325] WIP --- package-lock.json | 567 ++++++++--- package.json | 11 +- packages/bloom/lib/commands/bloom/RESERVE.ts | 1 - packages/bloom/lib/commands/cuckoo/DEL.ts | 2 +- packages/bloom/lib/commands/cuckoo/EXISTS.ts | 2 +- packages/bloom/package.json | 2 +- packages/client/lib/RESP/types.ts | 5 - packages/client/lib/client/legacy-mode.ts | 2 +- packages/client/lib/client/multi-command.ts | 2 +- packages/client/lib/cluster/cluster-slots.ts | 8 +- packages/client/lib/cluster/multi-command.ts | 2 +- .../lib/commands/CLIENT_TRACKINGINFO.spec.ts | 1 - packages/client/lib/commands/FCALL.ts | 2 +- packages/client/lib/commands/FCALL_RO.ts | 2 +- packages/client/lib/commands/FUNCTION_LIST.ts | 2 +- .../lib/commands/GEORADIUSBYMEMBER_WITH.ts | 2 +- packages/client/lib/commands/MEMORY_STATS.ts | 2 +- packages/client/lib/commands/MODULE_LOAD.ts | 1 - packages/client/lib/commands/UNWATCH.ts | 2 +- packages/client/lib/commands/ZINCRBY.ts | 2 +- packages/client/lib/commands/ZSCAN.ts | 2 +- .../lib/commands/generic-transformers.ts | 2 +- packages/client/package.json | 2 +- packages/graph/lib/graph.ts | 4 +- packages/graph/package.json | 2 +- packages/json/lib/commands/DEBUG_MEMORY.ts | 2 +- packages/json/package.json | 2 +- .../search/lib/commands/AGGREGATE.spec.ts | 944 +++++++++--------- packages/search/lib/commands/AGGREGATE.ts | 459 ++++----- .../lib/commands/AGGREGATE_WITHCURSOR.spec.ts | 66 +- .../lib/commands/AGGREGATE_WITHCURSOR.ts | 103 +- packages/search/lib/commands/CREATE.ts | 7 +- packages/search/lib/commands/SEARCH.spec.ts | 559 ++++++----- packages/search/lib/commands/SEARCH.ts | 247 +++-- .../lib/commands/SEARCH_NOCONTENT.spec.ts | 65 +- .../search/lib/commands/SEARCH_NOCONTENT.ts | 43 +- packages/search/lib/commands/index.ts | 558 +---------- packages/search/package.json | 2 +- packages/test-utils/lib/dockers.ts | 2 +- packages/time-series/lib/index.ts | 10 +- packages/time-series/package.json | 2 +- tsconfig.base.json | 16 +- 42 files changed, 1767 insertions(+), 1952 deletions(-) diff --git a/package-lock.json b/package-lock.json index 724dae3bcef..f28500f157c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,15 +10,14 @@ ], "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.3", + "@types/node": "^20.8.9", "@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/parser": "^6.9.0", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", + "tsx": "^3.14.0", "typedoc": "^0.25.2", "typescript": "^5.2.2" } @@ -509,26 +508,356 @@ "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, "node_modules/@eslint-community/eslint-utils": { @@ -903,36 +1232,6 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@tsconfig/node18": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.2.tgz", - "integrity": "sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -946,13 +1245,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, - "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { @@ -1185,6 +1483,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1202,15 +1501,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1311,12 +1601,6 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1610,12 +1894,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1736,6 +2014,43 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -2193,6 +2508,18 @@ "node": ">=8.0.0" } }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/gh-pages": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.0.0.tgz", @@ -2872,12 +3199,6 @@ "semver": "bin/semver.js" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -3633,6 +3954,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4021,56 +4351,21 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/tsx": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", + "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "esbuild": "~0.18.20", + "get-tsconfig": "^4.7.2", + "source-map-support": "^0.5.21" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "tsx": "dist/cli.mjs" }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" + "optionalDependencies": { + "fsevents": "~2.3.3" } }, "node_modules/type-check": { @@ -4176,11 +4471,10 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", - "dev": true, - "peer": true + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/universalify": { "version": "2.0.0", @@ -4240,12 +4534,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", @@ -4401,15 +4689,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 9bd08c7401d..a3f3d3a8c4f 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,15 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@tsconfig/node18": "^18.2.2", "@types/mocha": "^10.0.3", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@types/node": "^20.8.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "source-map-support": "^0.5.21", - "ts-node": "^10.9.1", - "typedoc": "^0.25.2", + "tsx": "^3.14.0", + "typedoc": "^0.25.3", "typescript": "^5.2.2" } } diff --git a/packages/bloom/lib/commands/bloom/RESERVE.ts b/packages/bloom/lib/commands/bloom/RESERVE.ts index c4602535236..6bccb1d1d13 100644 --- a/packages/bloom/lib/commands/bloom/RESERVE.ts +++ b/packages/bloom/lib/commands/bloom/RESERVE.ts @@ -1,5 +1,4 @@ import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; export interface BfReserveOptions { EXPANSION?: number; diff --git a/packages/bloom/lib/commands/cuckoo/DEL.ts b/packages/bloom/lib/commands/cuckoo/DEL.ts index 55cefb4a054..0af8ebc851b 100644 --- a/packages/bloom/lib/commands/cuckoo/DEL.ts +++ b/packages/bloom/lib/commands/cuckoo/DEL.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { diff --git a/packages/bloom/lib/commands/cuckoo/EXISTS.ts b/packages/bloom/lib/commands/cuckoo/EXISTS.ts index 1cb6b4df8fa..8fd74ca47ca 100644 --- a/packages/bloom/lib/commands/cuckoo/EXISTS.ts +++ b/packages/bloom/lib/commands/cuckoo/EXISTS.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; import { transformBooleanReply } from '@redis/client/dist/lib/commands/generic-transformers'; export default { diff --git a/packages/bloom/package.json b/packages/bloom/package.json index f87525225b2..f76224f2016 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index c4ad18e1a1f..9f0e9217345 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -210,11 +210,6 @@ export type ReplyWithTypeMapping< ) ); -type a = ReplyWithTypeMapping< - ArrayReply>, - {} ->; - export type TransformReply = (this: void, reply: any, preserve?: any) => any; // TODO; export type RedisArgument = string | Buffer; diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 532c23fafb3..555c4eaae52 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -1,4 +1,4 @@ -import { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, Command, CommandArguments, ReplyUnion } from '../RESP/types'; +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, Command, CommandArguments, ReplyUnion } from '../RESP/types'; import { RedisClientType } from '.'; import { getTransformReply } from '../commander'; import { ErrorReply } from '../errors'; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 267444ad31a..c078193f64b 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import { RedisClientType } from '.'; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 79fd2e2aeb0..6fc0af8c919 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -1,16 +1,10 @@ import { RedisClusterClientOptions, RedisClusterOptions } from '.'; import { RootNodesUnavailableError } from '../errors'; import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; -import { types } from 'node:util'; import { EventEmitter } from 'node:stream'; import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; - -// TODO: ?! -// We need to use 'require', because it's not possible with Typescript to import -// function that are exported as 'module.exports = function`, without esModuleInterop -// set to true. -const calculateSlot = require('cluster-key-slot'); +import calculateSlot from 'cluster-key-slot'; interface NodeAddress { host: string; diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index a0292356dab..d036256247b 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; -import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, ReplyUnion, RedisArgument } from '../RESP/types'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, RedisArgument } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; import RedisCluster, { RedisClusterType } from '.'; diff --git a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts index 0921a9141fe..1cefbd27d53 100644 --- a/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts +++ b/packages/client/lib/commands/CLIENT_TRACKINGINFO.spec.ts @@ -1,7 +1,6 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import CLIENT_TRACKINGINFO from './CLIENT_TRACKINGINFO'; -import { RESP_TYPES } from '../RESP/decoder'; describe('CLIENT TRACKINGINFO', () => { testUtils.isVersionGreaterThanHook([6, 2]); diff --git a/packages/client/lib/commands/FCALL.ts b/packages/client/lib/commands/FCALL.ts index 57b9f652319..ba371a81b13 100644 --- a/packages/client/lib/commands/FCALL.ts +++ b/packages/client/lib/commands/FCALL.ts @@ -1,5 +1,5 @@ import { Command } from '../RESP/types'; -import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; +import EVAL, { transformEvalArguments } from './EVAL'; export default { FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, diff --git a/packages/client/lib/commands/FCALL_RO.ts b/packages/client/lib/commands/FCALL_RO.ts index 700b25e5f7b..ec002a79f82 100644 --- a/packages/client/lib/commands/FCALL_RO.ts +++ b/packages/client/lib/commands/FCALL_RO.ts @@ -1,5 +1,5 @@ import { Command } from '../RESP/types'; -import EVAL, { EvalOptions, transformEvalArguments } from './EVAL'; +import EVAL, { transformEvalArguments } from './EVAL'; export default { FIRST_KEY_INDEX: EVAL.FIRST_KEY_INDEX, diff --git a/packages/client/lib/commands/FUNCTION_LIST.ts b/packages/client/lib/commands/FUNCTION_LIST.ts index 8993496ca2c..07c1ff2a000 100644 --- a/packages/client/lib/commands/FUNCTION_LIST.ts +++ b/packages/client/lib/commands/FUNCTION_LIST.ts @@ -1,4 +1,4 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types'; +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command } from '../RESP/types'; export interface FunctionListOptions { LIBRARYNAME?: RedisArgument; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts index 31480430b5f..be9472a438f 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts @@ -1,4 +1,4 @@ -import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { RedisArgument, CommandArguments, Command } from '../RESP/types'; import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; import { GeoSearchOptions, GeoUnits, pushGeoSearchOptions } from './GEOSEARCH'; import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; diff --git a/packages/client/lib/commands/MEMORY_STATS.ts b/packages/client/lib/commands/MEMORY_STATS.ts index 38deae90134..2192d619ee6 100644 --- a/packages/client/lib/commands/MEMORY_STATS.ts +++ b/packages/client/lib/commands/MEMORY_STATS.ts @@ -1,4 +1,4 @@ -import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types'; +import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Command } from '../RESP/types'; export type MemoryStatsReply = TuplesToMapReply<[ [BlobStringReply<'peak.allocated'>, NumberReply], diff --git a/packages/client/lib/commands/MODULE_LOAD.ts b/packages/client/lib/commands/MODULE_LOAD.ts index 293a18a03c6..82c5b81a905 100644 --- a/packages/client/lib/commands/MODULE_LOAD.ts +++ b/packages/client/lib/commands/MODULE_LOAD.ts @@ -1,5 +1,4 @@ import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; -import { pushVariadicArguments } from './generic-transformers'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts index 9dd83b9aee7..d12e9c2b949 100644 --- a/packages/client/lib/commands/UNWATCH.ts +++ b/packages/client/lib/commands/UNWATCH.ts @@ -1,4 +1,4 @@ -import { RedisArgument, SimpleStringReply, Command } from '../RESP/types'; +import { SimpleStringReply, Command } from '../RESP/types'; export default { FIRST_KEY_INDEX: undefined, diff --git a/packages/client/lib/commands/ZINCRBY.ts b/packages/client/lib/commands/ZINCRBY.ts index 3bb987d5f1c..d9e43845016 100644 --- a/packages/client/lib/commands/ZINCRBY.ts +++ b/packages/client/lib/commands/ZINCRBY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, Command } from '../RESP/types'; import { transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export default { diff --git a/packages/client/lib/commands/ZSCAN.ts b/packages/client/lib/commands/ZSCAN.ts index 68186afc0e0..853cdf098f6 100644 --- a/packages/client/lib/commands/ZSCAN.ts +++ b/packages/client/lib/commands/ZSCAN.ts @@ -1,6 +1,6 @@ import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; import { ScanCommonOptions, pushScanArguments } from './SCAN'; -import { SortedSetMember, transformDoubleReply, transformSortedSetReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export interface HScanEntry { field: BlobStringReply; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 5b8aa12d7e5..a96e79a9c51 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -1,4 +1,4 @@ -import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply, RespType } from '../RESP/types'; +import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types'; export function isNullReply(reply: unknown): reply is NullReply { return reply === null; diff --git a/packages/client/package.json b/packages/client/package.json index ed2e3128423..5bea1dd5ff6 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "dependencies": { "cluster-key-slot": "1.1.2", diff --git a/packages/graph/lib/graph.ts b/packages/graph/lib/graph.ts index 8866052bdad..72242d502b2 100644 --- a/packages/graph/lib/graph.ts +++ b/packages/graph/lib/graph.ts @@ -1,4 +1,4 @@ -import { RedisClientType } from '@redis/client/dist/lib/client/index'; +import { RedisClientType } from '@redis/client'; import { RedisArgument, RedisFunctions, RedisScripts } from '@redis/client/dist/lib/RESP/types'; import QUERY, { QueryOptions } from './commands/QUERY'; @@ -132,7 +132,7 @@ type GraphReply = { type GraphClientType = RedisClientType<{ graph: { query: typeof QUERY, - roQuery: typeof import('./commands/RO_QUERY').default + roQuery: typeof import('./commands/RO_QUERY.js').default } }, RedisFunctions, RedisScripts>; diff --git a/packages/graph/package.json b/packages/graph/package.json index dd5533f1bc7..c0851e5734a 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/json/lib/commands/DEBUG_MEMORY.ts b/packages/json/lib/commands/DEBUG_MEMORY.ts index a96f05b8064..c2e730b9dc2 100644 --- a/packages/json/lib/commands/DEBUG_MEMORY.ts +++ b/packages/json/lib/commands/DEBUG_MEMORY.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, ArrayReply, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; export interface JsonDebugMemoryOptions { path?: RedisArgument; diff --git a/packages/json/package.json b/packages/json/package.json index 7acbfc3d8d0..e52d12c9a95 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -8,7 +8,7 @@ "dist/" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index 08e8a87f231..c0b34997c63 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -1,509 +1,515 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { AggregateGroupByReducers, AggregateSteps, transformArguments } from './AGGREGATE'; -import { SchemaFieldTypes } from '.'; +import AGGREGATE from './AGGREGATE'; +// import { SchemaFieldTypes } from '.'; describe('AGGREGATE', () => { - describe('transformArguments', () => { - it('without options', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*'), + ['FT.AGGREGATE', 'index', '*'] + ); + }); + + it('with VERBATIM', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + VERBATIM: true + }), + ['FT.AGGREGATE', 'index', '*', 'VERBATIM'] + ); + }); + + describe('with LOAD', () => { + describe('single', () => { + describe('without alias', () => { + it('string', () => { assert.deepEqual( - transformArguments('index', '*'), - ['FT.AGGREGATE', 'index', '*'] + AGGREGATE.transformArguments('index', '*', { + LOAD: '@property' + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] ); - }); + }); - it('with VERBATIM', () => { + it('{ identifier: string }', () => { assert.deepEqual( - transformArguments('index', '*', { VERBATIM: true }), - ['FT.AGGREGATE', 'index', '*', 'VERBATIM'] + AGGREGATE.transformArguments('index', '*', { + LOAD: { + identifier: '@property' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property'] ); + }); }); - 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('with alias', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + LOAD: { + identifier: '@property', + AS: 'alias' + } + }), + ['FT.AGGREGATE', 'index', '*', 'LOAD', '3', '@property', 'AS', 'alias'] + ); + }); + }); + + it('multiple', () => { + assert.deepEqual( + AGGREGATE.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( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0'] + ); + }); + + it('with alias', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT', + AS: 'count' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT', '0', 'AS', 'count'] + ); + }); + }); + + describe('with properties', () => { + it('single', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + properties: '@property', + REDUCE: { + type: 'COUNT' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '1', '@property', 'REDUCE', 'COUNT', '0'] + ); }); it('multiple', () => { - assert.deepEqual( - transformArguments('index', '*', { LOAD: ['@1', '@2'] }), - ['FT.AGGREGATE', 'index', '*', 'LOAD', '2', '@1', '@2'] - ); + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + properties: ['@1', '@2'], + REDUCE: { + type: 'COUNT' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '2', '@1', '@2', 'REDUCE', 'COUNT', '0'] + ); }); + }); }); - 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'] - ); - }); - }); + it('COUNT_DISTINCT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT_DISTINCT', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCT', '1', '@property'] + ); + }); - 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'] - ); - }); - }); + it('COUNT_DISTINCTISH', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'COUNT_DISTINCTISH', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'COUNT_DISTINCTISH', '1', '@property'] + ); + }); - describe('APPLY', () => { - assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.APPLY, - expression: '@field + 1', - AS: 'as' - }] - }), - ['FT.AGGREGATE', 'index', '*', 'APPLY', '@field + 1', 'AS', 'as'] - ); - }); + it('SUM', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'SUM', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'SUM', '1', '@property'] + ); + }); - describe('LIMIT', () => { + it('MIN', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'MIN', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MIN', '1', '@property'] + ); + }); + + it('MAX', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'MAX', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'MAX', '1', '@property'] + ); + }); + + it('AVG', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'AVG', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'AVG', '1', '@property'] + ); + }); + + it('STDDEV', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'STDDEV', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'STDDEV', '1', '@property'] + ); + }); + + it('QUANTILE', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'QUANTILE', + property: '@property', + quantile: 0.5 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'QUANTILE', '2', '@property', '0.5'] + ); + }); + + it('TOLIST', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'TOLIST', + property: '@property' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'TOLIST', '1', '@property'] + ); + }); + + describe('FIRST_VALUE', () => { + it('simple', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: '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.LIMIT, - from: 0, - size: 1 - }] - }), - ['FT.AGGREGATE', 'index', '*', 'LIMIT', '0', '1'] + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: '@by' + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] ); - }); + }); + - describe('FILTER', () => { + it('{ property: string }', () => { assert.deepEqual( - transformArguments('index', '*', { - STEPS: [{ - type: AggregateSteps.FILTER, - expression: '@field != ""' - }] - }), - ['FT.AGGREGATE', 'index', '*', 'FILTER', '@field != ""'] + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: { + property: '@by' + } + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '3', '@property', 'BY', '@by'] ); + }); }); - }); - it('with PARAMS', () => { - assert.deepEqual( - transformArguments('index', '*', { - PARAMS: { - param: 'value' + it('with direction', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'FIRST_VALUE', + property: '@property', + BY: { + property: '@by', + direction: 'ASC' + } } + }] }), - ['FT.AGGREGATE', 'index', '*', 'PARAMS', '2', 'param', 'value'] - ); + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'FIRST_VALUE', '4', '@property', 'BY', '@by', 'ASC'] + ); + }); + }); }); - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', '*', { - DIALECT: 1 - }), - ['FT.AGGREGATE', 'index', '*', 'DIALECT', '1'] - ); + it('RANDOM_SAMPLE', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: { + type: 'RANDOM_SAMPLE', + property: '@property', + sampleSize: 1 + } + }] + }), + ['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'RANDOM_SAMPLE', '2', '@property', '1'] + ); + }); + }); + + describe('SORTBY', () => { + it('string', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: '@by' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by'] + ); }); - it('with TIMEOUT', () => { - assert.deepEqual( - transformArguments('index', '*', { TIMEOUT: 10 }), - ['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10'] - ); + it('Array', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: ['@1', '@2'] + }] + }), + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '2', '@1', '@2'] + ); }); - }); - testUtils.testWithClient('client.ft.aggregate', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC + it('with MAX', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'SORTBY', + BY: '@by', + MAX: 1 + }] }), - client.hSet('1', 'field', '1'), - client.hSet('2', 'field', '2') - ]); + ['FT.AGGREGATE', 'index', '*', 'SORTBY', '1', '@by', 'MAX', '1'] + ); + }); + }); + describe('APPLY', () => { 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 - } - }) - ] - } + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'APPLY', + expression: '@field + 1', + AS: 'as' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'APPLY', '@field + 1', 'AS', 'as'] + ); + }); + + describe('LIMIT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'LIMIT', + from: 0, + size: 1 + }] + }), + ['FT.AGGREGATE', 'index', '*', 'LIMIT', '0', '1'] + ); + }); + + describe('FILTER', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + STEPS: [{ + type: 'FILTER', + expression: '@field != ""' + }] + }), + ['FT.AGGREGATE', 'index', '*', 'FILTER', '@field != ""'] ); - }, GLOBAL.SERVERS.OPEN); + }); + }); + + it('with PARAMS', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + PARAMS: { + param: 'value' + } + }), + ['FT.AGGREGATE', 'index', '*', 'PARAMS', '2', 'param', 'value'] + ); + }); + + it('with DIALECT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { + DIALECT: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'DIALECT', '1'] + ); + }); + + it('with TIMEOUT', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { TIMEOUT: 10 }), + ['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10'] + ); + }); + }); + + testUtils.testWithClient('client.ft.aggregate', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'NUMERIC' + }), + client.hSet('1', 'field', '1'), + client.hSet('2', 'field', '2') + ]); + + assert.deepEqual( + await client.ft.aggregate('index', '*', { + STEPS: [{ + type: 'GROUPBY', + REDUCE: [{ + type: 'SUM', + property: '@field', + AS: 'sum' + }, { + type: '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 index 6739581538b..c21f1ce2a55 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -1,311 +1,294 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushVariadicArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; -import { Params, PropertyName, pushArgumentsWithLength, pushParamsArgs, pushSortByArguments, SortByProperty } from '.'; - -export enum AggregateSteps { - GROUPBY = 'GROUPBY', - SORTBY = 'SORTBY', - APPLY = 'APPLY', - LIMIT = 'LIMIT', - FILTER = 'FILTER' +import { Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RediSearchProperty } from './CREATE'; +import { FtSearchParams, pushParamsArgument } from './SEARCH'; +import { pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; + +type LoadField = RediSearchProperty | { + identifier: RediSearchProperty; + AS?: RedisArgument; } -interface AggregateStep { - type: T; +export const FT_AGGREGATE_STEPS = { + GROUPBY: 'GROUPBY', + SORTBY: 'SORTBY', + APPLY: 'APPLY', + LIMIT: 'LIMIT', + FILTER: 'FILTER' +} as const; + +type FT_AGGREGATE_STEPS = typeof FT_AGGREGATE_STEPS; + +export type FtAggregateStep = FT_AGGREGATE_STEPS[keyof FT_AGGREGATE_STEPS]; + +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' +export const FT_AGGREGATE_GROUP_BY_REDUCERS = { + COUNT: 'COUNT', + COUNT_DISTINCT: 'COUNT_DISTINCT', + COUNT_DISTINCTISH: 'COUNT_DISTINCTISH', + SUM: 'SUM', + MIN: 'MIN', + MAX: 'MAX', + AVG: 'AVG', + STDDEV: 'STDDEV', + QUANTILE: 'QUANTILE', + TOLIST: 'TOLIST', + FIRST_VALUE: 'FIRST_VALUE', + RANDOM_SAMPLE: 'RANDOM_SAMPLE' +} as const; + +type FT_AGGREGATE_GROUP_BY_REDUCERS = typeof FT_AGGREGATE_GROUP_BY_REDUCERS; + +export type FtAggregateGroupByReducer = FT_AGGREGATE_GROUP_BY_REDUCERS[keyof FT_AGGREGATE_GROUP_BY_REDUCERS]; + +interface GroupByReducer { + type: T; + AS?: RedisArgument; } -interface GroupByReducer { - type: T; - AS?: string; +interface GroupByReducerWithProperty extends GroupByReducer { + property: RediSearchProperty; } -type CountReducer = GroupByReducer; +type CountReducer = GroupByReducer; -interface CountDistinctReducer extends GroupByReducer { - property: PropertyName; -} +type CountDistinctReducer = GroupByReducerWithProperty; -interface CountDistinctishReducer extends GroupByReducer { - property: PropertyName; -} +type CountDistinctishReducer = GroupByReducerWithProperty; -interface SumReducer extends GroupByReducer { - property: PropertyName; -} +type SumReducer = GroupByReducerWithProperty; -interface MinReducer extends GroupByReducer { - property: PropertyName; -} +type MinReducer = GroupByReducerWithProperty; -interface MaxReducer extends GroupByReducer { - property: PropertyName; -} +type MaxReducer = GroupByReducerWithProperty; -interface AvgReducer extends GroupByReducer { - property: PropertyName; -} +type AvgReducer = GroupByReducerWithProperty; -interface StdDevReducer extends GroupByReducer { - property: PropertyName; -} +type StdDevReducer = GroupByReducerWithProperty; -interface QuantileReducer extends GroupByReducer { - property: PropertyName; - quantile: number; +interface QuantileReducer extends GroupByReducerWithProperty { + quantile: number; } -interface ToListReducer extends GroupByReducer { - property: PropertyName; -} +type ToListReducer = GroupByReducerWithProperty; -interface FirstValueReducer extends GroupByReducer { - property: PropertyName; - BY?: PropertyName | { - property: PropertyName; - direction?: 'ASC' | 'DESC'; - }; +interface FirstValueReducer extends GroupByReducerWithProperty { + BY?: RediSearchProperty | { + property: RediSearchProperty; + direction?: 'ASC' | 'DESC'; + }; } -interface RandomSampleReducer extends GroupByReducer { - property: PropertyName; - sampleSize: number; +interface RandomSampleReducer extends GroupByReducerWithProperty { + 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 GroupByStep extends AggregateStep { + properties?: RediSearchProperty | Array; + REDUCE: GroupByReducers | Array; } -interface SortStep extends AggregateStep { - BY: SortByProperty | Array; - MAX?: number; -} +type SortByProperty = RedisArgument | { + BY: RediSearchProperty; + DIRECTION?: 'ASC' | 'DESC'; +}; -interface ApplyStep extends AggregateStep { - expression: string; - AS: string; +interface SortStep extends AggregateStep { + BY: SortByProperty | Array; + MAX?: number; } -interface LimitStep extends AggregateStep { - from: number; - size: number; +interface ApplyStep extends AggregateStep { + expression: RedisArgument; + AS: RedisArgument; } -interface FilterStep extends AggregateStep { - expression: string; +interface LimitStep extends AggregateStep { + from: number; + size: number; } -type LoadField = PropertyName | { - identifier: PropertyName; - AS?: string; +interface FilterStep extends AggregateStep { + expression: RedisArgument; } -export interface AggregateOptions { - VERBATIM?: true; - LOAD?: LoadField | Array; - STEPS?: Array; - PARAMS?: Params; - DIALECT?: number; - TIMEOUT?: number; +export interface FtAggregateOptions { + VERBATIM?: boolean; + LOAD?: LoadField | Array; + TIMEOUT?: number; + STEPS?: Array; + PARAMS?: FtSearchParams; + DIALECT?: number; } -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateOptions) { + const args = ['FT.AGGREGATE', index, query]; -export function transformArguments( - index: string, - query: string, - options?: AggregateOptions -): RedisCommandArguments { - return pushAggregatehOptions( - ['FT.AGGREGATE', index, query], - options - ); -} - -export function pushAggregatehOptions( - args: RedisCommandArguments, - options?: AggregateOptions -): RedisCommandArguments { if (options?.VERBATIM) { - args.push('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!); - } - }); - } + const length = args.push('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 { - pushVariadicArgument(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; - } + if (Array.isArray(options.LOAD)) { + for (const load of options.LOAD) { + pushLoadField(args, load); } - } - - pushParamsArgs(args, options?.PARAMS); + } else { + pushLoadField(args, options.LOAD); + } - if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); + args[length - 1] = (args.length - length).toString(); } if (options?.TIMEOUT !== undefined) { - args.push('TIMEOUT', options.TIMEOUT.toString()); + args.push('TIMEOUT', options.TIMEOUT.toString()); } - return args; -} + if (options?.STEPS) { + for (const step of options.STEPS) { + args.push(step.type); + switch (step.type) { + case FT_AGGREGATE_STEPS.GROUPBY: + if (!step.properties) { + args.push('0'); + } else { + pushVariadicArgument(args, step.properties); + } -function pushLoadField(args: RedisCommandArguments, toLoad: LoadField): void { - if (typeof toLoad === 'string') { - args.push(toLoad); - } else { - args.push(toLoad.identifier); + if (Array.isArray(step.REDUCE)) { + for (const reducer of step.REDUCE) { + pushGroupByReducer(args, reducer); + } + } else { + pushGroupByReducer(args, step.REDUCE); + } - if (toLoad.AS) { - args.push('AS', toLoad.AS); - } - } -} + break; + + case FT_AGGREGATE_STEPS.SORTBY: + const length = args.push(''); + + if (Array.isArray(step.BY)) { + for (const by of step.BY) { + pushSortByProperty(args, by); + } + } else { + pushSortByProperty(args, step.BY); + } -function pushGroupByReducer(args: RedisCommandArguments, reducer: GroupByReducers): void { - args.push('REDUCE', reducer.type); + if (step.MAX) { + args.push('MAX', step.MAX.toString()); + } + + args[length - 1] = (args.length - length).toString(); - 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); + case FT_AGGREGATE_STEPS.APPLY: + args.push('APPLY', step.expression, 'AS', step.AS); break; - case AggregateGroupByReducers.QUANTILE: - args.push('2', reducer.property, reducer.quantile.toString()); + case FT_AGGREGATE_STEPS.LIMIT: + args.push('LIMIT', step.from.toString(), step.size.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); - } - } - } - }); + case FT_AGGREGATE_STEPS.FILTER: + args.push('FILTER', step.expression); break; } + } + } - case AggregateGroupByReducers.RANDOM_SAMPLE: - args.push('2', reducer.property, reducer.sampleSize.toString()); - break; + pushParamsArgument(args, options?.PARAMS); + + if (options?.DIALECT !== undefined) { + args.push('DIALECT', options.DIALECT.toString()); } - if (reducer.AS) { - args.push('AS', reducer.AS); + return args; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; + +function pushLoadField(args: Array, toLoad: LoadField) { + if (typeof toLoad === 'string' || toLoad instanceof Buffer) { + args.push(toLoad); + } else { + args.push(toLoad.identifier); + + if (toLoad.AS) { + args.push('AS', toLoad.AS); } + } } -export type AggregateRawReply = [ - total: number, - ...results: Array> -]; +function pushGroupByReducer(args: Array, reducer: GroupByReducers) { + args.push('REDUCE', reducer.type); + + switch (reducer.type) { + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT: + args.push('0'); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCT: + case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCTISH: + case FT_AGGREGATE_GROUP_BY_REDUCERS.SUM: + case FT_AGGREGATE_GROUP_BY_REDUCERS.MIN: + case FT_AGGREGATE_GROUP_BY_REDUCERS.MAX: + case FT_AGGREGATE_GROUP_BY_REDUCERS.AVG: + case FT_AGGREGATE_GROUP_BY_REDUCERS.STDDEV: + case FT_AGGREGATE_GROUP_BY_REDUCERS.TOLIST: + args.push('1', reducer.property); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.QUANTILE: + args.push('2', reducer.property, reducer.quantile.toString()); + break; + + case FT_AGGREGATE_GROUP_BY_REDUCERS.FIRST_VALUE: { + const length = args.push('', reducer.property) - 1; + if (reducer.BY) { + args.push('BY'); + if (typeof reducer.BY === 'string' || reducer.BY instanceof Buffer) { + args.push(reducer.BY); + } else { + args.push(reducer.BY.property); + if (reducer.BY.direction) { + args.push(reducer.BY.direction); + } + } + } + + args[length - 1] = (args.length - length).toString(); + break; + } -export interface AggregateReply { - total: number; - results: Array>; + case FT_AGGREGATE_GROUP_BY_REDUCERS.RANDOM_SAMPLE: + args.push('2', reducer.property, reducer.sampleSize.toString()); + break; + } + + if (reducer.AS) { + args.push('AS', reducer.AS); + } } -export function transformReply(rawReply: AggregateRawReply): AggregateReply { - const results: Array> = []; - for (let i = 1; i < rawReply.length; i++) { - results.push( - transformTuplesReply(rawReply[i] as Array) - ); +function pushSortByProperty(args: Array, sortBy: SortByProperty) { + if (typeof sortBy === 'string' || sortBy instanceof Buffer) { + args.push(sortBy); + } else { + args.push(sortBy.BY); + if (sortBy.DIRECTION) { + args.push(sortBy.DIRECTION); } - - return { - total: rawReply[0], - results - }; -} \ No newline at end of file + } +} diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts index bd60965e7db..9db3d945f97 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.spec.ts @@ -1,37 +1,47 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './AGGREGATE_WITHCURSOR'; -import { SchemaFieldTypes } from '.'; +import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; describe('AGGREGATE WITHCURSOR', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', '*'), - ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR'] - ); - }); + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*'), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*', { + COUNT: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'COUNT', '1'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('index', '*', { COUNT: 1 }), - ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'COUNT', '1'] - ); - }); + it('with MAXIDLE', () => { + assert.deepEqual( + AGGREGATE_WITHCURSOR.transformArguments('index', '*', { + MAXIDLE: 1 + }), + ['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'MAXIDLE', '1'] + ); }); + }); - testUtils.testWithClient('client.ft.aggregateWithCursor', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }); + testUtils.testWithClient('client.ft.aggregateWithCursor', async client => { + await client.ft.create('index', { + field: 'NUMERIC' + }); - assert.deepEqual( - await client.ft.aggregateWithCursor('index', '*'), - { - total: 0, - results: [], - cursor: 0 - } - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + await client.ft.aggregateWithCursor('index', '*'), + { + total: 0, + results: [], + cursor: 0 + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts index 63f6ee8f187..6591d4620f4 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts @@ -1,44 +1,73 @@ -import { - AggregateOptions, - AggregateRawReply, - AggregateReply, - transformArguments as transformAggregateArguments, - transformReply as transformAggregateReply -} from './AGGREGATE'; - -export { FIRST_KEY_INDEX, IS_READ_ONLY } from './AGGREGATE'; - -interface AggregateWithCursorOptions extends AggregateOptions { - COUNT?: number; -} +// import { +// AggregateOptions, +// AggregateRawReply, +// AggregateReply, +// transformArguments as transformAggregateArguments, +// transformReply as transformAggregateReply +// } from './AGGREGATE'; -export function transformArguments( - index: string, - query: string, - options?: AggregateWithCursorOptions -) { - const args = transformAggregateArguments(index, query, options); +// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './AGGREGATE'; - args.push('WITHCURSOR'); - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); - } +// interface AggregateWithCursorOptions extends AggregateOptions { +// COUNT?: number; +// } - return args; -} +// export function transformArguments( +// index: string, +// query: string, +// options?: AggregateWithCursorOptions +// ) { +// const args = transformAggregateArguments(index, query, options); -type AggregateWithCursorRawReply = [ - result: AggregateRawReply, - cursor: number -]; +// args.push('WITHCURSOR'); +// if (options?.COUNT) { +// args.push('COUNT', options.COUNT.toString()); +// } -interface AggregateWithCursorReply extends AggregateReply { - cursor: number; -} +// return args; +// } + +// type AggregateWithCursorRawReply = [ +// result: AggregateRawReply, +// cursor: number +// ]; + +// interface AggregateWithCursorReply extends AggregateReply { +// cursor: number; +// } + +// export function transformReply(reply: AggregateWithCursorRawReply): AggregateWithCursorReply { +// return { +// ...transformAggregateReply(reply[0]), +// cursor: reply[1] +// }; +// } + +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import AGGREGATE, { FtAggregateOptions } from './AGGREGATE'; -export function transformReply(reply: AggregateWithCursorRawReply): AggregateWithCursorReply { - return { - ...transformAggregateReply(reply[0]), - cursor: reply[1] - }; +export interface FtAggregateWithCursorOptions extends FtAggregateOptions { + COUNT?: number; + MAXIDLE?: number; } + +export default { + FIRST_KEY_INDEX: AGGREGATE.FIRST_KEY_INDEX, + IS_READ_ONLY: AGGREGATE.IS_READ_ONLY, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateWithCursorOptions) { + const args = AGGREGATE.transformArguments(index, query, options); + args.push('WITHCURSOR'); + + if (options?.COUNT !== undefined) { + args.push('COUNT', options.COUNT.toString()); + } + + if(options?.MAXIDLE !== undefined) { + args.push('MAXIDLE', options.MAXIDLE.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; + diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index ea63873be45..f6b66085f2d 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -1,6 +1,5 @@ import { RedisArgument, SimpleStringReply, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { PropertyName } from '.'; export const SCHEMA_FIELD_TYPE = { TEXT: 'TEXT', @@ -257,14 +256,16 @@ export const REDISEARCH_LANGUAGE = { export type RediSearchLanguage = typeof REDISEARCH_LANGUAGE[keyof typeof REDISEARCH_LANGUAGE]; +export type RediSearchProperty = `${'@' | '$.'}${string}`; + export interface CreateOptions { ON?: 'HASH' | 'JSON'; PREFIX?: RedisVariadicArgument; FILTER?: RedisArgument; LANGUAGE?: RediSearchLanguage; - LANGUAGE_FIELD?: PropertyName; + LANGUAGE_FIELD?: RediSearchProperty; SCORE?: number; - SCORE_FIELD?: PropertyName; + SCORE_FIELD?: RediSearchProperty; // PAYLOAD_FIELD?: string; MAXTEXTFIELDS?: boolean; TEMPORARY?: number; diff --git a/packages/search/lib/commands/SEARCH.spec.ts b/packages/search/lib/commands/SEARCH.spec.ts index d3d9bf9ae37..257dbb79515 100644 --- a/packages/search/lib/commands/SEARCH.spec.ts +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -1,300 +1,327 @@ import { strict as assert } from 'node:assert'; -import { RedisSearchLanguages, SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SEARCH'; +import SEARCH 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'] - ); - }); +describe('FT.SEARCH', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query'), + ['FT.SEARCH', 'index', 'query'] + ); + }); - it('with RETURN', () => { - assert.deepEqual( - transformArguments('index', 'query', { RETURN: 'return' }), - ['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return'] - ); - }); + it('with VERBATIM', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + VERBATIM: true + }), + ['FT.SEARCH', 'index', 'query', 'VERBATIM'] + ); + }); - describe('with SUMMARIZE', () => { - it('true', () => { - assert.deepEqual( - transformArguments('index', 'query', { SUMMARIZE: true }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE'] - ); - }); + it('with NOSTOPWORDS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + NOSTOPWORDS: true + }), + ['FT.SEARCH', 'index', 'query', 'NOSTOPWORDS'] + ); + }); - describe('with FIELDS', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FIELDS: ['@field'] - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '1', '@field'] - ); - }); + it('with INKEYS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INKEYS: 'key' + }), + ['FT.SEARCH', 'index', 'query', 'INKEYS', '1', 'key'] + ); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FIELDS: ['@1', '@2'] - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '2', '@1', '@2'] - ); - }); - }); + it('with INFIELDS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INFIELDS: 'field' + }), + ['FT.SEARCH', 'index', 'query', 'INFIELDS', '1', 'field'] + ); + }); - it('with FRAGS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - FRAGS: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FRAGS', '1'] - ); - }); + it('with RETURN', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + RETURN: 'return' + }), + ['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return'] + ); + }); - it('with LEN', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - LEN: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'LEN', '1'] - ); - }); + describe('with SUMMARIZE', () => { + it('true', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: true + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE'] + ); + }); - it('with SEPARATOR', () => { - assert.deepEqual( - transformArguments('index', 'query', { - SUMMARIZE: { - SEPARATOR: 'separator' - } - }), - ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'SEPARATOR', 'separator'] - ); - }); + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: '@field' + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '1', '@field'] + ); }); - describe('with HIGHLIGHT', () => { - it('true', () => { - assert.deepEqual( - transformArguments('index', 'query', { HIGHLIGHT: true }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT'] - ); - }); + it('Array', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FIELDS', '2', '@1', '@2'] + ); + }); + }); - describe('with FIELDS', () => { - it('string', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - FIELDS: ['@field'] - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '1', '@field'] - ); - }); + it('with FRAGS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + FRAGS: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'FRAGS', '1'] + ); + }); - it('Array', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - FIELDS: ['@1', '@2'] - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '2', '@1', '@2'] - ); - }); - }); + it('with LEN', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + LEN: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'LEN', '1'] + ); + }); - it('with TAGS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - HIGHLIGHT: { - TAGS: { - open: 'open', - close: 'close' - } - } - }), - ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'TAGS', 'open', 'close'] - ); - }); - }); + it('with SEPARATOR', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SUMMARIZE: { + SEPARATOR: 'separator' + } + }), + ['FT.SEARCH', 'index', 'query', 'SUMMARIZE', 'SEPARATOR', 'separator'] + ); + }); + }); - it('with SLOP', () => { - assert.deepEqual( - transformArguments('index', 'query', { SLOP: 1 }), - ['FT.SEARCH', 'index', 'query', 'SLOP', '1'] - ); - }); + describe('with HIGHLIGHT', () => { + it('true', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: true + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT'] + ); + }); - it('with INORDER', () => { - assert.deepEqual( - transformArguments('index', 'query', { INORDER: true }), - ['FT.SEARCH', 'index', 'query', 'INORDER'] - ); + describe('with FIELDS', () => { + it('string', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@field'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '1', '@field'] + ); }); - it('with LANGUAGE', () => { - assert.deepEqual( - transformArguments('index', 'query', { LANGUAGE: RedisSearchLanguages.ARABIC }), - ['FT.SEARCH', 'index', 'query', 'LANGUAGE', RedisSearchLanguages.ARABIC] - ); + it('Array', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + FIELDS: ['@1', '@2'] + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'FIELDS', '2', '@1', '@2'] + ); }); + }); - it('with EXPANDER', () => { - assert.deepEqual( - transformArguments('index', 'query', { EXPANDER: 'expender' }), - ['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender'] - ); - }); + it('with TAGS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + HIGHLIGHT: { + TAGS: { + open: 'open', + close: 'close' + } + } + }), + ['FT.SEARCH', 'index', 'query', 'HIGHLIGHT', 'TAGS', 'open', 'close'] + ); + }); + }); - it('with SCORER', () => { - assert.deepEqual( - transformArguments('index', 'query', { SCORER: 'scorer' }), - ['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer'] - ); - }); + it('with SLOP', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SLOP: 1 + }), + ['FT.SEARCH', 'index', 'query', 'SLOP', '1'] + ); + }); - it('with SORTBY', () => { - assert.deepEqual( - transformArguments('index', 'query', { SORTBY: '@by' }), - ['FT.SEARCH', 'index', 'query', 'SORTBY', '@by'] - ); - }); + it('with TIMEOUT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + TIMEOUT: 1 + }), + ['FT.SEARCH', 'index', 'query', 'TIMEOUT', '1'] + ); + }); - it('with LIMIT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - LIMIT: { - from: 0, - size: 1 - } - }), - ['FT.SEARCH', 'index', 'query', 'LIMIT', '0', '1'] - ); - }); + it('with INORDER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + INORDER: true + }), + ['FT.SEARCH', 'index', 'query', 'INORDER'] + ); + }); - it('with PARAMS', () => { - assert.deepEqual( - transformArguments('index', 'query', { - PARAMS: { - param: 'value' - } - }), - ['FT.SEARCH', 'index', 'query', 'PARAMS', '2', 'param', 'value'] - ); - }); + it('with LANGUAGE', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + LANGUAGE: 'Arabic' + }), + ['FT.SEARCH', 'index', 'query', 'LANGUAGE', 'Arabic'] + ); + }); - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - DIALECT: 1 - }), - ['FT.SEARCH', 'index', 'query', 'DIALECT', '1'] - ); - }); + it('with EXPANDER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + EXPANDER: 'expender' + }), + ['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender'] + ); + }); - it('with TIMEOUT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - TIMEOUT: 5 - }), - ['FT.SEARCH', 'index', 'query', 'TIMEOUT', '5'] - ); - }); + it('with SCORER', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SCORER: 'scorer' + }), + ['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer'] + ); }); - describe('client.ft.search', () => { - testUtils.testWithClient('without optional options', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }), - client.hSet('1', 'field', '1') - ]); + it('with SORTBY', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + SORTBY: '@by' + }), + ['FT.SEARCH', 'index', 'query', 'SORTBY', '@by'] + ); + }); - 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); + it('with LIMIT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + LIMIT: { + from: 0, + size: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'LIMIT', '0', '1'] + ); + }); - testUtils.testWithClient('RETURN []', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.NUMERIC - }), - client.hSet('1', 'field', '1'), - client.hSet('2', 'field', '2') - ]); + it('with PARAMS', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + PARAMS: { + string: 'string', + buffer: Buffer.from('buffer'), + number: 1 + } + }), + ['FT.SEARCH', 'index', 'query', 'PARAMS', '6', 'string', 'string', 'buffer', Buffer.from('buffer'), 'number', '1'] + ); + }); - assert.deepEqual( - await client.ft.search('index', '*', { - RETURN: [] - }), - { - total: 2, - documents: [{ - id: '1', - value: Object.create(null) - }, { - id: '2', - value: Object.create(null) - }] - } - ); - }, GLOBAL.SERVERS.OPEN); + it('with DIALECT', () => { + assert.deepEqual( + SEARCH.transformArguments('index', 'query', { + DIALECT: 1 + }), + ['FT.SEARCH', 'index', 'query', 'DIALECT', '1'] + ); }); + }); + + describe('client.ft.search', () => { + testUtils.testWithClient('without optional options', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + 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); + + testUtils.testWithClient('RETURN []', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + client.hSet('1', 'field', '1'), + client.hSet('2', 'field', '2') + ]); + + assert.deepEqual( + await client.ft.search('index', '*', { + RETURN: [] + }), + { + total: 2, + documents: [{ + id: '1', + value: Object.create(null) + }, { + id: '2', + value: Object.create(null) + }] + } + ); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SEARCH.ts b/packages/search/lib/commands/SEARCH.ts index ff7ab7e201d..91946c8becd 100644 --- a/packages/search/lib/commands/SEARCH.ts +++ b/packages/search/lib/commands/SEARCH.ts @@ -1,109 +1,162 @@ -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -import { pushSearchOptions, RedisSearchLanguages, Params, PropertyName, SortByProperty, SearchReply } from '.'; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export interface SearchOptions { - 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?: SortByProperty; - // MSORTBY?: SortByProperty | Array; - LIMIT?: { - from: number | string; - size: number | string; - }; - PARAMS?: Params; - DIALECT?: number; - TIMEOUT?: number; -} +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RediSearchProperty, RediSearchLanguage } from './CREATE'; -export function transformArguments( - index: string, - query: string, - options?: SearchOptions -): RedisCommandArguments { - return pushSearchOptions( - ['FT.SEARCH', index, query], - options - ); -} +export type FtSearchParams = Record; -export type SearchRawReply = Array; +export function pushParamsArgument(args: Array, params?: FtSearchParams) { + if (params) { + const length = args.push('PARAMS', ''); + for (const key in params) { + if (!Object.hasOwn(params, key)) continue; -export function transformReply(reply: SearchRawReply, withoutDocuments: boolean): SearchReply { - const documents = []; - let i = 1; - while (i < reply.length) { - documents.push({ - id: reply[i++], - value: withoutDocuments ? Object.create(null) : documentValue(reply[i++]) - }); + const value = params[key]; + args.push( + key, + typeof value === 'number' ? value.toString() : value + ); } - return { - total: reply[0], - documents + args[length - 1] = (args.length - length).toString(); + } +} + +export interface FtSearchOptions { + VERBATIM?: boolean; + NOSTOPWORDS?: boolean; + INKEYS?: RedisVariadicArgument; + INFIELDS?: RedisVariadicArgument; + RETURN?: RedisVariadicArgument; + SUMMARIZE?: boolean | { + FIELDS?: RediSearchProperty | Array; + FRAGS?: number; + LEN?: number; + SEPARATOR?: RedisArgument; + }; + HIGHLIGHT?: boolean | { + FIELDS?: RediSearchProperty | Array; + TAGS?: { + open: RedisArgument; + close: RedisArgument; }; + }; + SLOP?: number; + TIMEOUT?: number; + INORDER?: boolean; + LANGUAGE?: RediSearchLanguage; + EXPANDER?: RedisArgument; + SCORER?: RedisArgument; + SORTBY?: RedisArgument | { + BY: RediSearchProperty; + DIRECTION?: 'ASC' | 'DESC'; + }; + LIMIT?: { + from: number | RedisArgument; + size: number | RedisArgument; + }; + PARAMS?: FtSearchParams; + DIALECT?: number; } -function documentValue(tuples: any) { - const message = Object.create(null); - - let i = 0; - while (i < tuples.length) { - const key = tuples[i++], - value = tuples[i++]; - if (key === '$') { // might be a JSON reply - try { - Object.assign(message, JSON.parse(value)); - continue; - } catch { - // set as a regular property if not a valid JSON - } +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSearchOptions) { + const args = ['FT.SEARCH', index, query]; + + if (options?.VERBATIM) { + args.push('VERBATIM'); + } + + if (options?.NOSTOPWORDS) { + args.push('NOSTOPWORDS'); + } + + pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); + pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); + pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); + + if (options?.SUMMARIZE) { + args.push('SUMMARIZE'); + + if (typeof options.SUMMARIZE === 'object') { + pushOptionalVariadicArgument(args, 'FIELDS', options.SUMMARIZE.FIELDS); + + if (options.SUMMARIZE.FRAGS !== undefined) { + args.push('FRAGS', options.SUMMARIZE.FRAGS.toString()); } - message[key] = value; + if (options.SUMMARIZE.LEN !== undefined) { + args.push('LEN', options.SUMMARIZE.LEN.toString()); + } + + if (options.SUMMARIZE.SEPARATOR !== undefined) { + args.push('SEPARATOR', options.SUMMARIZE.SEPARATOR); + } + } } - return message; -} + if (options?.HIGHLIGHT) { + args.push('HIGHLIGHT'); + + if (typeof options.HIGHLIGHT === 'object') { + pushOptionalVariadicArgument(args, 'FIELDS', options.HIGHLIGHT.FIELDS); + + if (options.HIGHLIGHT.TAGS) { + args.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close); + } + } + } + + if (options?.SLOP !== undefined) { + args.push('SLOP', options.SLOP.toString()); + } + + if (options?.TIMEOUT !== undefined) { + args.push('TIMEOUT', options.TIMEOUT.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?.SORTBY) { + args.push('SORTBY'); + + if (typeof options.SORTBY === 'string' || options.SORTBY instanceof Buffer) { + args.push(options.SORTBY); + } else { + args.push(options.SORTBY.BY); + + if (options.SORTBY.DIRECTION) { + args.push(options.SORTBY.DIRECTION); + } + } + } + + if (options?.LIMIT) { + args.push('LIMIT', options.LIMIT.from.toString(), options.LIMIT.size.toString()); + } + + pushParamsArgument(args, options?.PARAMS); + + if (options?.DIALECT !== undefined) { + args.push('DIALECT', options.DIALECT.toString()); + } + + return args; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts b/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts index da5a6feaba7..be998b9e63d 100644 --- a/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts +++ b/packages/search/lib/commands/SEARCH_NOCONTENT.spec.ts @@ -1,45 +1,34 @@ import { strict as assert } from 'assert'; -import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './SEARCH_NOCONTENT'; +import SEARCH_NOCONTENT from './SEARCH_NOCONTENT'; -describe('SEARCH_NOCONTENT', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', 'query'), - ['FT.SEARCH', 'index', 'query', 'NOCONTENT'] - ); - }); +describe('FT.SEARCH NOCONTENT', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SEARCH_NOCONTENT.transformArguments('index', 'query'), + ['FT.SEARCH', 'index', 'query', 'NOCONTENT'] + ); }); + }); - describe('transformReply', () => { - it('returns total and keys', () => { - assert.deepEqual(transformReply([3, '1', '2', '3']), { - total: 3, - documents: ['1', '2', '3'] - }) - }); - }); - - describe('client.ft.searchNoContent', () => { - testUtils.testWithClient('returns total and keys', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }), - client.hSet('1', 'field', 'field1'), - client.hSet('2', 'field', 'field2'), - client.hSet('3', 'field', 'field3') - ]); + describe('client.ft.searchNoContent', () => { + testUtils.testWithClient('returns total and keys', async client => { + await Promise.all([ + client.ft.create('index', { + field: 'TEXT' + }), + client.hSet('1', 'field', 'field1'), + client.hSet('2', 'field', 'field2') + ]); - assert.deepEqual( - await client.ft.searchNoContent('index', '*'), - { - total: 3, - documents: ['1','2','3'] - } - ); - }, GLOBAL.SERVERS.OPEN); - }); + assert.deepEqual( + await client.ft.searchNoContent('index', '*'), + { + total: 2, + documents: ['1', '2'] + } + ); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SEARCH_NOCONTENT.ts b/packages/search/lib/commands/SEARCH_NOCONTENT.ts index ab50ae2b9ff..28853091775 100644 --- a/packages/search/lib/commands/SEARCH_NOCONTENT.ts +++ b/packages/search/lib/commands/SEARCH_NOCONTENT.ts @@ -1,30 +1,13 @@ -import { RedisCommandArguments } from "@redis/client/dist/lib/commands"; -import { pushSearchOptions } from "."; -import { SearchOptions, SearchRawReply } from "./SEARCH"; - -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -export function transformArguments( - index: string, - query: string, - options?: SearchOptions -): RedisCommandArguments { - return pushSearchOptions( - ['FT.SEARCH', index, query, 'NOCONTENT'], - options - ); -} - -export interface SearchNoContentReply { - total: number; - documents: Array; -}; - -export function transformReply(reply: SearchRawReply): SearchNoContentReply { - return { - total: reply[0], - documents: reply.slice(1) - }; -} +import { Command } from '@redis/client/dist/lib/RESP/types'; +import SEARCH from './SEARCH'; + +export default { + FIRST_KEY_INDEX: SEARCH.FIRST_KEY_INDEX, + IS_READ_ONLY: SEARCH.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = SEARCH.transformArguments(...args); + redisArgs.push('NOCONTENT'); + return redisArgs; + }, + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 43831c90ac5..978ee1b2652 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -1,7 +1,7 @@ import _LIST from './_LIST'; import ALTER from './ALTER'; -// import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; -// import AGGREGATE from './AGGREGATE'; +import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; +import AGGREGATE from './AGGREGATE'; import ALIASADD from './ALIASADD'; import ALIASDEL from './ALIASDEL'; import ALIASUPDATE from './ALIASUPDATE'; @@ -19,7 +19,8 @@ import DROPINDEX from './DROPINDEX'; // import INFO from './INFO'; // import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; -// import SEARCH from './SEARCH'; +import SEARCH_NOCONTENT from './SEARCH_NOCONTENT'; +import SEARCH from './SEARCH'; import SPELLCHECK from './SPELLCHECK'; import SUGADD from './SUGADD'; import SUGDEL from './SUGDEL'; @@ -31,6 +32,7 @@ import SUGLEN from './SUGLEN'; import SYNDUMP from './SYNDUMP'; import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; +import { RedisArgument } from '@redis/client'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; // import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; // import { SearchOptions } from './SEARCH'; @@ -41,10 +43,10 @@ export default { _list: _LIST, ALTER, alter: ALTER, - // AGGREGATE_WITHCURSOR, - // aggregateWithCursor: AGGREGATE_WITHCURSOR, - // AGGREGATE, - // aggregate: AGGREGATE, + AGGREGATE_WITHCURSOR, + aggregateWithCursor: AGGREGATE_WITHCURSOR, + AGGREGATE, + aggregate: AGGREGATE, ALIASADD, aliasAdd: ALIASADD, ALIASDEL, @@ -79,8 +81,10 @@ export default { // profileSearch: PROFILESEARCH, // PROFILEAGGREGATE, // profileAggregate: PROFILEAGGREGATE, - // SEARCH, - // search: SEARCH, + SEARCH_NOCONTENT, + searchNoContent: SEARCH_NOCONTENT, + SEARCH, + search: SEARCH, SPELLCHECK, spellCheck: SPELLCHECK, SUGADD, @@ -104,539 +108,3 @@ export default { TAGVALS, tagVals: TAGVALS }; - -// export enum RedisSearchLanguages { -// ARABIC = 'Arabic', -// BASQUE = 'Basque', -// CATALANA = 'Catalan', -// DANISH = 'Danish', -// DUTCH = 'Dutch', -// ENGLISH = 'English', -// FINNISH = 'Finnish', -// FRENCH = 'French', -// GERMAN = 'German', -// GREEK = 'Greek', -// HUNGARIAN = 'Hungarian', -// INDONESAIN = 'Indonesian', -// IRISH = 'Irish', -// ITALIAN = 'Italian', -// LITHUANIAN = 'Lithuanian', -// NEPALI = 'Nepali', -// NORWEIGAN = 'Norwegian', -// PORTUGUESE = 'Portuguese', -// ROMANIAN = 'Romanian', -// RUSSIAN = 'Russian', -// SPANISH = 'Spanish', -// SWEDISH = 'Swedish', -// TAMIL = 'Tamil', -// TURKISH = 'Turkish', -// CHINESE = 'Chinese' -// } - -export type PropertyName = `${'@' | '$.'}${string}`; - -// export type SortByProperty = string | { -// BY: string; -// DIRECTION?: 'ASC' | 'DESC'; -// }; - -// export function pushSortByProperty(args: RedisCommandArguments, sortBy: SortByProperty): 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: SortByProperty | 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: CommandArguments, fn: (args: CommandArguments) => void) { -// const lengthIndex = args.push('') - 1; -// fn(args); -// args[lengthIndex] = (args.length - lengthIndex - 1).toString(); -// return args; -// } - -// export enum SchemaFieldTypes { -// TEXT = 'TEXT', -// NUMERIC = 'NUMERIC', -// GEO = 'GEO', -// TAG = 'TAG', -// VECTOR = 'VECTOR' -// } - -// type CreateSchemaField< -// T extends SchemaFieldTypes, -// E = Record -// > = T | ({ -// type: T; -// AS?: string; -// } & E); - -// type CreateSchemaCommonField< -// T extends SchemaFieldTypes, -// E = Record -// > = CreateSchemaField< -// T, -// ({ -// 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 = CreateSchemaCommonField; - -// type CreateSchemaNumericField = CreateSchemaCommonField; - -// type CreateSchemaGeoField = CreateSchemaCommonField; - -// type CreateSchemaTagField = CreateSchemaCommonField; - -// export enum VectorAlgorithms { -// FLAT = 'FLAT', -// HNSW = 'HNSW' -// } - -// type CreateSchemaVectorField< -// T extends VectorAlgorithms, -// A extends Record -// > = CreateSchemaField; - -// type CreateSchemaFlatVectorField = CreateSchemaVectorField; - -// type CreateSchemaHNSWVectorField = CreateSchemaVectorField; - -// export interface RediSearchSchema { -// [field: string]: -// CreateSchemaTextField | -// CreateSchemaNumericField | -// CreateSchemaGeoField | -// CreateSchemaTagField | -// CreateSchemaFlatVectorField | -// CreateSchemaHNSWVectorField; -// } - -// export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { -// 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 SchemaFieldTypes.TEXT: -// if (fieldOptions.NOSTEM) { -// args.push('NOSTEM'); -// } - -// if (fieldOptions.WEIGHT) { -// args.push('WEIGHT', fieldOptions.WEIGHT.toString()); -// } - -// if (fieldOptions.PHONETIC) { -// args.push('PHONETIC', fieldOptions.PHONETIC); -// } - -// if (fieldOptions.WITHSUFFIXTRIE) { -// args.push('WITHSUFFIXTRIE'); -// } - -// break; - -// // case SchemaFieldTypes.NUMERIC: -// // case SchemaFieldTypes.GEO: -// // break; - -// case SchemaFieldTypes.TAG: -// if (fieldOptions.SEPARATOR) { -// args.push('SEPARATOR', fieldOptions.SEPARATOR); -// } - -// if (fieldOptions.CASESENSITIVE) { -// args.push('CASESENSITIVE'); -// } - -// if (fieldOptions.WITHSUFFIXTRIE) { -// args.push('WITHSUFFIXTRIE'); -// } - -// break; - -// case SchemaFieldTypes.VECTOR: -// args.push(fieldOptions.ALGORITHM); - -// pushArgumentsWithLength(args, () => { -// args.push( -// 'TYPE', fieldOptions.TYPE, -// 'DIM', fieldOptions.DIM.toString(), -// 'DISTANCE_METRIC', fieldOptions.DISTANCE_METRIC -// ); - -// if (fieldOptions.INITIAL_CAP) { -// args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString()); -// } - -// switch (fieldOptions.ALGORITHM) { -// case VectorAlgorithms.FLAT: -// if (fieldOptions.BLOCK_SIZE) { -// args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString()); -// } - -// break; - -// case VectorAlgorithms.HNSW: -// if (fieldOptions.M) { -// args.push('M', fieldOptions.M.toString()); -// } - -// if (fieldOptions.EF_CONSTRUCTION) { -// args.push('EF_CONSTRUCTION', fieldOptions.EF_CONSTRUCTION.toString()); -// } - -// if (fieldOptions.EF_RUNTIME) { -// args.push('EF_RUNTIME', fieldOptions.EF_RUNTIME.toString()); -// } - -// break; -// } -// }); - -// continue; // vector fields do not contain SORTABLE and NOINDEX options -// } - -// if (fieldOptions.SORTABLE) { -// args.push('SORTABLE'); - -// if (fieldOptions.SORTABLE === 'UNF') { -// args.push('UNF'); -// } -// } - -// if (fieldOptions.NOINDEX) { -// args.push('NOINDEX'); -// } -// } -// } - -// export type Params = Record; - -// export function pushParamsArgs( -// args: RedisCommandArguments, -// params?: Params -// ): RedisCommandArguments { -// if (params) { -// const enrties = Object.entries(params); -// args.push('PARAMS', (enrties.length * 2).toString()); -// for (const [key, value] of enrties) { -// args.push(key, typeof value === 'number' ? value.toString() : value); -// } -// } - -// return args; -// } - -// export function pushSearchOptions( -// args: RedisCommandArguments, -// options?: SearchOptions -// ): RedisCommandArguments { -// if (options?.VERBATIM) { -// args.push('VERBATIM'); -// } - -// if (options?.NOSTOPWORDS) { -// args.push('NOSTOPWORDS'); -// } - -// // if (options?.WITHSCORES) { -// // args.push('WITHSCORES'); -// // } - -// // if (options?.WITHPAYLOADS) { -// // args.push('WITHPAYLOADS'); -// // } - -// pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS); -// pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS); -// pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN); - -// if (options?.SUMMARIZE) { -// args.push('SUMMARIZE'); - -// if (typeof options.SUMMARIZE === 'object') { -// if (options.SUMMARIZE.FIELDS) { -// args.push('FIELDS'); -// pushVariadicArgument(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'); -// pushVariadicArgument(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'); -// pushSortByProperty(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() -// ); -// } - -// if (options?.PARAMS) { -// pushParamsArgs(args, options.PARAMS); -// } - -// if (options?.DIALECT) { -// args.push('DIALECT', options.DIALECT.toString()); -// } - -// if (options?.RETURN?.length === 0) { -// args.preserve = true; -// } - -// if (options?.TIMEOUT !== undefined) { -// args.push('TIMEOUT', options.TIMEOUT.toString()); -// } - -// return args; -// } - -// interface SearchDocumentValue { -// [key: string]: string | number | null | Array | SearchDocumentValue; -// } - -// export interface SearchReply { -// total: number; -// documents: Array<{ -// id: string; -// value: SearchDocumentValue; -// }>; -// } - -// export interface ProfileOptions { -// LIMITED?: true; -// } - -// export type ProfileRawReply = [ -// results: T, -// profile: [ -// _: string, -// TotalProfileTime: string, -// _: string, -// ParsingTime: string, -// _: string, -// PipelineCreationTime: string, -// _: string, -// IteratorsProfile: Array -// ] -// ]; - -// export interface ProfileReply { -// results: SearchReply | AGGREGATE.AggregateReply; -// profile: ProfileData; -// } - -// interface ChildIterator { -// type?: string, -// counter?: number, -// term?: string, -// size?: number, -// time?: string, -// childIterators?: Array -// } - -// interface IteratorsProfile { -// type?: string, -// counter?: number, -// queryType?: string, -// time?: string, -// childIterators?: Array -// } - -// interface ProfileData { -// totalProfileTime: string, -// parsingTime: string, -// pipelineCreationTime: string, -// iteratorsProfile: IteratorsProfile -// } - -// export function transformProfile(reply: Array): ProfileData { -// return { -// totalProfileTime: reply[0][1], -// parsingTime: reply[1][1], -// pipelineCreationTime: reply[2][1], -// iteratorsProfile: transformIterators(reply[3][1]) -// }; -// } - -// function transformIterators(IteratorsProfile: Array): IteratorsProfile { -// var res: IteratorsProfile = {}; -// for (let i = 0; i < IteratorsProfile.length; i += 2) { -// const value = IteratorsProfile[i + 1]; -// switch (IteratorsProfile[i]) { -// case 'Type': -// res.type = value; -// break; -// case 'Counter': -// res.counter = value; -// break; -// case 'Time': -// res.time = value; -// break; -// case 'Query type': -// res.queryType = value; -// break; -// case 'Child iterators': -// res.childIterators = value.map(transformChildIterators); -// break; -// } -// } - -// return res; -// } - -// function transformChildIterators(IteratorsProfile: Array): ChildIterator { -// var res: ChildIterator = {}; -// for (let i = 1; i < IteratorsProfile.length; i += 2) { -// const value = IteratorsProfile[i + 1]; -// switch (IteratorsProfile[i]) { -// case 'Type': -// res.type = value; -// break; -// case 'Counter': -// res.counter = value; -// break; -// case 'Time': -// res.time = value; -// break; -// case 'Size': -// res.size = value; -// break; -// case 'Term': -// res.term = value; -// break; -// case 'Child iterators': -// res.childIterators = value.map(transformChildIterators); -// break; -// } -// } - -// return res; -// } diff --git a/packages/search/package.json b/packages/search/package.json index ede33a6d839..614ce51b44f 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/packages/test-utils/lib/dockers.ts b/packages/test-utils/lib/dockers.ts index c2d76838945..d282005e110 100644 --- a/packages/test-utils/lib/dockers.ts +++ b/packages/test-utils/lib/dockers.ts @@ -46,7 +46,7 @@ export interface RedisServerDocker { dockerId: string; } -// extrea ".." cause it'll be in `./dist` +// extra ".." cause it'll be in `./dist` const DOCKER_FODLER_PATH = path.join(__dirname, '../../docker'); async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array): Promise { diff --git a/packages/time-series/lib/index.ts b/packages/time-series/lib/index.ts index 9372621b009..8a9efc8b374 100644 --- a/packages/time-series/lib/index.ts +++ b/packages/time-series/lib/index.ts @@ -1,11 +1,7 @@ -export { default } from './commands'; - export { - TIME_SERIES_ENCODING, - TimeSeriesEncoding, - TIME_SERIES_DUPLICATE_POLICIES, - TimeSeriesDuplicatePolicies + default, + TIME_SERIES_ENCODING, TimeSeriesEncoding, + TIME_SERIES_DUPLICATE_POLICIES, TimeSeriesDuplicatePolicies } from './commands'; - export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE'; export { TIME_SERIES_BUCKET_TIMESTAMP, TimeSeriesBucketTimestamp } from './commands/RANGE'; diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 1ffa3bd1038..f19c69a64de 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -9,7 +9,7 @@ "!dist/tsconfig.tsbuildinfo" ], "scripts": { - "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" + "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { "@redis/client": "*" diff --git a/tsconfig.base.json b/tsconfig.base.json index cb4c5026393..3bec460a0dd 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,12 +1,18 @@ { - "extends": "@tsconfig/node18/tsconfig.json", "compilerOptions": { + "lib": ["ES2023"], + "module": "ES2022", + "moduleResolution": "Node", + "target": "ES2022", + + "strict": true, + "forceConsistentCasingInFileNames": true, + "noUnusedLocals": true, + "esModuleInterop": true, + "skipLibCheck": true, + "composite": true, "declaration": true, "allowJs": true - }, - "ts-node": { - "files": true, - "transpileOnly": true } } From 98970fab2e42ebcbfacad6b28a87192e9abbddbb Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 6 Nov 2023 14:06:54 -0500 Subject: [PATCH 243/325] FT.CURSOR READ --- docs/v4-to-v5.md | 1 + .../lib/commands/AGGREGATE_WITHCURSOR.ts | 45 ------------ .../search/lib/commands/CURSOR_READ.spec.ts | 73 +++++++++---------- packages/search/lib/commands/CURSOR_READ.ts | 37 ++++------ packages/search/lib/commands/index.ts | 6 +- 5 files changed, 54 insertions(+), 108 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 2c8d153b089..4841ab5569e 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -207,6 +207,7 @@ await cluster.multi() ### Search - `FT.SUGDEL`: [^boolean-to-number] +- `FT.CURSOR READ`: `cursor` type changed from `number` to `string` (in and out) to avoid issues when the number is bigger than `Number.MAX_SAFE_INTEGER`. See [here](https://github.com/redis/node-redis/issues/2561). ### Time Series diff --git a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts index 6591d4620f4..dae5c09b2cf 100644 --- a/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts +++ b/packages/search/lib/commands/AGGREGATE_WITHCURSOR.ts @@ -1,48 +1,3 @@ -// import { -// AggregateOptions, -// AggregateRawReply, -// AggregateReply, -// transformArguments as transformAggregateArguments, -// transformReply as transformAggregateReply -// } from './AGGREGATE'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './AGGREGATE'; - -// interface AggregateWithCursorOptions extends AggregateOptions { -// COUNT?: number; -// } - -// export function transformArguments( -// index: string, -// query: string, -// options?: AggregateWithCursorOptions -// ) { -// const args = transformAggregateArguments(index, query, options); - -// args.push('WITHCURSOR'); -// if (options?.COUNT) { -// args.push('COUNT', options.COUNT.toString()); -// } - -// return args; -// } - -// type AggregateWithCursorRawReply = [ -// result: AggregateRawReply, -// cursor: number -// ]; - -// interface AggregateWithCursorReply extends AggregateReply { -// cursor: number; -// } - -// export function transformReply(reply: AggregateWithCursorRawReply): AggregateWithCursorReply { -// return { -// ...transformAggregateReply(reply[0]), -// cursor: reply[1] -// }; -// } - import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; import AGGREGATE, { FtAggregateOptions } from './AGGREGATE'; diff --git a/packages/search/lib/commands/CURSOR_READ.spec.ts b/packages/search/lib/commands/CURSOR_READ.spec.ts index e8ef2c30912..237d234786e 100644 --- a/packages/search/lib/commands/CURSOR_READ.spec.ts +++ b/packages/search/lib/commands/CURSOR_READ.spec.ts @@ -1,45 +1,44 @@ import { strict as assert } from 'node:assert'; -import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CURSOR_READ'; +import CURSOR_READ from './CURSOR_READ'; -describe('CURSOR READ', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', 0), - ['FT.CURSOR', 'READ', 'index', '0'] - ); - }); +describe('FT.CURSOR READ', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + CURSOR_READ.transformArguments('index', '0'), + ['FT.CURSOR', 'READ', 'index', '0'] + ); + }); - it('with COUNT', () => { - assert.deepEqual( - transformArguments('index', 0, { COUNT: 1 }), - ['FT.CURSOR', 'READ', 'index', '0', 'COUNT', '1'] - ); - }); + it('with COUNT', () => { + assert.deepEqual( + CURSOR_READ.transformArguments('index', '0', { + COUNT: 1 + }), + ['FT.CURSOR', 'READ', 'index', '0', 'COUNT', '1'] + ); }); + }); - testUtils.testWithClient('client.ft.cursorRead', async client => { - const [, , { cursor }] = await Promise.all([ - client.ft.create('idx', { - field: { - type: SchemaFieldTypes.TEXT - } - }), - client.hSet('key', 'field', 'value'), - client.ft.aggregateWithCursor('idx', '*', { - COUNT: 1 - }) - ]); + testUtils.testWithClient('client.ft.cursorRead', async client => { + const [, , { cursor }] = await Promise.all([ + client.ft.create('idx', { + field: 'TEXT' + }), + client.hSet('key', 'field', 'value'), + client.ft.aggregateWithCursor('idx', '*', { + COUNT: 1 + }) + ]); - assert.deepEqual( - await client.ft.cursorRead('idx', cursor), - { - total: 0, - results: [], - cursor: 0 - } - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual( + await client.ft.cursorRead('idx', cursor), + { + total: 0, + results: [], + cursor: '0' + } + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/CURSOR_READ.ts b/packages/search/lib/commands/CURSOR_READ.ts index 35cf1bc4f06..1c647303f97 100644 --- a/packages/search/lib/commands/CURSOR_READ.ts +++ b/packages/search/lib/commands/CURSOR_READ.ts @@ -1,30 +1,21 @@ -import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; -export const FIRST_KEY_INDEX = 1; - -export const IS_READ_ONLY = true; - -interface CursorReadOptions { - COUNT?: number; +export interface FtCursorReadOptions { + COUNT?: number; } -export function transformArguments( - index: RedisCommandArgument, - cursor: number, - options?: CursorReadOptions -): RedisCommandArguments { - const args = [ - 'FT.CURSOR', - 'READ', - index, - cursor.toString() - ]; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, cursor: RedisArgument, options?: FtCursorReadOptions) { + const args = ['FT.CURSOR', 'READ', index, cursor]; - if (options?.COUNT) { - args.push('COUNT', options.COUNT.toString()); + if (options?.COUNT !== undefined) { + args.push('COUNT', options.COUNT.toString()); } return args; -} - -export { transformReply } from './AGGREGATE_WITHCURSOR'; + }, + transformReply: AGGREGATE_WITHCURSOR.transformReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 978ee1b2652..af51fc1bbc2 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -9,7 +9,7 @@ import CONFIG_GET from './CONFIG_GET'; import CONFIG_SET from './CONFIG_SET'; import CREATE from './CREATE'; import CURSOR_DEL from './CURSOR_DEL'; -// import CURSOR_READ from './CURSOR_READ'; +import CURSOR_READ from './CURSOR_READ'; import DICTADD from './DICTADD'; import DICTDEL from './DICTDEL'; import DICTDUMP from './DICTDUMP'; @@ -61,8 +61,8 @@ export default { create: CREATE, CURSOR_DEL, cursorDel: CURSOR_DEL, - // CURSOR_READ, - // cursorRead: CURSOR_READ, + CURSOR_READ, + cursorRead: CURSOR_READ, DICTADD, dictAdd: DICTADD, DICTDEL, From a5a4cb45ea08d1e90e243ae377b35b22d0fc541b Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 11:12:41 -0500 Subject: [PATCH 244/325] wip --- docs/v4-to-v5.md | 5 +- .../bloom/lib/commands/bloom/INFO.spec.ts | 44 +++++---- packages/bloom/lib/commands/bloom/INFO.ts | 68 +++---------- packages/bloom/lib/commands/bloom/index.ts | 6 +- .../bloom/lib/commands/cuckoo/INFO.spec.ts | 50 +++++----- packages/bloom/lib/commands/cuckoo/INFO.ts | 97 ++++++++++--------- packages/bloom/lib/commands/cuckoo/index.ts | 6 +- .../bloom/lib/commands/t-digest/INFO.spec.ts | 46 ++++----- packages/bloom/lib/commands/t-digest/INFO.ts | 94 +++++++++--------- packages/bloom/lib/commands/t-digest/index.ts | 6 +- .../client/lib/commands/CLUSTER_INFO.spec.ts | 4 +- packages/client/lib/commands/INFO.spec.ts | 36 ++++--- packages/client/lib/commands/KEYS.spec.ts | 7 +- packages/client/lib/commands/SCAN.spec.ts | 7 +- packages/client/lib/commands/WAIT.spec.ts | 7 +- 15 files changed, 222 insertions(+), 261 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 4841ab5569e..83dde28c7c7 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -134,7 +134,8 @@ await cluster.multi() - `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants] - `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants] - `CLIENT TRACKINGINFO`: `flags` in RESP2 - `Set` -> `Array` (to match RESP3 default type mapping) -- `CLUSETER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] +- `CLUSTER INFO`: +- `CLUSTER SETSLOT`: `ClusterSlotStates` -> `CLUSTER_SLOT_STATES` [^enum-to-constants] - `CLUSTER RESET`: the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants], the second argument is `{ mode: string; }` instead of `string` [^future-proofing] - `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys] @@ -145,7 +146,7 @@ await cluster.multi() - `HEXISTS`: `boolean` -> `number` [^boolean-to-number] - `HRANDFIELD_COUNT_WITHVALUES`: `Record` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates). - `HSETNX`: `boolean` -> `number` [^boolean-to-number] - +- `INFO`: - `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>` diff --git a/packages/bloom/lib/commands/bloom/INFO.spec.ts b/packages/bloom/lib/commands/bloom/INFO.spec.ts index 77b6a589ba4..9a8cb8bdf12 100644 --- a/packages/bloom/lib/commands/bloom/INFO.spec.ts +++ b/packages/bloom/lib/commands/bloom/INFO.spec.ts @@ -1,24 +1,26 @@ -// import { strict as assert } from 'node:assert'; -// import testUtils, { GLOBAL } from '../../test-utils'; -// import { transformArguments } from './INFO'; +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import INFO from './INFO'; -// describe('BF INFO', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('bloom'), -// ['BF.INFO', 'bloom'] -// ); -// }); +describe('BF.INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + INFO.transformArguments('bloom'), + ['BF.INFO', 'bloom'] + ); + }); -// testUtils.testWithClient('client.bf.info', async client => { -// await client.bf.reserve('key', 0.01, 100); + testUtils.testWithClient('client.bf.info', async client => { + const [, reply] = await Promise.all([ + client.bf.reserve('key', 0.01, 100), + client.bf.info('key') + ]); -// const info = await client.bf.info('key'); -// assert.equal(typeof info, 'object'); -// assert.equal(info.capacity, 100); -// assert.equal(typeof info.size, 'number'); -// assert.equal(typeof info.numberOfFilters, 'number'); -// assert.equal(typeof info.numberOfInsertedItems, 'number'); -// assert.equal(typeof info.expansionRate, 'number'); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(typeof reply, 'object'); + assert.equal(reply.capacity, 100); + assert.equal(typeof reply.size, 'number'); + assert.equal(typeof reply.numberOfFilters, 'number'); + assert.equal(typeof reply.numberOfInsertedItems, 'number'); + assert.equal(typeof reply.expansionRate, 'number'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/bloom/INFO.ts b/packages/bloom/lib/commands/bloom/INFO.ts index 7954053f0f5..d5055b1c03f 100644 --- a/packages/bloom/lib/commands/bloom/INFO.ts +++ b/packages/bloom/lib/commands/bloom/INFO.ts @@ -1,57 +1,11 @@ -// // export type InfoRawReply = [ -// // _: string, -// // capacity: number, -// // _: string, -// // size: number, -// // _: string, -// // numberOfFilters: number, -// // _: string, -// // numberOfInsertedItems: number, -// // _: string, -// // expansionRate: number, -// // ]; - -// // export interface InfoReply { -// // capacity: number; -// // size: number; -// // numberOfFilters: number; -// // numberOfInsertedItems: number; -// // expansionRate: number; -// // } - -// // export function transformReply(reply: InfoRawReply): InfoReply { -// // return { -// // capacity: reply[1], -// // size: reply[3], -// // numberOfFilters: reply[5], -// // numberOfInsertedItems: reply[7], -// // expansionRate: reply[9] -// // }; -// // } - -// import { RedisArgument, Command, TuplesToMapReply, BlobStringReply, NumberReply } from '@redis/client/dist/lib/RESP/types'; -// import { transformBooleanArrayReply } from '@redis/client/dist/lib/commands/generic-transformers'; - -// export type BfInfoReply = TuplesToMapReply<[ -// [BlobStringReply<'Capacity'>, NumberReply], -// [BlobStringReply<'Size'>, NumberReply], -// [BlobStringReply<'Number of filters'>, NumberReply], - - -// ]>; - -// export default { -// FIRST_KEY_INDEX: 1, -// IS_READ_ONLY: true, -// transformArguments(key: RedisArgument) { -// return ['BF.INFO', key]; -// }, -// transformReply: { -// 2: () => { - -// }, -// 3: () => { - -// } -// } -// } as const satisfies Command; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['BF.INFO', key]; + }, + // TODO + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/bloom/index.ts b/packages/bloom/lib/commands/bloom/index.ts index 7483467d867..e61f4709a4f 100644 --- a/packages/bloom/lib/commands/bloom/index.ts +++ b/packages/bloom/lib/commands/bloom/index.ts @@ -2,7 +2,7 @@ import type { RedisCommands } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import CARD from './CARD'; import EXISTS from './EXISTS'; -// import INFO from './INFO'; +import INFO from './INFO'; import INSERT from './INSERT'; import LOADCHUNK from './LOADCHUNK'; import MADD from './MADD'; @@ -17,8 +17,8 @@ export default { card: CARD, EXISTS, exists: EXISTS, - // INFO, - // info: INFO, + INFO, + info: INFO, INSERT, insert: INSERT, LOADCHUNK, diff --git a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts index e92e32f1251..e4276e941b9 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.spec.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.spec.ts @@ -1,27 +1,29 @@ -// import { strict as assert } from 'node:assert'; -// import testUtils, { GLOBAL } from '../../test-utils'; -// import { transformArguments } from './INFO'; +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import INFO from './INFO'; -// describe('CF INFO', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('cuckoo'), -// ['CF.INFO', 'cuckoo'] -// ); -// }); +describe('CF.INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + INFO.transformArguments('cuckoo'), + ['CF.INFO', 'cuckoo'] + ); + }); -// testUtils.testWithClient('client.cf.info', async client => { -// await client.cf.reserve('key', 4); + testUtils.testWithClient('client.cf.info', async client => { + const [, reply] = await Promise.all([ + client.cf.reserve('key', 4), + client.cf.info('key') + ]); -// const info = await client.cf.info('key'); -// assert.equal(typeof info, 'object'); -// assert.equal(typeof info.size, 'number'); -// assert.equal(typeof info.numberOfBuckets, 'number'); -// assert.equal(typeof info.numberOfFilters, 'number'); -// assert.equal(typeof info.numberOfInsertedItems, 'number'); -// assert.equal(typeof info.numberOfDeletedItems, 'number'); -// assert.equal(typeof info.bucketSize, 'number'); -// assert.equal(typeof info.expansionRate, 'number'); -// assert.equal(typeof info.maxIteration, 'number'); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert.equal(typeof reply, 'object'); + assert.equal(typeof reply.size, 'number'); + assert.equal(typeof reply.numberOfBuckets, 'number'); + assert.equal(typeof reply.numberOfFilters, 'number'); + assert.equal(typeof reply.numberOfInsertedItems, 'number'); + assert.equal(typeof reply.numberOfDeletedItems, 'number'); + assert.equal(typeof reply.bucketSize, 'number'); + assert.equal(typeof reply.expansionRate, 'number'); + assert.equal(typeof reply.maxIteration, 'number'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/cuckoo/INFO.ts b/packages/bloom/lib/commands/cuckoo/INFO.ts index be77430ae95..f7a789712d8 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.ts @@ -1,50 +1,53 @@ -// export const FIRST_KEY_INDEX = 1; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -// export const IS_READ_ONLY = true; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['CF.INFO', key]; + }, + // TODO + // export type InfoRawReply = [ + // _: string, + // size: number, + // _: string, + // numberOfBuckets: number, + // _: string, + // numberOfFilters: number, + // _: string, + // numberOfInsertedItems: number, + // _: string, + // numberOfDeletedItems: number, + // _: string, + // bucketSize: number, + // _: string, + // expansionRate: number, + // _: string, + // maxIteration: number + // ]; -// export function transformArguments(key: string): Array { -// return ['CF.INFO', key]; -// } + // export interface InfoReply { + // size: number; + // numberOfBuckets: number; + // numberOfFilters: number; + // numberOfInsertedItems: number; + // numberOfDeletedItems: number; + // bucketSize: number; + // expansionRate: number; + // maxIteration: number; + // } -// export type InfoRawReply = [ -// _: string, -// size: number, -// _: string, -// numberOfBuckets: number, -// _: string, -// numberOfFilters: number, -// _: string, -// numberOfInsertedItems: number, -// _: string, -// numberOfDeletedItems: number, -// _: string, -// bucketSize: number, -// _: string, -// expansionRate: number, -// _: string, -// maxIteration: number -// ]; - -// export interface InfoReply { -// size: number; -// numberOfBuckets: number; -// numberOfFilters: number; -// numberOfInsertedItems: number; -// numberOfDeletedItems: number; -// bucketSize: number; -// expansionRate: number; -// maxIteration: number; -// } - -// export function transformReply(reply: InfoRawReply): InfoReply { -// return { -// size: reply[1], -// numberOfBuckets: reply[3], -// numberOfFilters: reply[5], -// numberOfInsertedItems: reply[7], -// numberOfDeletedItems: reply[9], -// bucketSize: reply[11], -// expansionRate: reply[13], -// maxIteration: reply[15] -// }; -// } + // export function transformReply(reply: InfoRawReply): InfoReply { + // return { + // size: reply[1], + // numberOfBuckets: reply[3], + // numberOfFilters: reply[5], + // numberOfInsertedItems: reply[7], + // numberOfDeletedItems: reply[9], + // bucketSize: reply[11], + // expansionRate: reply[13], + // maxIteration: reply[15] + // }; + // } + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/index.ts b/packages/bloom/lib/commands/cuckoo/index.ts index f8eaed93059..62c63fe8d19 100644 --- a/packages/bloom/lib/commands/cuckoo/index.ts +++ b/packages/bloom/lib/commands/cuckoo/index.ts @@ -4,7 +4,7 @@ import ADDNX from './ADDNX'; import COUNT from './COUNT'; import DEL from './DEL'; import EXISTS from './EXISTS'; -// import INFO from './INFO'; +import INFO from './INFO'; import INSERT from './INSERT'; import INSERTNX from './INSERTNX'; import LOADCHUNK from './LOADCHUNK'; @@ -22,8 +22,8 @@ export default { del: DEL, EXISTS, exists: EXISTS, - // INFO, - // info: INFO, + INFO, + info: INFO, INSERT, insert: INSERT, INSERTNX, diff --git a/packages/bloom/lib/commands/t-digest/INFO.spec.ts b/packages/bloom/lib/commands/t-digest/INFO.spec.ts index 7845c49804f..0d50406a3a1 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.spec.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.spec.ts @@ -1,25 +1,27 @@ -// import { strict as assert } from 'node:assert'; -// import testUtils, { GLOBAL } from '../../test-utils'; -// import { transformArguments } from './INFO'; +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import INFO from './INFO'; -// describe('TDIGEST.INFO', () => { -// it('transformArguments', () => { -// assert.deepEqual( -// transformArguments('key'), -// ['TDIGEST.INFO', 'key'] -// ); -// }); +describe('TDIGEST.INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + INFO.transformArguments('key'), + ['TDIGEST.INFO', 'key'] + ); + }); -// testUtils.testWithClient('client.tDigest.info', async client => { -// await client.tDigest.create('key'); + testUtils.testWithClient('client.tDigest.info', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.info('key') + ]); -// const info = await client.tDigest.info('key'); -// assert(typeof info.capacity, 'number'); -// assert(typeof info.mergedNodes, 'number'); -// assert(typeof info.unmergedNodes, 'number'); -// assert(typeof info.mergedWeight, 'number'); -// assert(typeof info.unmergedWeight, 'number'); -// assert(typeof info.totalCompression, 'number'); -// assert(typeof info.totalCompression, 'number'); -// }, GLOBAL.SERVERS.OPEN); -// }); + assert(typeof reply.capacity, 'number'); + assert(typeof reply.mergedNodes, 'number'); + assert(typeof reply.unmergedNodes, 'number'); + assert(typeof reply.mergedWeight, 'number'); + assert(typeof reply.unmergedWeight, 'number'); + assert(typeof reply.totalCompression, 'number'); + assert(typeof reply.totalCompression, 'number'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/INFO.ts b/packages/bloom/lib/commands/t-digest/INFO.ts index 7830f71f9dd..5286f9742bf 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.ts @@ -1,51 +1,49 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; -// export const FIRST_KEY_INDEX = 1; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument) { + return ['TDIGEST.INFO', key]; + }, + // TODO + // type InfoRawReply = [ + // 'Compression', + // number, + // 'Capacity', + // number, + // 'Merged nodes', + // number, + // 'Unmerged nodes', + // number, + // 'Merged weight', + // string, + // 'Unmerged weight', + // string, + // 'Total compressions', + // number + // ]; -// export const IS_READ_ONLY = true; + // interface InfoReply { + // comperssion: number; + // capacity: number; + // mergedNodes: number; + // unmergedNodes: number; + // mergedWeight: number; + // unmergedWeight: number; + // totalCompression: number; + // } -// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { -// return [ -// 'TDIGEST.INFO', -// key -// ]; -// } - -// type InfoRawReply = [ -// 'Compression', -// number, -// 'Capacity', -// number, -// 'Merged nodes', -// number, -// 'Unmerged nodes', -// number, -// 'Merged weight', -// string, -// 'Unmerged weight', -// string, -// 'Total compressions', -// number -// ]; - -// interface InfoReply { -// comperssion: number; -// capacity: number; -// mergedNodes: number; -// unmergedNodes: number; -// mergedWeight: number; -// unmergedWeight: number; -// totalCompression: number; -// } - -// export function transformReply(reply: InfoRawReply): InfoReply { -// return { -// comperssion: reply[1], -// capacity: reply[3], -// mergedNodes: reply[5], -// unmergedNodes: reply[7], -// mergedWeight: Number(reply[9]), -// unmergedWeight: Number(reply[11]), -// totalCompression: reply[13] -// }; -// } \ No newline at end of file + // export function transformReply(reply: InfoRawReply): InfoReply { + // return { + // comperssion: reply[1], + // capacity: reply[3], + // mergedNodes: reply[5], + // unmergedNodes: reply[7], + // mergedWeight: Number(reply[9]), + // unmergedWeight: Number(reply[11]), + // totalCompression: reply[13] + // }; + // } + transformReply: undefined as unknown as () => any +} as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/index.ts b/packages/bloom/lib/commands/t-digest/index.ts index de3d07bdb7b..d180911dbf9 100644 --- a/packages/bloom/lib/commands/t-digest/index.ts +++ b/packages/bloom/lib/commands/t-digest/index.ts @@ -4,7 +4,7 @@ import BYRANK from './BYRANK'; import BYREVRANK from './BYREVRANK'; import CDF from './CDF'; import CREATE from './CREATE'; -// import INFO from './INFO'; +import INFO from './INFO'; import MAX from './MAX'; import MERGE from './MERGE'; import MIN from './MIN'; @@ -25,8 +25,8 @@ export default { cdf: CDF, CREATE, create: CREATE, - // INFO, - // info: INFO, + INFO, + info: INFO, MAX, max: MAX, MERGE, diff --git a/packages/client/lib/commands/CLUSTER_INFO.spec.ts b/packages/client/lib/commands/CLUSTER_INFO.spec.ts index e20b90a3011..f7c708663fc 100644 --- a/packages/client/lib/commands/CLUSTER_INFO.spec.ts +++ b/packages/client/lib/commands/CLUSTER_INFO.spec.ts @@ -1,11 +1,11 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './CLUSTER_INFO'; +import CLUSTER_INFO from './CLUSTER_INFO'; describe('CLUSTER INFO', () => { it('transformArguments', () => { assert.deepEqual( - transformArguments(), + CLUSTER_INFO.transformArguments(), ['CLUSTER', 'INFO'] ); }); diff --git a/packages/client/lib/commands/INFO.spec.ts b/packages/client/lib/commands/INFO.spec.ts index f59ce26168a..c4555778729 100644 --- a/packages/client/lib/commands/INFO.spec.ts +++ b/packages/client/lib/commands/INFO.spec.ts @@ -1,20 +1,28 @@ import { strict as assert } from 'node:assert'; -import { transformArguments } from './INFO'; +import testUtils, { GLOBAL } from '../test-utils'; +import INFO from './INFO'; describe('INFO', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments(), - ['INFO'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + INFO.transformArguments(), + ['INFO'] + ); + }); - it('server section', () => { - assert.deepEqual( - transformArguments('server'), - ['INFO', 'server'] - ); - }); + it('server section', () => { + assert.deepEqual( + INFO.transformArguments('server'), + ['INFO', 'server'] + ); }); + }); + + testUtils.testWithClient('client.info', async client => { + assert.equal( + typeof await client.info(), + 'string' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/KEYS.spec.ts b/packages/client/lib/commands/KEYS.spec.ts index 46f8a3cb0b2..8100559a7e9 100644 --- a/packages/client/lib/commands/KEYS.spec.ts +++ b/packages/client/lib/commands/KEYS.spec.ts @@ -2,13 +2,10 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; describe('KEYS', () => { - testUtils.testAll('keys', async client => { + testUtils.testWithClient('keys', async client => { assert.deepEqual( await client.keys('pattern'), [] ); - }, { - client: GLOBAL.SERVERS.OPEN, - cluster: GLOBAL.CLUSTERS.OPEN - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/SCAN.spec.ts b/packages/client/lib/commands/SCAN.spec.ts index 908c57ffee5..f4dd865d113 100644 --- a/packages/client/lib/commands/SCAN.spec.ts +++ b/packages/client/lib/commands/SCAN.spec.ts @@ -50,7 +50,7 @@ describe('SCAN', () => { }); }); - testUtils.testAll('scan', async client => { + testUtils.testWithClient('client.scan', async client => { assert.deepEqual( await client.scan('0'), { @@ -58,8 +58,5 @@ describe('SCAN', () => { keys: [] } ); - }, { - client: GLOBAL.SERVERS.OPEN, - cluster: GLOBAL.CLUSTERS.OPEN - }); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/WAIT.spec.ts b/packages/client/lib/commands/WAIT.spec.ts index ff91f4ed514..61b197c90ba 100644 --- a/packages/client/lib/commands/WAIT.spec.ts +++ b/packages/client/lib/commands/WAIT.spec.ts @@ -10,13 +10,10 @@ describe('WAIT', () => { ); }); - testUtils.testAll('wait', async client => { + testUtils.testWithClient('client.wait', async client => { assert.equal( await client.wait(0, 1), 0 ); - }, { - client: GLOBAL.SERVERS.OPEN, - cluster: GLOBAL.CLUSTERS.OPEN - }); + }, GLOBAL.SERVERS.OPEN); }); From 2d8c0f0b79a1a6177efecb62d7fa95bbbb5d8cd0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 19:12:29 -0500 Subject: [PATCH 245/325] getting ready for a beta release :) --- .gitignore | 1 + package-lock.json | 331 +++++++++--------- package.json | 2 +- packages/client/.npmignore | 10 - packages/graph/lib/commands/QUERY.ts | 2 +- packages/redis/tsconfig.json | 15 +- .../search/lib/commands/AGGREGATE.spec.ts | 1 - packages/search/lib/commands/AGGREGATE.ts | 6 +- packages/search/lib/commands/index.ts | 5 - packages/test-utils/tsconfig.json | 5 +- packages/time-series/.npmignore | 6 - tsconfig.json | 5 +- 12 files changed, 192 insertions(+), 197 deletions(-) delete mode 100644 packages/client/.npmignore delete mode 100644 packages/time-series/.npmignore diff --git a/.gitignore b/.gitignore index dfd47ff6716..ecdef37dffd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules/ .DS_Store dump.rdb documentation/ +tsconfig.tsbuildinfo diff --git a/package-lock.json b/package-lock.json index f28500f157c..50211aa1760 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,14 +11,14 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.3", - "@types/node": "^20.8.9", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@types/node": "^20.8.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "tsx": "^3.14.0", - "typedoc": "^0.25.2", + "typedoc": "^0.25.3", "typescript": "^5.2.2" } }, @@ -130,30 +130,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", + "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", + "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/generator": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", + "@babel/parser": "^7.23.3", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.3", + "@babel/types": "^7.23.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -184,12 +184,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -270,9 +270,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -439,9 +439,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", + "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -465,19 +465,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/generator": "^7.23.3", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -495,9 +495,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", + "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", @@ -876,18 +876,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "peer": true, "dependencies": { @@ -909,9 +909,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true, "peer": true, "engines": { @@ -919,13 +919,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -948,9 +948,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true, "peer": true }, @@ -1116,9 +1116,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1233,73 +1233,73 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.3.tgz", - "integrity": "sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz", + "integrity": "sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", + "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.19", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.19.tgz", - "integrity": "sha512-MWZNGPSchIdDfb5FL+VFi4zHsHbNOTQEgjqFQk7HazXSXwUU9PAX3z9XBqb3AJGYr9YwrtCtaSMsT3brYsN/jQ==", + "version": "10.0.20", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", + "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.3.tgz", - "integrity": "sha512-4g+2YyWe0Ve+LBh+WUm1697PD0Kdi6coG1eU0YjQbwx61AZ8XbEpL1zIT6WjuUKrCMCROpEaYQPDjBnDouBVAQ==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.28", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", - "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", + "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", - "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", + "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/type-utils": "6.9.0", - "@typescript-eslint/utils": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/type-utils": "6.10.0", + "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1325,15 +1325,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", + "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4" }, "engines": { @@ -1353,13 +1353,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1370,13 +1370,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", - "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", + "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/utils": "6.10.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1397,9 +1397,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1410,13 +1410,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1437,17 +1437,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", - "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", + "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", "semver": "^7.5.4" }, "engines": { @@ -1462,12 +1462,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1478,10 +1478,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "peer": true + }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "peer": true, "bin": { @@ -1626,9 +1633,9 @@ } }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, "node_modules/balanced-match": { @@ -1747,9 +1754,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001549", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", - "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", + "version": "1.0.30001561", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", + "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", "dev": true, "funding": [ { @@ -1991,9 +1998,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.556", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz", - "integrity": "sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ==", + "version": "1.4.580", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz", + "integrity": "sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw==", "dev": true }, "node_modules/email-addresses": { @@ -2073,19 +2080,20 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2241,9 +2249,9 @@ "peer": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2882,9 +2890,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -3352,9 +3360,9 @@ "dev": true }, "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", + "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", @@ -3863,9 +3871,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "peer": true, "engines": { @@ -4119,9 +4127,9 @@ "dev": true }, "node_modules/sinon": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.0.tgz", - "integrity": "sha512-ZSgzF0vwmoa8pq0GEynqfdnpEDyP1PkYmEChnkjW0Vyh8IDlyFEJ+fkMhCP0il6d5cJjPl2PUsnUSAuP5sttOQ==", + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz", + "integrity": "sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -4413,9 +4421,9 @@ } }, "node_modules/typedoc": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz", - "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", + "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -4477,9 +4485,9 @@ "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -4702,7 +4710,6 @@ } }, "packages/bloom": { - "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { @@ -4713,7 +4720,6 @@ } }, "packages/client": { - "name": "@redis/client", "version": "2.0.0-next.2", "license": "MIT", "dependencies": { @@ -4730,7 +4736,6 @@ } }, "packages/graph": { - "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { @@ -4741,7 +4746,6 @@ } }, "packages/json": { - "name": "@redis/json", "version": "1.0.6", "license": "MIT", "devDependencies": { @@ -4764,7 +4768,6 @@ } }, "packages/search": { - "name": "@redis/search", "version": "1.1.5", "license": "MIT", "devDependencies": { @@ -4775,7 +4778,6 @@ } }, "packages/test-utils": { - "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.24", "yargs": "^17.7.2" @@ -4826,7 +4828,6 @@ } }, "packages/time-series": { - "name": "@redis/time-series", "version": "1.0.5", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index a3f3d3a8c4f..3b4bfc1a2f8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ ], "scripts": { "test": "npm run test -ws --if-present", - "build": "NODE_OPTIONS='--max-old-space-size=8192' tsc --build", + "build": "NODE_OPTIONS='--max-old-space-size=4096' tsc --build", "documentation": "typedoc", "gh-pages": "gh-pages -d ./documentation -e ./documentation -u 'documentation-bot '" }, diff --git a/packages/client/.npmignore b/packages/client/.npmignore deleted file mode 100644 index d064e1d0db6..00000000000 --- a/packages/client/.npmignore +++ /dev/null @@ -1,10 +0,0 @@ -.nyc_output/ -coverage/ -documentation/ -lib/ -.eslintrc.json -.nycrc.json -.release-it.json -dump.rdb -index.ts -tsconfig.json diff --git a/packages/graph/lib/commands/QUERY.ts b/packages/graph/lib/commands/QUERY.ts index 10032fb8451..8a052354610 100644 --- a/packages/graph/lib/commands/QUERY.ts +++ b/packages/graph/lib/commands/QUERY.ts @@ -14,7 +14,7 @@ type QueryRawReply = TuplesReply<[ metadata: Metadata ]>; -type QueryParam = null | RedisArgument | number | boolean | QueryParams | Array; +type QueryParam = null | string | number | boolean | QueryParams | Array; type QueryParams = { [key: string]: QueryParam; diff --git a/packages/redis/tsconfig.json b/packages/redis/tsconfig.json index 50da0ba733a..0ffdfcf10bb 100644 --- a/packages/redis/tsconfig.json +++ b/packages/redis/tsconfig.json @@ -5,5 +5,18 @@ }, "include": [ "./index.ts" - ] + ], + "references": [{ + "path": "./packages/client" + }, { + "path": "./packages/bloom" + }, { + "path": "./packages/graph" + }, { + "path": "./packages/json" + }, { + "path": "./packages/search" + }, { + "path": "./packages/time-series" + }] } diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index c0b34997c63..1a40f264ff4 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -1,7 +1,6 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; import AGGREGATE from './AGGREGATE'; -// import { SchemaFieldTypes } from '.'; describe('AGGREGATE', () => { describe('transformArguments', () => { diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index c21f1ce2a55..a12e455a0cb 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -194,15 +194,15 @@ export default { break; case FT_AGGREGATE_STEPS.APPLY: - args.push('APPLY', step.expression, 'AS', step.AS); + args.push(step.expression, 'AS', step.AS); break; case FT_AGGREGATE_STEPS.LIMIT: - args.push('LIMIT', step.from.toString(), step.size.toString()); + args.push(step.from.toString(), step.size.toString()); break; case FT_AGGREGATE_STEPS.FILTER: - args.push('FILTER', step.expression); + args.push(step.expression); break; } } diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index af51fc1bbc2..24a1996a6b3 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -32,11 +32,6 @@ import SUGLEN from './SUGLEN'; import SYNDUMP from './SYNDUMP'; import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; -import { RedisArgument } from '@redis/client'; -// import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; -// import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -// import { SearchOptions } from './SEARCH'; -// import { CommandArguments } from '@redis/client/dist/lib/RESP/types'; export default { _LIST, diff --git a/packages/test-utils/tsconfig.json b/packages/test-utils/tsconfig.json index 14fda1d8711..6bb104668fc 100644 --- a/packages/test-utils/tsconfig.json +++ b/packages/test-utils/tsconfig.json @@ -5,5 +5,8 @@ }, "include": [ "./lib/**/*.ts" - ] + ], + "references": [{ + "path": "../client" + }] } diff --git a/packages/time-series/.npmignore b/packages/time-series/.npmignore deleted file mode 100644 index bbef2b404fb..00000000000 --- a/packages/time-series/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.nyc_output/ -coverage/ -lib/ -.nycrc.json -.release-it.json -tsconfig.json diff --git a/tsconfig.json b/tsconfig.json index c65451d427b..93f7f5de025 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,5 @@ { + "files": [], "references": [{ "path": "./packages/client" }, { @@ -13,7 +14,5 @@ "path": "./packages/search" }, { "path": "./packages/time-series" - }, { - "path": "./packages/redis" }] -} \ No newline at end of file +} From 37c39b71c9f9a921228f39b0e8d23570174aae53 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 19:57:43 -0500 Subject: [PATCH 246/325] fix cluster slots PubSubNode type --- packages/client/lib/cluster/cluster-slots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 6fc0af8c919..514e7805855 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -78,7 +78,7 @@ type PubSubNode< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > = ( - Exclude, 'client'> & + Omit, 'client'> & Required, 'client'>> ); From 7247777a6f639b4b6adb96d86f2a16d7d34fc804 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:01:26 -0500 Subject: [PATCH 247/325] a little bit docs --- docs/blocking-commands.md | 88 ----------------------------- docs/clustering.md | 22 +++----- docs/pool.md | 74 ++++++++++++++++++++++++ docs/pub-sub.md | 2 +- docs/scan-iterators.md | 6 +- packages/client/lib/client/index.ts | 2 +- packages/client/lib/client/pool.ts | 2 +- packages/redis/README.md | 16 +++--- 8 files changed, 97 insertions(+), 115 deletions(-) delete mode 100644 docs/blocking-commands.md create mode 100644 docs/pool.md diff --git a/docs/blocking-commands.md b/docs/blocking-commands.md deleted file mode 100644 index 639ab2b78ed..00000000000 --- a/docs/blocking-commands.md +++ /dev/null @@ -1,88 +0,0 @@ -### 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.isolated().blPop( - '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). - -# Isolated Execution - -Sometimes you want to run your commands on an exclusive connection. There are a few reasons to do this: - -- You're using [transactions]() and need to `WATCH` a key or keys for changes. -- You want to run a blocking command that will take over the connection, such as `BLPOP` or `BLMOVE`. -- You're using the `MONITOR` command which also takes over a connection. - -Below are several examples of how to use isolated execution. - -> NOTE: Behind the scenes we're using [`generic-pool`](https://www.npmjs.com/package/generic-pool) to provide a pool of connections that can be isolated. Go there to learn more. - -## The Simple Scenario - -This just isolates execution on a single connection. Do what you want with that connection: - -```typescript -await client.executeIsolated(async isolatedClient => { - await isolatedClient.set('key', 'value'); - await isolatedClient.get('key'); -}); -``` - -## Transactions - -Things get a little more complex with transactions. Here we are `.watch()`ing some keys. If the keys change during the transaction, a `WatchError` is thrown when `.exec()` is called: - -```typescript -try { - await client.executeIsolated(async isolatedClient => { - await isolatedClient.watch('key'); - - const multi = isolatedClient.multi() - .ping() - .get('key'); - - if (Math.random() > 0.5) { - await isolatedClient.watch('another-key'); - multi.set('another-key', await isolatedClient.get('another-key') / 2); - } - - return multi.exec(); - }); -} catch (err) { - if (err instanceof WatchError) { - // the transaction aborted - } -} - -``` - -## Blocking Commands - -For blocking commands, you can execute a tidy little one-liner: - -```typescript -await client.executeIsolated(isolatedClient => isolatedClient.blPop('key')); -``` - -Or, you can just run the command directly, and provide the `isolated` option: - -```typescript -await client.blPop( - commandOptions({ isolated: true }), - 'key' -); -``` diff --git a/docs/clustering.md b/docs/clustering.md index 7b8b66a9ad4..38419b06cdd 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -4,26 +4,22 @@ Connecting to a cluster is a bit different. Create the client by specifying some (or all) of the nodes in your cluster and then use it like a regular client instance: -```typescript +```javascript import { createCluster } from 'redis'; -const cluster = createCluster({ - rootNodes: [ - { +const cluster = await createCluster({ + rootNodes: [{ url: 'redis://10.0.0.1:30001' - }, - { + }, { url: 'redis://10.0.0.2:30002' - } - ] -}); - -cluster.on('error', (err) => console.log('Redis Cluster Error', err)); - -await cluster.connect(); + }] + }) + .on('error', err => console.log('Redis Cluster Error', err)) + .connect(); await cluster.set('key', 'value'); const value = await cluster.get('key'); +await cluster.close(); ``` ## `createCluster` configuration diff --git a/docs/pool.md b/docs/pool.md new file mode 100644 index 00000000000..7121e601d73 --- /dev/null +++ b/docs/pool.md @@ -0,0 +1,74 @@ +# `RedisClientPool` + +Sometimes you want to run your commands on an exclusive connection. There are a few reasons to do this: + +- You want to run a blocking command that will take over the connection, such as `BLPOP` or `BLMOVE`. +- You're using [transactions](https://redis.io/docs/interact/transactions/) and need to `WATCH` a key or keys for changes. +- Some more... + +For those use cases you'll need to create a connection pool. + +## Creating a pool + +You can create a pool using the `createClientPool` function: + +```javascript +import { createClientPool } from 'redis'; + +const pool = await createClientPool() + .on('error', err => console.error('Redis Client Pool Error', err)); +``` + +the function accepts two arguments, the client configuration (see [here](./client-configuration.md) for more details), and the pool configuration: + +| Property | Default | Description | +|----------------|---------|--------------------------------------------------------------------------------------------------------------------------------| +| minimum | 1 | The minimum clients the pool should hold to. The pool won't close clients if the pool size is less than the minimum. | +| maximum | 100 | The maximum clients the pool will have at once. The pool won't create any more resources and queue requests in memory. | +| acquireTimeout | 3000 | The maximum time (in ms) a task can wait in the queue. The pool will reject the task with `TimeoutError` in case of a timeout. | +| cleanupDelay | 3000 | The time to wait before cleaning up unused clients. | + +You can also create a pool from a client (reusing it's configuration): +```javascript +const pool = await client.createPool() + .on('error', err => console.error('Redis Client Pool Error', err)); +``` + +## The Simple Scenario + +All the client APIs are exposed on the pool instance directly, and will execute the commands using one of the available clients. + +```javascript +await pool.sendCommand(['PING']); // 'PONG' +await client.ping(); // 'PONG' +await client.withTypeMapping({ + [RESP_TYPES.SIMPLE_STRING]: Buffer +}).ping(); // Buffer +``` + +## Transactions + +Things get a little more complex with transactions. Here we are `.watch()`ing some keys. If the keys change during the transaction, a `WatchError` is thrown when `.exec()` is called: + +```javascript +try { + await pool.execute(async client => { + await client.watch('key'); + + const multi = client.multi() + .ping() + .get('key'); + + if (Math.random() > 0.5) { + await client.watch('another-key'); + multi.set('another-key', await client.get('another-key') / 2); + } + + return multi.exec(); + }); +} catch (err) { + if (err instanceof WatchError) { + // the transaction aborted + } +} +``` diff --git a/docs/pub-sub.md b/docs/pub-sub.md index b319925569d..bd1d842e0e5 100644 --- a/docs/pub-sub.md +++ b/docs/pub-sub.md @@ -6,7 +6,7 @@ The Pub/Sub API is implemented by `RedisClient` and `RedisCluster`. Pub/Sub requires a dedicated stand-alone client. You can easily get one by `.duplicate()`ing an existing `RedisClient`: -```typescript +```javascript const subscriber = client.duplicate(); subscriber.on('error', err => console.error(err)); await subscriber.connect(); diff --git a/docs/scan-iterators.md b/docs/scan-iterators.md index ead3a346a2e..47c4d6c0567 100644 --- a/docs/scan-iterators.md +++ b/docs/scan-iterators.md @@ -4,7 +4,7 @@ [`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 +```javascript for await (const keys of client.scanIterator()) { const values = await client.mGet(keys); } @@ -12,7 +12,7 @@ for await (const keys of client.scanIterator()) { This works with `HSCAN`, `SSCAN`, and `ZSCAN` too: -```typescript +```javascript for await (const entries of client.hScanIterator('hash')) {} for await (const members of client.sScanIterator('set')) {} for await (const membersWithScores of client.zScanIterator('sorted-set')) {} @@ -20,7 +20,7 @@ for await (const membersWithScores of client.zScanIterator('sorted-set')) {} You can override the default options by providing a configuration object: -```typescript +```javascript client.scanIterator({ cursor: '0', // optional, defaults to '0' TYPE: 'string', // `SCAN` only diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 4979c905b2a..72ce1f2ff7e 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -517,7 +517,7 @@ export default class RedisClient< /** * Create {@link RedisClientPool `RedisClientPool`} using this client as a prototype */ - pool(options?: Partial) { + createPool(options?: Partial) { return RedisClientPool.create( this._options, options diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 6ed008f8867..357c89f45b2 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -216,7 +216,7 @@ export class RedisClientPool< } /** - * You are probably looking for {@link RedisClient.pool `RedisClient.pool`}, + * You are probably looking for {@link RedisClient.createPool `RedisClient.createPool`}, * {@link RedisClientPool.fromClient `RedisClientPool.fromClient`}, * or {@link RedisClientPool.fromOptions `RedisClientPool.fromOptions`}... */ diff --git a/packages/redis/README.md b/packages/redis/README.md index ce8b618e9b8..4a57dbd7b15 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -61,7 +61,7 @@ To check if the the client is connected and ready to send commands, use `client. 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 +```javascript // raw Redis commands await client.HSET('key', 'field', 'value'); await client.HGETALL('key'); @@ -73,7 +73,7 @@ await client.hGetAll('key'); Modifiers to commands are specified using a JavaScript object: -```typescript +```javascript await client.set('key', 'value', { expiration: { type: 'EX', @@ -85,7 +85,7 @@ await client.set('key', 'value', { Replies will be mapped to useful data structures: -```typescript +```javascript await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } await client.hVals('key'); // ['value1', 'value2'] ``` @@ -96,7 +96,7 @@ await client.hVals('key'); // ['value1', 'value2'] If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`: -```typescript +```javascript await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] @@ -110,7 +110,7 @@ There are two functions that disconnect a client from the Redis server. In most #### `.close()` -```typescript +```javascript const [ping, get] = await Promise.all([ client.ping(), client.get('key'), @@ -134,14 +134,14 @@ Forcibly close a client's connection to Redis immediately. Calling `destroy` wil Node Redis will automatically pipeline requests that are made during the same "tick". -```typescript +```javascript 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 +```javascript await Promise.all([ client.set('Tm9kZSBSZWRpcw==', 'users:1'), client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==') @@ -172,7 +172,7 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each - [Scan Iterators](../../docs/scan-iterators.md). - [Programmability](../../docs/programmability.md). - [Command Options](../../docs/command-options.md). -- [Blocking Commands](../../docs/blocking-commands.md). +- [Pool](../../docs/pool.md). - [Clustering](../../docs/clustering.md). ## Supported Redis versions From 5b086ba3581a1e54ecb597ea8b72aa9e1fdbd2c2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:08:53 -0500 Subject: [PATCH 248/325] get ready for beta release --- .npmignore | 12 - package-lock.json | 4418 ++++++++++++++++- package.json | 1 + packages/bloom/.npmignore | 6 - packages/json/.npmignore | 6 - packages/search/.npmignore | 6 - packages/search/lib/commands/EXPLAIN.ts | 46 +- packages/search/lib/commands/INFO.ts | 326 +- .../search/lib/commands/PROFILE_AGGREGATE.ts | 46 +- .../search/lib/commands/PROFILE_SEARCH.ts | 46 +- packages/time-series/lib/commands/INFO.ts | 152 +- .../time-series/lib/commands/INFO_DEBUG.ts | 104 +- 12 files changed, 4666 insertions(+), 503 deletions(-) delete mode 100644 .npmignore delete mode 100644 packages/bloom/.npmignore delete mode 100644 packages/json/.npmignore delete mode 100644 packages/search/.npmignore diff --git a/.npmignore b/.npmignore deleted file mode 100644 index a36c5e83cf2..00000000000 --- a/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -.github/ -.vscode/ -docs/ -examples/ -packages/ -.deepsource.toml -.release-it.json -CONTRIBUTING.md -SECURITY.md -index.ts -tsconfig.base.json -tsconfig.json diff --git a/package-lock.json b/package-lock.json index 50211aa1760..0f7fd004d05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", + "release-it": "^16.2.1", "tsx": "^3.14.0", "typedoc": "^0.25.3", "typescript": "^5.2.2" @@ -954,6 +955,12 @@ "dev": true, "peer": true }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1125,6 +1132,18 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@ljharb/through": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz", + "integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1160,6 +1179,238 @@ "node": ">= 8" } }, + "node_modules/@octokit/auth-token": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^3.0.0", + "@octokit/graphql": "^5.0.0", + "@octokit/request": "^6.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/endpoint": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/graphql": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "dev": true, + "dependencies": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^9.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "18.1.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", + "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "dev": true, + "dependencies": { + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=4" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", + "dev": true, + "dependencies": { + "@octokit/types": "^10.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/request-error": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "dev": true, + "dependencies": { + "@octokit/types": "^9.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/request/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@octokit/rest": { + "version": "19.0.13", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", + "dev": true, + "dependencies": { + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, + "node_modules/@octokit/types": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dev": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@redis/bloom": { "resolved": "packages/bloom", "link": true @@ -1188,6 +1439,18 @@ "resolved": "packages/time-series", "link": true }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -1232,6 +1495,30 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1508,6 +1795,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1538,6 +1837,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -1547,6 +1855,33 @@ "node": ">=6" } }, + "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==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1614,6 +1949,19 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -1632,18 +1980,135 @@ "node": ">=0.10.0" } }, + "node_modules/array.prototype.map": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.6.tgz", + "integrity": "sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-ftp": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", + "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1653,35 +2118,195 @@ "node": ">=8" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" }, "engines": { - "node": ">=8" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { + "node_modules/boxen/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/boxen/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", @@ -1713,12 +2338,78 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1734,12 +2425,25 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -1789,6 +2493,12 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1828,6 +2538,21 @@ "node": ">= 6" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1837,6 +2562,51 @@ "node": ">=6" } }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", + "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -1848,6 +2618,15 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cluster-key-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", @@ -1895,12 +2674,73 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "dev": true, + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1915,25 +2755,61 @@ "node": ">= 8" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "type-fest": "^1.0.1" }, "engines": { - "node": ">=6.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize": { - "version": "1.2.0", + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, @@ -1941,6 +2817,42 @@ "node": ">=0.10.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1948,6 +2860,40 @@ "dev": true, "peer": true }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-require-extensions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", @@ -1963,6 +2909,90 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -1997,6 +3027,27 @@ "node": ">=6.0.0" } }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { "version": "1.4.580", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz", @@ -2015,6 +3066,131 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2067,6 +3243,18 @@ "node": ">=6" } }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2079,6 +3267,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, "node_modules/eslint": { "version": "8.53.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", @@ -2226,7 +3435,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -2236,11 +3444,59 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2299,31 +3555,94 @@ "reusify": "^1.0.4" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "dev": true, - "peer": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], "dependencies": { - "flat-cache": "^3.0.4" + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.20 || >= 14.13" } }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, "engines": { - "node": ">=4" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, "dependencies": { @@ -2414,6 +3733,15 @@ "dev": true, "peer": true }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -2427,6 +3755,27 @@ "node": ">=8.0.0" } }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", @@ -2481,6 +3830,42 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -2507,6 +3892,21 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -2516,6 +3916,34 @@ "node": ">=8.0.0" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-tsconfig": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", @@ -2528,6 +3956,62 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/get-uri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", + "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", + "dev": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.0", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/data-uri-to-buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", + "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/gh-pages": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.0.0.tgz", @@ -2578,6 +4062,25 @@ "node": ">=0.10.0" } }, + "node_modules/git-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", + "dev": true, + "dependencies": { + "is-ssh": "^1.4.0", + "parse-url": "^8.1.0" + } + }, + "node_modules/git-url-parse": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", + "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", + "dev": true, + "dependencies": { + "git-up": "^7.0.0" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -2611,6 +4114,21 @@ "node": ">=10.13.0" } }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globals": { "version": "13.23.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", @@ -2627,6 +4145,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2647,6 +4180,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2659,6 +4229,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2668,6 +4247,69 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -2693,6 +4335,18 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2708,6 +4362,92 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", + "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2722,7 +4462,6 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "peer": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2734,6 +4473,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2768,46 +4516,428 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/inquirer": { + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.11.tgz", + "integrity": "sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==", + "dev": true, + "dependencies": { + "@ljharb/through": "^2.3.9", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/inquirer/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/inquirer/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/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==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-number": { @@ -2819,12 +4949,35 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -2838,6 +4991,61 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ssh": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", + "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", + "dev": true, + "dependencies": { + "protocols": "^2.0.1" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2850,6 +5058,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2868,6 +5121,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -2877,6 +5142,42 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2889,6 +5190,22 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/issue-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "dev": true, + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": ">=10.13" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -3007,6 +5324,28 @@ "node": ">=8" } }, + "node_modules/iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "dependencies": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3041,8 +5380,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "peer": true + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3099,11 +5443,25 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "peer": true, "dependencies": { "json-buffer": "3.0.1" } }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "dev": true, + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3118,6 +5476,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3133,6 +5497,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", @@ -3145,6 +5527,18 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3152,6 +5546,12 @@ "dev": true, "peer": true }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3168,6 +5568,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3183,6 +5595,18 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, + "node_modules/macos-release": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.2.0.tgz", + "integrity": "sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -3219,6 +5643,12 @@ "node": ">= 12" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3241,6 +5671,51 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3253,6 +5728,15 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/mocha": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", @@ -3341,6 +5825,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -3359,6 +5852,42 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/new-github-release-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", + "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", + "dev": true, + "dependencies": { + "type-fest": "^2.5.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/new-github-release-url/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nise": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", @@ -3381,6 +5910,43 @@ "type-detect": "4.0.8" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -3408,6 +5974,45 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", + "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -3560,56 +6165,327 @@ "yargs-parser": "^18.1.2" }, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", + "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.3.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "string-width": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "dev": true, + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", + "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^10.2.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/os-name": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", + "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", "dev": true, + "dependencies": { + "macos-release": "^3.1.0", + "windows-release": "^5.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, - "peer": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=12.20" } }, "node_modules/p-limit": { @@ -3663,6 +6539,39 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dev": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dev": true, + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/package-hash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", @@ -3678,12 +6587,54 @@ "node": ">=8" } }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dev": true, + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json/node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "peer": true, "dependencies": { "callsites": "^3.0.0" }, @@ -3691,6 +6642,42 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dev": true, + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dev": true, + "dependencies": { + "parse-path": "^7.0.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3718,6 +6705,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -3870,6 +6863,72 @@ "node": ">=8" } }, + "node_modules/promise.allsettled": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.7.tgz", + "integrity": "sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA==", + "dev": true, + "dependencies": { + "array.prototype.map": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "iterate-value": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true + }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3880,6 +6939,21 @@ "node": ">=6" } }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "dev": true, + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3900,6 +6974,18 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3909,6 +6995,50 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3921,10 +7051,159 @@ "node": ">=8.10.0" } }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/redis": { "resolved": "packages/redis", "link": true }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dev": true, + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/release-it": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-16.2.1.tgz", + "integrity": "sha512-+bHiKPqkpld+NaiW+K/2WsjaHgfPB00J6uk8a+g8QyuBtzfFoMVe+GKsfaDO5ztEHRrSg+7luoXzd8IfvPNPig==", + "dev": true, + "dependencies": { + "@iarna/toml": "2.2.5", + "@octokit/rest": "19.0.13", + "async-retry": "1.3.3", + "chalk": "5.3.0", + "cosmiconfig": "8.3.6", + "execa": "7.2.0", + "git-url-parse": "13.1.0", + "globby": "13.2.2", + "got": "13.0.0", + "inquirer": "9.2.11", + "is-ci": "3.0.1", + "issue-parser": "6.0.0", + "lodash": "4.17.21", + "mime-types": "2.1.35", + "new-github-release-url": "2.0.0", + "node-fetch": "3.3.2", + "open": "9.1.0", + "ora": "7.0.1", + "os-name": "5.1.0", + "promise.allsettled": "1.0.7", + "proxy-agent": "6.3.1", + "semver": "7.5.4", + "shelljs": "0.8.5", + "update-notifier": "6.0.2", + "url-join": "5.0.0", + "wildcard-match": "5.1.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "release-it": "bin/release-it.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/release-it/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/release-it/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/release-it/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/release-it/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -3952,12 +7231,34 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "peer": true, "engines": { "node": ">=4" } @@ -3971,6 +7272,67 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3996,6 +7358,107 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/run-applescript/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-applescript/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4019,6 +7482,39 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4039,6 +7535,26 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -4054,6 +7570,21 @@ "node": ">=10" } }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4087,6 +7618,35 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4108,6 +7668,23 @@ "node": ">=8" } }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/shiki": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", @@ -4120,6 +7697,20 @@ "vscode-textmate": "^8.0.0" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4162,6 +7753,50 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4204,6 +7839,42 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "dev": true, + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4218,6 +7889,51 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4239,6 +7955,18 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4284,6 +8012,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4305,6 +8045,30 @@ "dev": true, "peer": true }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4326,6 +8090,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -4359,6 +8129,12 @@ "typescript": ">=4.2.0" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/tsx": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", @@ -4411,6 +8187,71 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -4478,12 +8319,48 @@ "node": ">=14.17" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -4493,6 +8370,15 @@ "node": ">= 10.0.0" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -4523,6 +8409,46 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "dev": true, + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4533,6 +8459,21 @@ "punycode": "^2.1.0" } }, + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -4554,6 +8495,40 @@ "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4569,12 +8544,210 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wildcard-match": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", + "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", + "dev": true + }, + "node_modules/windows-release": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.1.1.tgz", + "integrity": "sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==", + "dev": true, + "dependencies": { + "execa": "^5.1.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/windows-release/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/windows-release/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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/windows-release/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/windows-release/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -4616,6 +8789,18 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -4710,6 +8895,7 @@ } }, "packages/bloom": { + "name": "@redis/bloom", "version": "1.2.0", "license": "MIT", "devDependencies": { @@ -4720,6 +8906,7 @@ } }, "packages/client": { + "name": "@redis/client", "version": "2.0.0-next.2", "license": "MIT", "dependencies": { @@ -4736,6 +8923,7 @@ } }, "packages/graph": { + "name": "@redis/graph", "version": "1.1.0", "license": "MIT", "devDependencies": { @@ -4746,6 +8934,7 @@ } }, "packages/json": { + "name": "@redis/json", "version": "1.0.6", "license": "MIT", "devDependencies": { @@ -4768,6 +8957,7 @@ } }, "packages/search": { + "name": "@redis/search", "version": "1.1.5", "license": "MIT", "devDependencies": { @@ -4778,6 +8968,7 @@ } }, "packages/test-utils": { + "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.24", "yargs": "^17.7.2" @@ -4828,6 +9019,7 @@ } }, "packages/time-series": { + "name": "@redis/time-series", "version": "1.0.5", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 3b4bfc1a2f8..f15b0e0fce0 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "gh-pages": "^6.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", + "release-it": "^16.2.1", "tsx": "^3.14.0", "typedoc": "^0.25.3", "typescript": "^5.2.2" diff --git a/packages/bloom/.npmignore b/packages/bloom/.npmignore deleted file mode 100644 index bbef2b404fb..00000000000 --- a/packages/bloom/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.nyc_output/ -coverage/ -lib/ -.nycrc.json -.release-it.json -tsconfig.json diff --git a/packages/json/.npmignore b/packages/json/.npmignore deleted file mode 100644 index bbef2b404fb..00000000000 --- a/packages/json/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.nyc_output/ -coverage/ -lib/ -.nycrc.json -.release-it.json -tsconfig.json diff --git a/packages/search/.npmignore b/packages/search/.npmignore deleted file mode 100644 index bbef2b404fb..00000000000 --- a/packages/search/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.nyc_output/ -coverage/ -lib/ -.nycrc.json -.release-it.json -tsconfig.json diff --git a/packages/search/lib/commands/EXPLAIN.ts b/packages/search/lib/commands/EXPLAIN.ts index 538299e9c0f..35e56046a88 100644 --- a/packages/search/lib/commands/EXPLAIN.ts +++ b/packages/search/lib/commands/EXPLAIN.ts @@ -1,28 +1,28 @@ -import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -import { Params, pushParamsArgs } from "."; +// import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; +// import { Params, pushParamsArgs } from "."; -export interface FtExplainOptions { - PARAMS?: Params; - DIALECT?: number; -} +// export interface FtExplainOptions { +// PARAMS?: Params; +// DIALECT?: number; +// } -export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, - transformArguments( - index: RedisArgument, - query: RedisArgument, - options?: FtExplainOptions - ) { - const args = ['FT.EXPLAIN', index, query]; +// export default { +// FIRST_KEY_INDEX: undefined, +// IS_READ_ONLY: true, +// transformArguments( +// index: RedisArgument, +// query: RedisArgument, +// options?: FtExplainOptions +// ) { +// const args = ['FT.EXPLAIN', index, query]; - pushParamsArgs(args, options?.PARAMS); +// pushParamsArgs(args, options?.PARAMS); - if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); - } +// if (options?.DIALECT) { +// args.push('DIALECT', options.DIALECT.toString()); +// } - return args; - }, - transformReply: undefined as unknown as () => SimpleStringReply -} as const satisfies Command; +// return args; +// }, +// transformReply: undefined as unknown as () => SimpleStringReply +// } as const satisfies Command; diff --git a/packages/search/lib/commands/INFO.ts b/packages/search/lib/commands/INFO.ts index 269d12d51cf..c18032891d1 100644 --- a/packages/search/lib/commands/INFO.ts +++ b/packages/search/lib/commands/INFO.ts @@ -1,167 +1,167 @@ -import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; -import { transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; +// import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; +// import { transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; -export function transformArguments(index: string): Array { - return ['FT.INFO', index]; -} +// export function transformArguments(index: string): Array { +// return ['FT.INFO', index]; +// } -type InfoRawReply = [ - 'index_name', - RedisCommandArgument, - 'index_options', - Array, - 'index_definition', - Array, - 'attributes', - Array>, - 'num_docs', - RedisCommandArgument, - 'max_doc_id', - RedisCommandArgument, - 'num_terms', - RedisCommandArgument, - 'num_records', - RedisCommandArgument, - 'inverted_sz_mb', - RedisCommandArgument, - 'vector_index_sz_mb', - RedisCommandArgument, - 'total_inverted_index_blocks', - RedisCommandArgument, - 'offset_vectors_sz_mb', - RedisCommandArgument, - 'doc_table_size_mb', - RedisCommandArgument, - 'sortable_values_size_mb', - RedisCommandArgument, - 'key_table_size_mb', - RedisCommandArgument, - 'records_per_doc_avg', - RedisCommandArgument, - 'bytes_per_record_avg', - RedisCommandArgument, - 'offsets_per_term_avg', - RedisCommandArgument, - 'offset_bits_per_record_avg', - RedisCommandArgument, - 'hash_indexing_failures', - RedisCommandArgument, - 'indexing', - RedisCommandArgument, - 'percent_indexed', - RedisCommandArgument, - 'gc_stats', - [ - 'bytes_collected', - RedisCommandArgument, - 'total_ms_run', - RedisCommandArgument, - 'total_cycles', - RedisCommandArgument, - 'average_cycle_time_ms', - RedisCommandArgument, - 'last_run_time_ms', - RedisCommandArgument, - 'gc_numeric_trees_missed', - RedisCommandArgument, - 'gc_blocks_denied', - RedisCommandArgument - ], - 'cursor_stats', - [ - 'global_idle', - number, - 'global_total', - number, - 'index_capacity', - number, - 'index_total', - number - ], - 'stopwords_list'?, - Array? -]; +// type InfoRawReply = [ +// 'index_name', +// RedisCommandArgument, +// 'index_options', +// Array, +// 'index_definition', +// Array, +// 'attributes', +// Array>, +// 'num_docs', +// RedisCommandArgument, +// 'max_doc_id', +// RedisCommandArgument, +// 'num_terms', +// RedisCommandArgument, +// 'num_records', +// RedisCommandArgument, +// 'inverted_sz_mb', +// RedisCommandArgument, +// 'vector_index_sz_mb', +// RedisCommandArgument, +// 'total_inverted_index_blocks', +// RedisCommandArgument, +// 'offset_vectors_sz_mb', +// RedisCommandArgument, +// 'doc_table_size_mb', +// RedisCommandArgument, +// 'sortable_values_size_mb', +// RedisCommandArgument, +// 'key_table_size_mb', +// RedisCommandArgument, +// 'records_per_doc_avg', +// RedisCommandArgument, +// 'bytes_per_record_avg', +// RedisCommandArgument, +// 'offsets_per_term_avg', +// RedisCommandArgument, +// 'offset_bits_per_record_avg', +// RedisCommandArgument, +// 'hash_indexing_failures', +// RedisCommandArgument, +// 'indexing', +// RedisCommandArgument, +// 'percent_indexed', +// RedisCommandArgument, +// 'gc_stats', +// [ +// 'bytes_collected', +// RedisCommandArgument, +// 'total_ms_run', +// RedisCommandArgument, +// 'total_cycles', +// RedisCommandArgument, +// 'average_cycle_time_ms', +// RedisCommandArgument, +// 'last_run_time_ms', +// RedisCommandArgument, +// 'gc_numeric_trees_missed', +// RedisCommandArgument, +// 'gc_blocks_denied', +// RedisCommandArgument +// ], +// 'cursor_stats', +// [ +// 'global_idle', +// number, +// 'global_total', +// number, +// 'index_capacity', +// number, +// 'index_total', +// number +// ], +// 'stopwords_list'?, +// Array? +// ]; -interface InfoReply { - indexName: RedisCommandArgument; - indexOptions: Array; - indexDefinition: Record; - attributes: Array>; - numDocs: RedisCommandArgument; - maxDocId: RedisCommandArgument; - numTerms: RedisCommandArgument; - numRecords: RedisCommandArgument; - invertedSzMb: RedisCommandArgument; - vectorIndexSzMb: RedisCommandArgument; - totalInvertedIndexBlocks: RedisCommandArgument; - offsetVectorsSzMb: RedisCommandArgument; - docTableSizeMb: RedisCommandArgument; - sortableValuesSizeMb: RedisCommandArgument; - keyTableSizeMb: RedisCommandArgument; - recordsPerDocAvg: RedisCommandArgument; - bytesPerRecordAvg: RedisCommandArgument; - offsetsPerTermAvg: RedisCommandArgument; - offsetBitsPerRecordAvg: RedisCommandArgument; - hashIndexingFailures: RedisCommandArgument; - indexing: RedisCommandArgument; - percentIndexed: RedisCommandArgument; - gcStats: { - bytesCollected: RedisCommandArgument; - totalMsRun: RedisCommandArgument; - totalCycles: RedisCommandArgument; - averageCycleTimeMs: RedisCommandArgument; - lastRunTimeMs: RedisCommandArgument; - gcNumericTreesMissed: RedisCommandArgument; - gcBlocksDenied: RedisCommandArgument; - }; - cursorStats: { - globalIdle: number; - globalTotal: number; - indexCapacity: number; - idnexTotal: number; - }; - stopWords: Array | undefined; -} +// interface InfoReply { +// indexName: RedisCommandArgument; +// indexOptions: Array; +// indexDefinition: Record; +// attributes: Array>; +// numDocs: RedisCommandArgument; +// maxDocId: RedisCommandArgument; +// numTerms: RedisCommandArgument; +// numRecords: RedisCommandArgument; +// invertedSzMb: RedisCommandArgument; +// vectorIndexSzMb: RedisCommandArgument; +// totalInvertedIndexBlocks: RedisCommandArgument; +// offsetVectorsSzMb: RedisCommandArgument; +// docTableSizeMb: RedisCommandArgument; +// sortableValuesSizeMb: RedisCommandArgument; +// keyTableSizeMb: RedisCommandArgument; +// recordsPerDocAvg: RedisCommandArgument; +// bytesPerRecordAvg: RedisCommandArgument; +// offsetsPerTermAvg: RedisCommandArgument; +// offsetBitsPerRecordAvg: RedisCommandArgument; +// hashIndexingFailures: RedisCommandArgument; +// indexing: RedisCommandArgument; +// percentIndexed: RedisCommandArgument; +// gcStats: { +// bytesCollected: RedisCommandArgument; +// totalMsRun: RedisCommandArgument; +// totalCycles: RedisCommandArgument; +// averageCycleTimeMs: RedisCommandArgument; +// lastRunTimeMs: RedisCommandArgument; +// gcNumericTreesMissed: RedisCommandArgument; +// gcBlocksDenied: RedisCommandArgument; +// }; +// cursorStats: { +// globalIdle: number; +// globalTotal: number; +// indexCapacity: number; +// idnexTotal: number; +// }; +// stopWords: Array | undefined; +// } -export function transformReply(rawReply: InfoRawReply): InfoReply { - return { - indexName: rawReply[1], - indexOptions: rawReply[3], - indexDefinition: transformTuplesReply(rawReply[5]), - attributes: rawReply[7].map(attribute => transformTuplesReply(attribute)), - numDocs: rawReply[9], - maxDocId: rawReply[11], - numTerms: rawReply[13], - numRecords: rawReply[15], - invertedSzMb: rawReply[17], - vectorIndexSzMb: rawReply[19], - totalInvertedIndexBlocks: rawReply[21], - offsetVectorsSzMb: rawReply[23], - docTableSizeMb: rawReply[25], - sortableValuesSizeMb: rawReply[27], - keyTableSizeMb: rawReply[29], - recordsPerDocAvg: rawReply[31], - bytesPerRecordAvg: rawReply[33], - offsetsPerTermAvg: rawReply[35], - offsetBitsPerRecordAvg: rawReply[37], - hashIndexingFailures: rawReply[39], - indexing: rawReply[41], - percentIndexed: rawReply[43], - gcStats: { - bytesCollected: rawReply[45][1], - totalMsRun: rawReply[45][3], - totalCycles: rawReply[45][5], - averageCycleTimeMs: rawReply[45][7], - lastRunTimeMs: rawReply[45][9], - gcNumericTreesMissed: rawReply[45][11], - gcBlocksDenied: rawReply[45][13] - }, - cursorStats: { - globalIdle: rawReply[47][1], - globalTotal: rawReply[47][3], - indexCapacity: rawReply[47][5], - idnexTotal: rawReply[47][7] - }, - stopWords: rawReply[49] - }; -} +// export function transformReply(rawReply: InfoRawReply): InfoReply { +// return { +// indexName: rawReply[1], +// indexOptions: rawReply[3], +// indexDefinition: transformTuplesReply(rawReply[5]), +// attributes: rawReply[7].map(attribute => transformTuplesReply(attribute)), +// numDocs: rawReply[9], +// maxDocId: rawReply[11], +// numTerms: rawReply[13], +// numRecords: rawReply[15], +// invertedSzMb: rawReply[17], +// vectorIndexSzMb: rawReply[19], +// totalInvertedIndexBlocks: rawReply[21], +// offsetVectorsSzMb: rawReply[23], +// docTableSizeMb: rawReply[25], +// sortableValuesSizeMb: rawReply[27], +// keyTableSizeMb: rawReply[29], +// recordsPerDocAvg: rawReply[31], +// bytesPerRecordAvg: rawReply[33], +// offsetsPerTermAvg: rawReply[35], +// offsetBitsPerRecordAvg: rawReply[37], +// hashIndexingFailures: rawReply[39], +// indexing: rawReply[41], +// percentIndexed: rawReply[43], +// gcStats: { +// bytesCollected: rawReply[45][1], +// totalMsRun: rawReply[45][3], +// totalCycles: rawReply[45][5], +// averageCycleTimeMs: rawReply[45][7], +// lastRunTimeMs: rawReply[45][9], +// gcNumericTreesMissed: rawReply[45][11], +// gcBlocksDenied: rawReply[45][13] +// }, +// cursorStats: { +// globalIdle: rawReply[47][1], +// globalTotal: rawReply[47][3], +// indexCapacity: rawReply[47][5], +// idnexTotal: rawReply[47][7] +// }, +// stopWords: rawReply[49] +// }; +// } diff --git a/packages/search/lib/commands/PROFILE_AGGREGATE.ts b/packages/search/lib/commands/PROFILE_AGGREGATE.ts index b28e06ade91..ad490ec4771 100644 --- a/packages/search/lib/commands/PROFILE_AGGREGATE.ts +++ b/packages/search/lib/commands/PROFILE_AGGREGATE.ts @@ -1,29 +1,29 @@ -import { pushAggregatehOptions, AggregateOptions, transformReply as transformAggregateReply, AggregateRawReply } from './AGGREGATE'; -import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.'; +// import { pushAggregatehOptions, AggregateOptions, transformReply as transformAggregateReply, AggregateRawReply } from './AGGREGATE'; +// import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - index: string, - query: string, - options?: ProfileOptions & AggregateOptions -): Array { - const args = ['FT.PROFILE', index, 'AGGREGATE']; +// export function transformArguments( +// index: string, +// query: string, +// options?: ProfileOptions & AggregateOptions +// ): Array { +// const args = ['FT.PROFILE', index, 'AGGREGATE']; - if (options?.LIMITED) { - args.push('LIMITED'); - } +// if (options?.LIMITED) { +// args.push('LIMITED'); +// } - args.push('QUERY', query); - pushAggregatehOptions(args, options) - return args; -} +// args.push('QUERY', query); +// pushAggregatehOptions(args, options) +// return args; +// } -type ProfileAggeregateRawReply = ProfileRawReply; +// type ProfileAggeregateRawReply = ProfileRawReply; -export function transformReply(reply: ProfileAggeregateRawReply): ProfileReply { - return { - results: transformAggregateReply(reply[0]), - profile: transformProfile(reply[1]) - }; -} +// export function transformReply(reply: ProfileAggeregateRawReply): ProfileReply { +// return { +// results: transformAggregateReply(reply[0]), +// profile: transformProfile(reply[1]) +// }; +// } diff --git a/packages/search/lib/commands/PROFILE_SEARCH.ts b/packages/search/lib/commands/PROFILE_SEARCH.ts index 94fba8a6a54..626b3d47594 100644 --- a/packages/search/lib/commands/PROFILE_SEARCH.ts +++ b/packages/search/lib/commands/PROFILE_SEARCH.ts @@ -1,29 +1,29 @@ -import { SearchOptions, SearchRawReply, transformReply as transformSearchReply } from './SEARCH'; -import { pushSearchOptions, ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +// import { SearchOptions, SearchRawReply, transformReply as transformSearchReply } from './SEARCH'; +// import { pushSearchOptions, ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.'; +// import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments( - index: string, - query: string, - options?: ProfileOptions & SearchOptions -): RedisCommandArguments { - let args: RedisCommandArguments = ['FT.PROFILE', index, 'SEARCH']; +// export function transformArguments( +// index: string, +// query: string, +// options?: ProfileOptions & SearchOptions +// ): RedisCommandArguments { +// let args: RedisCommandArguments = ['FT.PROFILE', index, 'SEARCH']; - if (options?.LIMITED) { - args.push('LIMITED'); - } +// if (options?.LIMITED) { +// args.push('LIMITED'); +// } - args.push('QUERY', query); - return pushSearchOptions(args, options); -} +// args.push('QUERY', query); +// return pushSearchOptions(args, options); +// } -type ProfileSearchRawReply = ProfileRawReply; +// type ProfileSearchRawReply = ProfileRawReply; -export function transformReply(reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply { - return { - results: transformSearchReply(reply[0], withoutDocuments), - profile: transformProfile(reply[1]) - }; -} +// export function transformReply(reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply { +// return { +// results: transformSearchReply(reply[0], withoutDocuments), +// profile: transformProfile(reply[1]) +// }; +// } diff --git a/packages/time-series/lib/commands/INFO.ts b/packages/time-series/lib/commands/INFO.ts index 25ce3ef54ea..851d96d5713 100644 --- a/packages/time-series/lib/commands/INFO.ts +++ b/packages/time-series/lib/commands/INFO.ts @@ -1,82 +1,82 @@ -import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; +// import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; -export const FIRST_KEY_INDEX = 1; +// export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; +// export const IS_READ_ONLY = true; -export function transformArguments(key: string): Array { - return ['TS.INFO', key]; -} +// export function transformArguments(key: string): Array { +// return ['TS.INFO', key]; +// } -export type InfoRawReply = [ - 'totalSamples', - number, - 'memoryUsage', - number, - 'firstTimestamp', - number, - 'lastTimestamp', - number, - 'retentionTime', - number, - 'chunkCount', - number, - 'chunkSize', - number, - 'chunkType', - string, - 'duplicatePolicy', - TimeSeriesDuplicatePolicies | null, - 'labels', - Array<[name: string, value: string]>, - 'sourceKey', - string | null, - 'rules', - Array<[key: string, timeBucket: number, aggregationType: TimeSeriesAggregationType]> -]; +// export type InfoRawReply = [ +// 'totalSamples', +// number, +// 'memoryUsage', +// number, +// 'firstTimestamp', +// number, +// 'lastTimestamp', +// number, +// 'retentionTime', +// number, +// 'chunkCount', +// number, +// 'chunkSize', +// number, +// 'chunkType', +// string, +// 'duplicatePolicy', +// TimeSeriesDuplicatePolicies | null, +// 'labels', +// Array<[name: string, value: string]>, +// 'sourceKey', +// string | null, +// 'rules', +// Array<[key: string, timeBucket: number, aggregationType: TimeSeriesAggregationType]> +// ]; -export interface InfoReply { - totalSamples: number; - memoryUsage: number; - firstTimestamp: number; - lastTimestamp: number; - retentionTime: number; - chunkCount: number; - chunkSize: number; - chunkType: string; - duplicatePolicy: TimeSeriesDuplicatePolicies | null; - labels: Array<{ - name: string; - value: string; - }>; - sourceKey: string | null; - rules: Array<{ - key: string; - timeBucket: number; - aggregationType: TimeSeriesAggregationType - }>; -} +// export interface InfoReply { +// totalSamples: number; +// memoryUsage: number; +// firstTimestamp: number; +// lastTimestamp: number; +// retentionTime: number; +// chunkCount: number; +// chunkSize: number; +// chunkType: string; +// duplicatePolicy: TimeSeriesDuplicatePolicies | null; +// labels: Array<{ +// name: string; +// value: string; +// }>; +// sourceKey: string | null; +// rules: Array<{ +// key: string; +// timeBucket: number; +// aggregationType: TimeSeriesAggregationType +// }>; +// } -export function transformReply(reply: InfoRawReply): InfoReply { - return { - totalSamples: reply[1], - memoryUsage: reply[3], - firstTimestamp: reply[5], - lastTimestamp: reply[7], - retentionTime: reply[9], - chunkCount: reply[11], - chunkSize: reply[13], - chunkType: reply[15], - duplicatePolicy: reply[17], - labels: reply[19].map(([name, value]) => ({ - name, - value - })), - sourceKey: reply[21], - rules: reply[23].map(([key, timeBucket, aggregationType]) => ({ - key, - timeBucket, - aggregationType - })) - }; -} +// export function transformReply(reply: InfoRawReply): InfoReply { +// return { +// totalSamples: reply[1], +// memoryUsage: reply[3], +// firstTimestamp: reply[5], +// lastTimestamp: reply[7], +// retentionTime: reply[9], +// chunkCount: reply[11], +// chunkSize: reply[13], +// chunkType: reply[15], +// duplicatePolicy: reply[17], +// labels: reply[19].map(([name, value]) => ({ +// name, +// value +// })), +// sourceKey: reply[21], +// rules: reply[23].map(([key, timeBucket, aggregationType]) => ({ +// key, +// timeBucket, +// aggregationType +// })) +// }; +// } diff --git a/packages/time-series/lib/commands/INFO_DEBUG.ts b/packages/time-series/lib/commands/INFO_DEBUG.ts index 20d6ff5e242..f781593b1e6 100644 --- a/packages/time-series/lib/commands/INFO_DEBUG.ts +++ b/packages/time-series/lib/commands/INFO_DEBUG.ts @@ -1,57 +1,57 @@ -import { - transformArguments as transformInfoArguments, - InfoRawReply, - InfoReply, - transformReply as transformInfoReply -} from './INFO'; +// import { +// transformArguments as transformInfoArguments, +// InfoRawReply, +// InfoReply, +// transformReply as transformInfoReply +// } from './INFO'; -export { IS_READ_ONLY, FIRST_KEY_INDEX } from './INFO'; +// export { IS_READ_ONLY, FIRST_KEY_INDEX } from './INFO'; -export function transformArguments(key: string): Array { - const args = transformInfoArguments(key); - args.push('DEBUG'); - return args; -} +// export function transformArguments(key: string): Array { +// const args = transformInfoArguments(key); +// args.push('DEBUG'); +// return args; +// } -type InfoDebugRawReply = [ - ...InfoRawReply, - 'keySelfName', - string, - 'chunks', - Array<[ - 'startTimestamp', - number, - 'endTimestamp', - number, - 'samples', - number, - 'size', - number, - 'bytesPerSample', - string - ]> -]; +// type InfoDebugRawReply = [ +// ...InfoRawReply, +// 'keySelfName', +// string, +// 'chunks', +// Array<[ +// 'startTimestamp', +// number, +// 'endTimestamp', +// number, +// 'samples', +// number, +// 'size', +// number, +// 'bytesPerSample', +// string +// ]> +// ]; -interface InfoDebugReply extends InfoReply { - keySelfName: string; - chunks: Array<{ - startTimestamp: number; - endTimestamp: number; - samples: number; - size: number; - bytesPerSample: string; - }>; -} +// interface InfoDebugReply extends InfoReply { +// keySelfName: string; +// chunks: Array<{ +// startTimestamp: number; +// endTimestamp: number; +// samples: number; +// size: number; +// bytesPerSample: string; +// }>; +// } -export function transformReply(rawReply: InfoDebugRawReply): InfoDebugReply { - const reply = transformInfoReply(rawReply as unknown as InfoRawReply); - (reply as InfoDebugReply).keySelfName = rawReply[25]; - (reply as InfoDebugReply).chunks = rawReply[27].map(chunk => ({ - startTimestamp: chunk[1], - endTimestamp: chunk[3], - samples: chunk[5], - size: chunk[7], - bytesPerSample: chunk[9] - })); - return reply as InfoDebugReply; -} +// export function transformReply(rawReply: InfoDebugRawReply): InfoDebugReply { +// const reply = transformInfoReply(rawReply as unknown as InfoRawReply); +// (reply as InfoDebugReply).keySelfName = rawReply[25]; +// (reply as InfoDebugReply).chunks = rawReply[27].map(chunk => ({ +// startTimestamp: chunk[1], +// endTimestamp: chunk[3], +// samples: chunk[5], +// size: chunk[7], +// bytesPerSample: chunk[9] +// })); +// return reply as InfoDebugReply; +// } From e4007d74cba133459405dcbf54129798ac5327b7 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:10:41 -0500 Subject: [PATCH 249/325] npm update --- package-lock.json | 97 +++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f7fd004d05..38cb6724e21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2618,6 +2618,23 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -3154,12 +3171,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/es-set-tostringtag": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", @@ -4646,20 +4657,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/inquirer/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==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/internal-slot": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", @@ -5179,9 +5176,9 @@ } }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/isexe": { @@ -6126,20 +6123,6 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -6720,6 +6703,12 @@ "isarray": "0.0.1" } }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -7509,12 +7498,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8755,9 +8738,9 @@ "dev": true }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -8765,10 +8748,7 @@ "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/wrappy": { @@ -8991,6 +8971,23 @@ "node": ">=12" } }, + "packages/test-utils/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "packages/test-utils/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", From cb0fd4372bf73fa26bf553d69fa2629696b5234a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:12:46 -0500 Subject: [PATCH 250/325] Release client@2.0.0-next.3 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 5bea1dd5ff6..1308c8a0c74 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "2.0.0-next.2", + "version": "2.0.0-next.3", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 1a11456fd06ffb55047c2b8468474201829840ec Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:15:43 -0500 Subject: [PATCH 251/325] upgrade redis @redis/client dependency --- package-lock.json | 4 ++-- packages/redis/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38cb6724e21..7a181c7c7c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8887,7 +8887,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "2.0.0-next.2", + "version": "2.0.0-next.3", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -8929,7 +8929,7 @@ "license": "MIT", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "2.0.0-next.2", + "@redis/client": "2.0.0-next.3", "@redis/graph": "1.1.0", "@redis/json": "1.0.6", "@redis/search": "1.1.5", diff --git a/packages/redis/package.json b/packages/redis/package.json index 3c7e2a1907c..4636518a33e 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,7 +10,7 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "2.0.0-next.2", + "@redis/client": "2.0.0-next.3", "@redis/graph": "1.1.0", "@redis/json": "1.0.6", "@redis/search": "1.1.5", From 0e671ef64a05cd5d2dc628a1a95af4e8fd04b8a1 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:19:08 -0500 Subject: [PATCH 252/325] upgrade modules @redis/client peerDependency --- package-lock.json | 10 +++++----- packages/bloom/package.json | 2 +- packages/graph/package.json | 2 +- packages/json/package.json | 2 +- packages/search/package.json | 2 +- packages/time-series/package.json | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7a181c7c7c1..6b63f66c235 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8882,7 +8882,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" } }, "packages/client": { @@ -8910,7 +8910,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" } }, "packages/json": { @@ -8921,7 +8921,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" } }, "packages/redis": { @@ -8944,7 +8944,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" } }, "packages/test-utils": { @@ -9023,7 +9023,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" } } } diff --git a/packages/bloom/package.json b/packages/bloom/package.json index f76224f2016..be5869e992f 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/graph/package.json b/packages/graph/package.json index c0851e5734a..d8d5ad9499f 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/json/package.json b/packages/json/package.json index e52d12c9a95..3c2e0e69cc9 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -11,7 +11,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/search/package.json b/packages/search/package.json index 614ce51b44f..3490ea7be26 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/time-series/package.json b/packages/time-series/package.json index f19c69a64de..73875d80c70 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "*" + "@redis/client": "^2.0.0-next.3" }, "devDependencies": { "@redis/test-utils": "*" From bf97637919cdf131689d9f53fcaa009aa4dcdd88 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:30:21 -0500 Subject: [PATCH 253/325] release-it --workspaces-update=false --- packages/bloom/.release-it.json | 1 + packages/client/.release-it.json | 1 + packages/graph/.release-it.json | 1 + packages/json/.release-it.json | 1 + packages/search/.release-it.json | 1 + packages/time-series/.release-it.json | 1 + 6 files changed, 6 insertions(+) diff --git a/packages/bloom/.release-it.json b/packages/bloom/.release-it.json index 5d11263645f..3a27a088058 100644 --- a/packages/bloom/.release-it.json +++ b/packages/bloom/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } diff --git a/packages/client/.release-it.json b/packages/client/.release-it.json index 035124348ca..3ae247ad371 100644 --- a/packages/client/.release-it.json +++ b/packages/client/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } diff --git a/packages/graph/.release-it.json b/packages/graph/.release-it.json index 530d8f355d4..7797dd0b4dd 100644 --- a/packages/graph/.release-it.json +++ b/packages/graph/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } diff --git a/packages/json/.release-it.json b/packages/json/.release-it.json index ab495a49b13..8de2f3696e3 100644 --- a/packages/json/.release-it.json +++ b/packages/json/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } diff --git a/packages/search/.release-it.json b/packages/search/.release-it.json index 72cb1016ef4..3996a524e3b 100644 --- a/packages/search/.release-it.json +++ b/packages/search/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } diff --git a/packages/time-series/.release-it.json b/packages/time-series/.release-it.json index b5a7c08d24f..6c59e8955cf 100644 --- a/packages/time-series/.release-it.json +++ b/packages/time-series/.release-it.json @@ -5,6 +5,7 @@ "tagAnnotation": "Release ${tagName}" }, "npm": { + "versionArgs": ["--workspaces-update=false"], "publishArgs": ["--access", "public"] } } From 5aed71a7f8ef44314f6a9c42f5905503e2a9d726 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:31:00 -0500 Subject: [PATCH 254/325] Release bloom@2.0.0-next.1 --- packages/bloom/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index be5869e992f..36f089c3a85 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -1,6 +1,6 @@ { "name": "@redis/bloom", - "version": "1.2.0", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 8fb4a7ad61999ed77fd4456704cb2da9ac5de2f2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:31:26 -0500 Subject: [PATCH 255/325] Release graph@2.0.0-next.1 --- packages/graph/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graph/package.json b/packages/graph/package.json index d8d5ad9499f..d547ccc272f 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -1,6 +1,6 @@ { "name": "@redis/graph", - "version": "1.1.0", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 78fd21a0b36397e91f04920b229e0647b1442359 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:31:55 -0500 Subject: [PATCH 256/325] Release json@2.0.0-next.1 --- packages/json/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/json/package.json b/packages/json/package.json index 3c2e0e69cc9..c510bc0664d 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -1,6 +1,6 @@ { "name": "@redis/json", - "version": "1.0.6", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 46628ad79129ed4d95a3a0a14a44a19618e5a36b Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:32:25 -0500 Subject: [PATCH 257/325] Release search@2.0.0-next.1 --- packages/search/package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/search/package.json b/packages/search/package.json index 3490ea7be26..78974e4ef51 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -1,6 +1,6 @@ { "name": "@redis/search", - "version": "1.1.5", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", @@ -28,4 +28,5 @@ "keywords": [ "redis", "RediSearch" - ]} + ] +} From b2c363e0a2b7ac63493c9def23ec6fe804dd3e31 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:32:48 -0500 Subject: [PATCH 258/325] Release time-series@2.0.0-next.1 --- packages/time-series/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 73875d80c70..d16ce16f0c1 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -1,6 +1,6 @@ { "name": "@redis/time-series", - "version": "1.0.5", + "version": "2.0.0-next.1", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 247e8ddaf69ecc90e7c608c53ba0c272f70f7a65 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:33:38 -0500 Subject: [PATCH 259/325] upgrade ubpackages --- package-lock.json | 20 ++++++++++---------- packages/redis/package.json | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b63f66c235..fd873674acc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8876,7 +8876,7 @@ }, "packages/bloom": { "name": "@redis/bloom", - "version": "1.2.0", + "version": "2.0.0-next.1", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8904,7 +8904,7 @@ }, "packages/graph": { "name": "@redis/graph", - "version": "1.1.0", + "version": "2.0.0-next.1", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8915,7 +8915,7 @@ }, "packages/json": { "name": "@redis/json", - "version": "1.0.6", + "version": "2.0.0-next.1", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8928,17 +8928,17 @@ "version": "4.6.6", "license": "MIT", "dependencies": { - "@redis/bloom": "1.2.0", + "@redis/bloom": "2.0.0-next.1", "@redis/client": "2.0.0-next.3", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.6", - "@redis/search": "1.1.5", - "@redis/time-series": "1.0.5" + "@redis/graph": "2.0.0-next.1", + "@redis/json": "2.0.0-next.1", + "@redis/search": "2.0.0-next.1", + "@redis/time-series": "2.0.0-next.1" } }, "packages/search": { "name": "@redis/search", - "version": "1.1.5", + "version": "2.0.0-next.1", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -9017,7 +9017,7 @@ }, "packages/time-series": { "name": "@redis/time-series", - "version": "1.0.5", + "version": "2.0.0-next.1", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/redis/package.json b/packages/redis/package.json index 4636518a33e..ee8858aac5b 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -9,12 +9,12 @@ "dist/" ], "dependencies": { - "@redis/bloom": "1.2.0", + "@redis/bloom": "2.0.0-next.1", "@redis/client": "2.0.0-next.3", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.6", - "@redis/search": "1.1.5", - "@redis/time-series": "1.0.5" + "@redis/graph": "2.0.0-next.1", + "@redis/json": "2.0.0-next.1", + "@redis/search": "2.0.0-next.1", + "@redis/time-series": "2.0.0-next.1" }, "repository": { "type": "git", From 7a7c3308827335606c95601580428104b675bf74 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:34:07 -0500 Subject: [PATCH 260/325] Release redis@5.0.0-next.1 --- packages/redis/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/redis/package.json b/packages/redis/package.json index ee8858aac5b..fc94b886e68 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "4.6.6", + "version": "5.0.0-next.1", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 9803dbf90e4fc0dc935263f7ba1daaf15dc24601 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:38:55 -0500 Subject: [PATCH 261/325] fix redis build --- package-lock.json | 2 +- packages/redis/tsconfig.json | 15 +-------------- tsconfig.json | 2 ++ 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd873674acc..0d5d3aa2e55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8925,7 +8925,7 @@ } }, "packages/redis": { - "version": "4.6.6", + "version": "5.0.0-next.1", "license": "MIT", "dependencies": { "@redis/bloom": "2.0.0-next.1", diff --git a/packages/redis/tsconfig.json b/packages/redis/tsconfig.json index 0ffdfcf10bb..50da0ba733a 100644 --- a/packages/redis/tsconfig.json +++ b/packages/redis/tsconfig.json @@ -5,18 +5,5 @@ }, "include": [ "./index.ts" - ], - "references": [{ - "path": "./packages/client" - }, { - "path": "./packages/bloom" - }, { - "path": "./packages/graph" - }, { - "path": "./packages/json" - }, { - "path": "./packages/search" - }, { - "path": "./packages/time-series" - }] + ] } diff --git a/tsconfig.json b/tsconfig.json index 93f7f5de025..a578fefa54f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,7 @@ "path": "./packages/search" }, { "path": "./packages/time-series" + }, { + "path": "./packages/redis" }] } From aa30832304c5adb6c33a6849e658d60bfa2ca20c Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:39:37 -0500 Subject: [PATCH 262/325] Release redis@5.0.0-next.2 --- packages/redis/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/redis/package.json b/packages/redis/package.json index fc94b886e68..5a99cecde8a 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "5.0.0-next.1", + "version": "5.0.0-next.2", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 9126651bff0544a9215648c696ad89245acd286e Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 21:41:14 -0500 Subject: [PATCH 263/325] remove dist/tsconfig.tsbuildinfo from tarball --- package-lock.json | 2 +- packages/json/package.json | 3 ++- packages/redis/package.json | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d5d3aa2e55..133dee5727e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8925,7 +8925,7 @@ } }, "packages/redis": { - "version": "5.0.0-next.1", + "version": "5.0.0-next.2", "license": "MIT", "dependencies": { "@redis/bloom": "2.0.0-next.1", diff --git a/packages/json/package.json b/packages/json/package.json index c510bc0664d..0b3d810e0cc 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -5,7 +5,8 @@ "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" diff --git a/packages/redis/package.json b/packages/redis/package.json index 5a99cecde8a..8020dce02ac 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -6,7 +6,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "dependencies": { "@redis/bloom": "2.0.0-next.1", From 68785258fbff004cd9dc55e6da092f944cc12c8a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:28:48 -0500 Subject: [PATCH 264/325] change tsconfig module to CommonJS --- tsconfig.base.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.base.json b/tsconfig.base.json index 3bec460a0dd..bb779b5407d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,7 +1,7 @@ { "compilerOptions": { "lib": ["ES2023"], - "module": "ES2022", + "module": "CommonJS", "moduleResolution": "Node", "target": "ES2022", From 0568f46352a7f8075752689e6acddd3c2b40404a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:30:16 -0500 Subject: [PATCH 265/325] Release client@2.0.0-next.4 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 1308c8a0c74..7526e7e034e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "2.0.0-next.3", + "version": "2.0.0-next.4", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 74f6451792e56c2531d79329bfd4e6bd45b4b6ab Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:31:49 -0500 Subject: [PATCH 266/325] upgrade @redis/client --- package-lock.json | 14 +++++++------- packages/bloom/package.json | 3 ++- packages/graph/package.json | 2 +- packages/json/package.json | 2 +- packages/redis/package.json | 2 +- packages/search/package.json | 2 +- packages/time-series/package.json | 2 +- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 133dee5727e..416ee73a389 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8882,12 +8882,12 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" } }, "packages/client": { "name": "@redis/client", - "version": "2.0.0-next.3", + "version": "2.0.0-next.4", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -8910,7 +8910,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" } }, "packages/json": { @@ -8921,7 +8921,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" } }, "packages/redis": { @@ -8929,7 +8929,7 @@ "license": "MIT", "dependencies": { "@redis/bloom": "2.0.0-next.1", - "@redis/client": "2.0.0-next.3", + "@redis/client": "2.0.0-next.4", "@redis/graph": "2.0.0-next.1", "@redis/json": "2.0.0-next.1", "@redis/search": "2.0.0-next.1", @@ -8944,7 +8944,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" } }, "packages/test-utils": { @@ -9023,7 +9023,7 @@ "@redis/test-utils": "*" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" } } } diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 36f089c3a85..62303d6b6e0 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -2,6 +2,7 @@ "name": "@redis/bloom", "version": "2.0.0-next.1", "license": "MIT", + "type": "module", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", "files": [ @@ -12,7 +13,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/graph/package.json b/packages/graph/package.json index d547ccc272f..1133ce561e1 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/json/package.json b/packages/json/package.json index 0b3d810e0cc..eb0d3621883 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/redis/package.json b/packages/redis/package.json index 8020dce02ac..3fa49fb1611 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -11,7 +11,7 @@ ], "dependencies": { "@redis/bloom": "2.0.0-next.1", - "@redis/client": "2.0.0-next.3", + "@redis/client": "2.0.0-next.4", "@redis/graph": "2.0.0-next.1", "@redis/json": "2.0.0-next.1", "@redis/search": "2.0.0-next.1", diff --git a/packages/search/package.json b/packages/search/package.json index 78974e4ef51..bb87b83d4f1 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" }, "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/time-series/package.json b/packages/time-series/package.json index d16ce16f0c1..6f80bd2ab9a 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -12,7 +12,7 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "peerDependencies": { - "@redis/client": "^2.0.0-next.3" + "@redis/client": "^2.0.0-next.4" }, "devDependencies": { "@redis/test-utils": "*" From b3b3777147b4d8504420fbf2b40f662d9df77f93 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:33:25 -0500 Subject: [PATCH 267/325] Release bloom@2.0.0-next.2 --- packages/bloom/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 62303d6b6e0..2d732539ec1 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -1,6 +1,6 @@ { "name": "@redis/bloom", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "type": "module", "main": "./dist/lib/index.js", From 6d15036f86aac63cbaf0ab1447f01e7b328025bd Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:33:52 -0500 Subject: [PATCH 268/325] Release graph@2.0.0-next.2 --- packages/graph/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graph/package.json b/packages/graph/package.json index 1133ce561e1..0a6b728482d 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -1,6 +1,6 @@ { "name": "@redis/graph", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From c9c63740806c52a699ad2f8564d562d814b903dc Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:34:15 -0500 Subject: [PATCH 269/325] Release json@2.0.0-next.2 --- packages/json/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/json/package.json b/packages/json/package.json index eb0d3621883..12cfd674c4f 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -1,6 +1,6 @@ { "name": "@redis/json", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From bca283986ed4841eaebb0eccfc4160afce9309be Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:34:43 -0500 Subject: [PATCH 270/325] Release search@2.0.0-next.2 --- packages/search/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/search/package.json b/packages/search/package.json index bb87b83d4f1..67bb18da5d2 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -1,6 +1,6 @@ { "name": "@redis/search", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 6c9e1cc1df66cb7585dc8a60658ed67e5b186747 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:35:08 -0500 Subject: [PATCH 271/325] Release time-series@2.0.0-next.2 --- packages/time-series/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 6f80bd2ab9a..8f42844e95f 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -1,6 +1,6 @@ { "name": "@redis/time-series", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From c181ae9b7ac67d38b428e0b6f3d309db025c20d6 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:35:43 -0500 Subject: [PATCH 272/325] upgrade subpackages --- package-lock.json | 20 ++++++++++---------- packages/redis/package.json | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 416ee73a389..5d08b998807 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8876,7 +8876,7 @@ }, "packages/bloom": { "name": "@redis/bloom", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8904,7 +8904,7 @@ }, "packages/graph": { "name": "@redis/graph", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8915,7 +8915,7 @@ }, "packages/json": { "name": "@redis/json", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8928,17 +8928,17 @@ "version": "5.0.0-next.2", "license": "MIT", "dependencies": { - "@redis/bloom": "2.0.0-next.1", + "@redis/bloom": "2.0.0-next.2", "@redis/client": "2.0.0-next.4", - "@redis/graph": "2.0.0-next.1", - "@redis/json": "2.0.0-next.1", - "@redis/search": "2.0.0-next.1", - "@redis/time-series": "2.0.0-next.1" + "@redis/graph": "2.0.0-next.2", + "@redis/json": "2.0.0-next.2", + "@redis/search": "2.0.0-next.2", + "@redis/time-series": "2.0.0-next.2" } }, "packages/search": { "name": "@redis/search", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -9017,7 +9017,7 @@ }, "packages/time-series": { "name": "@redis/time-series", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" diff --git a/packages/redis/package.json b/packages/redis/package.json index 3fa49fb1611..32df531d11a 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,12 +10,12 @@ "!dist/tsconfig.tsbuildinfo" ], "dependencies": { - "@redis/bloom": "2.0.0-next.1", + "@redis/bloom": "2.0.0-next.2", "@redis/client": "2.0.0-next.4", - "@redis/graph": "2.0.0-next.1", - "@redis/json": "2.0.0-next.1", - "@redis/search": "2.0.0-next.1", - "@redis/time-series": "2.0.0-next.1" + "@redis/graph": "2.0.0-next.2", + "@redis/json": "2.0.0-next.2", + "@redis/search": "2.0.0-next.2", + "@redis/time-series": "2.0.0-next.2" }, "repository": { "type": "git", From 5fe2c6635c51145e184af0ea4ede8c6d2a17d7d4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:36:28 -0500 Subject: [PATCH 273/325] Release redis@5.0.0-next.3 --- packages/redis/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/redis/package.json b/packages/redis/package.json index 32df531d11a..b29572e196e 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "5.0.0-next.2", + "version": "5.0.0-next.3", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From f1294c59a29ab773c89151c5e22427d6ec5d125a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:36:45 -0500 Subject: [PATCH 274/325] package-lock.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 5d08b998807..baff6eb3be2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8925,7 +8925,7 @@ } }, "packages/redis": { - "version": "5.0.0-next.2", + "version": "5.0.0-next.3", "license": "MIT", "dependencies": { "@redis/bloom": "2.0.0-next.2", From 1049e3fa9446176d232086e1a7ecb1c043bee6d4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:38:33 -0500 Subject: [PATCH 275/325] remove "type": "module" from bloom --- packages/bloom/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 2d732539ec1..08a7dda00da 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -2,7 +2,6 @@ "name": "@redis/bloom", "version": "2.0.0-next.2", "license": "MIT", - "type": "module", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", "files": [ From 9d18a3c820999b25811702ba39f0ef9a5a7c902a Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:38:53 -0500 Subject: [PATCH 276/325] Release bloom@2.0.0-next.3 --- packages/bloom/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 08a7dda00da..6bdeb508218 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -1,6 +1,6 @@ { "name": "@redis/bloom", - "version": "2.0.0-next.2", + "version": "2.0.0-next.3", "license": "MIT", "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", From 392aa1d5eb4380e4d94bafa7486e00131e6ad9dc Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:39:23 -0500 Subject: [PATCH 277/325] upgrade @redis/bloom --- package-lock.json | 4 ++-- packages/redis/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index baff6eb3be2..d1244c15c42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8876,7 +8876,7 @@ }, "packages/bloom": { "name": "@redis/bloom", - "version": "2.0.0-next.2", + "version": "2.0.0-next.3", "license": "MIT", "devDependencies": { "@redis/test-utils": "*" @@ -8928,7 +8928,7 @@ "version": "5.0.0-next.3", "license": "MIT", "dependencies": { - "@redis/bloom": "2.0.0-next.2", + "@redis/bloom": "2.0.0-next.3", "@redis/client": "2.0.0-next.4", "@redis/graph": "2.0.0-next.2", "@redis/json": "2.0.0-next.2", diff --git a/packages/redis/package.json b/packages/redis/package.json index b29572e196e..06c17194471 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -10,7 +10,7 @@ "!dist/tsconfig.tsbuildinfo" ], "dependencies": { - "@redis/bloom": "2.0.0-next.2", + "@redis/bloom": "2.0.0-next.3", "@redis/client": "2.0.0-next.4", "@redis/graph": "2.0.0-next.2", "@redis/json": "2.0.0-next.2", From 6549fa49bf773f243396ddaae8f466c18bc224ea Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 9 Nov 2023 22:39:54 -0500 Subject: [PATCH 278/325] Release redis@5.0.0-next.4 --- packages/redis/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/redis/package.json b/packages/redis/package.json index 06c17194471..40cd3901483 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "5.0.0-next.3", + "version": "5.0.0-next.4", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 2ca6e1f33319128b6aac56921287e47488a19e4f Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 13 Nov 2023 18:14:12 -0500 Subject: [PATCH 279/325] add support for MULTI in ClientPool --- packages/client/lib/client/index.ts | 8 +++-- packages/client/lib/client/multi-command.ts | 20 +++++++---- packages/client/lib/client/pool.ts | 18 ++++++++-- packages/client/lib/cluster/index.ts | 38 ++++++-------------- packages/client/lib/cluster/multi-command.ts | 26 ++++++++++---- 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 72ce1f2ff7e..c4bc2654e30 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -794,8 +794,12 @@ export default class RedisClient< return execResult as Array; } - MULTI(): RedisClientMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { - return new (this as any).Multi(this); + MULTI() { + type Multi = new (...args: ConstructorParameters) => RedisClientMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING>;; + return new ((this as any).Multi as Multi)( + this._executeMulti.bind(this), + this._executePipeline.bind(this) + ); } multi = this.MULTI; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index c078193f64b..5f7679d2b17 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,8 +1,7 @@ import COMMANDS from '../commands'; -import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; +import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType, RedisMultiQueuedCommand } from '../multi-command'; import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; -import { RedisClientType } from '.'; type CommandSignature< REPLIES extends Array, @@ -84,6 +83,10 @@ export type RedisClientMultiCommandType< WithScripts ); +type ExecuteMulti = (commands: Array, selectedDB?: number) => Promise>; + +type ExecutePipeline = (commands: Array) => Promise>; + export default class RedisClientMultiCommand { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); @@ -149,11 +152,14 @@ export default class RedisClientMultiCommand { } private readonly _multi = new RedisMultiCommand(); - private readonly _client: RedisClientType; + private readonly _executeMulti: ExecuteMulti; + private readonly _executePipeline: ExecutePipeline; private _selectedDB?: number; - constructor(client: RedisClientType) { - this._client = client; + constructor(executeMulti: ExecuteMulti, executePipeline: ExecutePipeline) { + this._executeMulti = executeMulti; + this._executePipeline = executePipeline; + // this._client = client; } SELECT(db: number, transformReply?: TransformReply): this { @@ -173,7 +179,7 @@ export default class RedisClientMultiCommand { if (execAsPipeline) return this.execAsPipeline(); return this._multi.transformReplies( - await this._client._executeMulti(this._multi.queue, this._selectedDB) + await this._executeMulti(this._multi.queue, this._selectedDB) ) as MultiReplyType; } @@ -187,7 +193,7 @@ export default class RedisClientMultiCommand { if (this._multi.queue.length === 0) return [] as MultiReplyType; return this._multi.transformReplies( - await this._client._executePipeline(this._multi.queue) + await this._executePipeline(this._multi.queue) ) as MultiReplyType; } diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 357c89f45b2..5ea76e3e30b 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -6,6 +6,7 @@ import { DoublyLinkedNode, DoublyLinkedList, SinglyLinkedList } from './linked-l import { TimeoutError } from '../errors'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import { CommandOptions } from './commands-queue'; +import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; export interface RedisPoolOptions { /** @@ -118,7 +119,6 @@ export class RedisClientPool< clientOptions?: RedisClientOptions, options?: Partial ) { - // @ts-ignore const Pool = attachConfig({ BaseClass: RedisClientPool, commands: COMMANDS, @@ -129,6 +129,8 @@ export class RedisClientPool< config: clientOptions }); + Pool.prototype.Multi = RedisClientMultiCommand.extend(clientOptions); + // returning a "proxy" to prevent the namespaces.self to leak between "proxies" return Object.create( new Pool( @@ -327,8 +329,8 @@ export class RedisClientPool< this._returnClient(node); } - execute(fn: PoolTask): Promise { - return new Promise((resolve, reject) => { + execute(fn: PoolTask) { + return new Promise>((resolve, reject) => { const client = this._idleClients.shift(), { tail } = this._tasksQueue; if (!client) { @@ -425,6 +427,16 @@ export class RedisClientPool< return this.execute(client => client.executeScript(script, args, options)); } + MULTI() { + type Multi = new (...args: ConstructorParameters) => RedisClientMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING>; + return new ((this as any).Multi as Multi)( + (commands, selectedDB) => this.execute(client => client._executeMulti(commands, selectedDB)), + commands => this.execute(client => client._executePipeline(commands)) + ); + } + + multi = this.MULTI; + async close() { if (this._isClosing) return; // TODO: throw err? if (!this._isOpen) return; // TODO: throw err? diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 0b7cd210f47..f572bbac5ce 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -504,33 +504,17 @@ export default class RedisCluster< ); } - /** - * @internal - */ - async _executePipeline( - firstKey: RedisArgument | undefined, - isReadonly: boolean | undefined, - commands: Array - ) { - const client = await this._slots.getClient(firstKey, isReadonly); - return client._executePipeline(commands); - } - - /** - * @internal - */ - async _executeMulti( - firstKey: RedisArgument | undefined, - isReadonly: boolean | undefined, - commands: Array - ) { - const client = await this._slots.getClient(firstKey, isReadonly); - return client._executeMulti(commands); - } - - MULTI(routing?: RedisArgument): RedisClusterMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { - return new (this as any).Multi( - this, + MULTI(routing?: RedisArgument) { + type Multi = new (...args: ConstructorParameters) => RedisClusterMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING>; + return new ((this as any).Multi as Multi)( + async (firstKey, isReadonly, commands) => { + const client = await this._slots.getClient(firstKey, isReadonly); + return client._executeMulti(commands); + }, + async (firstKey, isReadonly, commands) => { + const client = await this._slots.getClient(firstKey, isReadonly); + return client._executePipeline(commands); + }, routing ); } diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index d036256247b..531c00f1d5e 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -1,8 +1,8 @@ import COMMANDS from '../commands'; -import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; +import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType, RedisMultiQueuedCommand } from '../multi-command'; import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping, RedisArgument } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; -import RedisCluster, { RedisClusterType } from '.'; +import RedisCluster from '.'; type CommandSignature< REPLIES extends Array, @@ -84,6 +84,12 @@ export type RedisClusterMultiCommandType< WithScripts ); +export type ClusterMultiExecute = ( + firstKey: RedisArgument | undefined, + isReadonly: boolean | undefined, + commands: Array +) => Promise>; + export default class RedisClusterMultiCommand { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); @@ -181,12 +187,18 @@ export default class RedisClusterMultiCommand { } private readonly _multi = new RedisMultiCommand(); - private readonly _cluster: RedisClusterType; + private readonly _executeMulti: ClusterMultiExecute; + private readonly _executePipeline: ClusterMultiExecute; private _firstKey: RedisArgument | undefined; private _isReadonly: boolean | undefined = true; - constructor(cluster: RedisClusterType, routing: RedisArgument | undefined) { - this._cluster = cluster; + constructor( + executeMulti: ClusterMultiExecute, + executePipeline: ClusterMultiExecute, + routing: RedisArgument | undefined + ) { + this._executeMulti = executeMulti; + this._executePipeline = executePipeline; this._firstKey = routing; } @@ -213,7 +225,7 @@ export default class RedisClusterMultiCommand { if (execAsPipeline) return this.execAsPipeline(); return this._multi.transformReplies( - await this._cluster._executeMulti( + await this._executeMulti( this._firstKey, this._isReadonly, this._multi.queue @@ -231,7 +243,7 @@ export default class RedisClusterMultiCommand { if (this._multi.queue.length === 0) return [] as MultiReplyType; return this._multi.transformReplies( - await this._cluster._executePipeline( + await this._executePipeline( this._firstKey, this._isReadonly, this._multi.queue From f8c24c0edd6a111768d2cd8a2f834f8ba2b6d498 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 14 Nov 2023 20:08:22 -0500 Subject: [PATCH 280/325] 6748ba5de33441d0bc3046f9eaf185769f4f34bf --- packages/client/lib/client/socket.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index a82e9be35a3..01968c13036 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -217,10 +217,11 @@ export default class RedisSocket extends EventEmitter { } private _onSocketError(err: Error): void { + const wasReady = this._isReady; this._isReady = false; this.emit('error', err); - if (!this._isOpen || typeof this._shouldReconnect(0, err) !== 'number') return; + if (!wasReady || !this._isOpen || typeof this._shouldReconnect(0, err) !== 'number') return; this.emit('reconnecting'); this._connect().catch(() => { From 52e8c50dc8d51d6a6edd36d18b7444ef27274a0c Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 20 Nov 2023 12:47:13 -0500 Subject: [PATCH 281/325] add testWithClientPool and first pool test --- packages/client/lib/client/pool.spec.ts | 11 ++++ packages/test-utils/lib/index.ts | 72 ++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 packages/client/lib/client/pool.spec.ts diff --git a/packages/client/lib/client/pool.spec.ts b/packages/client/lib/client/pool.spec.ts new file mode 100644 index 00000000000..8ab4bb556b2 --- /dev/null +++ b/packages/client/lib/client/pool.spec.ts @@ -0,0 +1,11 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; + +describe.only('RedisClientPool', () => { + testUtils.testWithClientPool('sendCommand', async pool => { + assert.equal( + await pool.sendCommand(['PING']), + 'PONG' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 5343beb91b4..87ba34db7ef 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -8,6 +8,9 @@ import { createClient, RedisClientOptions, RedisClientType, + RedisPoolOptions, + RedisClientPoolType, + createClientPool, createCluster, RedisClusterOptions, RedisClusterType @@ -23,6 +26,7 @@ interface TestUtilsConfig { } interface CommonTestOptions { + serverArguments: Array; minimumDockerVersion?: Array; } @@ -33,11 +37,21 @@ interface ClientTestOptions< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > extends CommonTestOptions { - serverArguments: Array; clientOptions?: Partial>; disableClientSetup?: boolean; } +interface ClientPoolTestOptions< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends CommonTestOptions { + clientOptions?: Partial>; + poolOptions?: RedisPoolOptions; +} + interface ClusterTestOptions< M extends RedisModules, F extends RedisFunctions, @@ -46,7 +60,6 @@ interface ClusterTestOptions< TYPE_MAPPING extends TypeMapping // POLICIES extends CommandPolicies > extends CommonTestOptions { - serverArguments: Array; clusterConfiguration?: Partial>; numberOfMasters?: number; numberOfReplicas?: number; @@ -164,9 +177,9 @@ export default class TestUtils { if (!dockerPromise) return this.skip(); const client = createClient({ - ...options?.clientOptions, + ...options.clientOptions, socket: { - ...options?.clientOptions?.socket, + ...options.clientOptions?.socket, // TODO // @ts-ignore port: (await dockerPromise).port @@ -191,6 +204,53 @@ export default class TestUtils { }); } + testWithClientPool< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >( + title: string, + fn: (client: RedisClientPoolType) => unknown, + options: ClientPoolTestOptions + ): void { + let dockerPromise: ReturnType; + if (this.isVersionGreaterThan(options.minimumDockerVersion)) { + const dockerImage = this.#DOCKER_IMAGE; + before(function () { + this.timeout(30000); + + dockerPromise = spawnRedisServer(dockerImage, options.serverArguments); + return dockerPromise; + }); + } + + it(title, async function () { + if (!dockerPromise) return this.skip(); + + const pool = createClientPool({ + ...options.clientOptions, + socket: { + ...options.clientOptions?.socket, + // TODO + // @ts-ignore + port: (await dockerPromise).port + } + }, options.poolOptions); + + await pool.connect(); + + try { + await pool.flushAll(); + await fn(pool); + } finally { + await pool.flushAll(); + pool.destroy(); + } + }); + } + static async #clusterFlushAll< M extends RedisModules, F extends RedisFunctions, @@ -228,8 +288,8 @@ export default class TestUtils { dockersPromise = spawnRedisCluster({ ...dockerImage, - numberOfMasters: options?.numberOfMasters, - numberOfReplicas: options?.numberOfReplicas + numberOfMasters: options.numberOfMasters, + numberOfReplicas: options.numberOfReplicas }, options.serverArguments); return dockersPromise; }); From 3ca33b8b80323aa4f2d0aada4dc37bad923616d0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 20 Nov 2023 12:47:22 -0500 Subject: [PATCH 282/325] remove unused import --- packages/client/lib/cluster/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index f572bbac5ce..a350eb37f59 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -6,7 +6,6 @@ import { EventEmitter } from 'node:events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command'; -import { RedisMultiQueuedCommand } from '../multi-command'; import { PubSubListener } from '../client/pub-sub'; import { ErrorReply } from '../errors'; From 520441704b4f3c354e63848c6111a0f914b23a62 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 20 Nov 2023 13:15:40 -0500 Subject: [PATCH 283/325] fix multi "generic" type, some docs --- docs/clustering.md | 1 + docs/transactions.md | 29 ++++++++++++++++++ packages/client/lib/multi-command.ts | 5 ++-- packages/redis/README.md | 44 +++++++++++++++++++++------- 4 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 docs/transactions.md diff --git a/docs/clustering.md b/docs/clustering.md index 38419b06cdd..43cea373a02 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -40,6 +40,7 @@ await cluster.close(); ## Auth with password and username Specifying the password in the URL or a root node will only affect the connection to that specific node. In case you want to set the password for all the connections being created from a cluster instance, use the `defaults` option. + ```javascript createCluster({ rootNodes: [{ diff --git a/docs/transactions.md b/docs/transactions.md new file mode 100644 index 00000000000..f71eb50b374 --- /dev/null +++ b/docs/transactions.md @@ -0,0 +1,29 @@ +# [Transactions](https://redis.io/docs/interact/transactions/) ([`MULTI`](https://redis.io/commands/multi/)/[`EXEC`](https://redis.io/commands/exec/)) + +Start a [transaction](https://redis.io/docs/interact/transactions/) by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results: + +```javascript +const [setReply, getReply] = await client.multi() + .set('key', 'value') + .get('another-key') + .exec(); +``` + +## `exec<'typed'>()`/`execTyped()` + +A transaction invoked with `.exec<'typed'>`/`execTyped()` will return types appropriate to the commands in the transaction: + +```javascript +const multi = client.multi().ping(); +await multi.exec(); // Array +await multi.exec<'typed'>(); // [string] +await multi.execTyped(); // [string] +``` + +> :warning: this only works when all the commands are invoked in a single "call chain" + +## [`WATCH`](https://redis.io/commands/watch/) + +You can also [watch](https://redis.io/docs/interact/transactions/#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. + +The `WATCH` state is stored on the connection (by the server). In case you need to run multiple `WATCH` & `MULTI` in parallel you'll need to use a [pool](./pool.md). diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 54b4bd22728..7396b1219a5 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -1,6 +1,5 @@ -import { CommandArguments, RedisScript, TransformReply } from './RESP/types'; +import { CommandArguments, RedisScript, ReplyUnion, TransformReply } from './RESP/types'; -// TODO: enum? export type MULTI_REPLY = { GENERIC: 'generic'; TYPED: 'typed'; @@ -8,7 +7,7 @@ export type MULTI_REPLY = { export type MultiReply = MULTI_REPLY[keyof MULTI_REPLY]; -export type MultiReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; +export type MultiReplyType = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array; export interface RedisMultiQueuedCommand { args: CommandArguments; diff --git a/packages/redis/README.md b/packages/redis/README.md index 4a57dbd7b15..4d20fd1cd78 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -55,7 +55,9 @@ createClient({ 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). -To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). +To client exposes 2 `boolean`s that track the client state: +1. `isOpen` - the client is either connecting or connected. +2. `isReady` - the client is connected and ready to send ### Redis Commands @@ -97,19 +99,17 @@ await client.hVals('key'); // ['value1', 'value2'] If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`: ```javascript -await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' - +await client.sendCommand(['SET', 'key', 'value', 'EX', '10', 'NX']); // 'OK' await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] ``` ### Disconnecting -There are two functions that disconnect a client from the Redis server. In most scenarios you should use `.close()` to ensure that pending commands are sent to Redis before closing a connection. - -> :warning: The `.quit()` and `.disconnect()` methods have been deprecated in v5. For more details, refer to the [v4-to-v5 guide](../../docs/v4-to-v5.md#quit-vs-disconnect). - #### `.close()` +Gracefully close a client's connection to Redis. +Wait for commands in process, but reject any new commands. + ```javascript const [ping, get] = await Promise.all([ client.ping(), @@ -124,11 +124,34 @@ try { } ``` -> :warning: `.close` is just like `.quit()` which was depreacted in Redis 7.2. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information. +> `.close()` is just like `.quit()` which was depreacted v5. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information. #### `.destroy()` -Forcibly close a client's connection to Redis immediately. Calling `destroy` will not send further pending commands to the Redis server, or wait for or parse outstanding responses. +Forcibly close a client's connection to Redis. + +```javascript +try { + const promise = Promise.all([ + client.ping(), + client.get('key') + ]); + + client.destroy(); + + await promise; +} catch (err) { + // DisconnectsClientError +} + +try { + await client.get('key'); +} catch (err) { + // ClientClosedError +} +``` + +> `.destroy()` is just like `.disconnect()` which was depreated in v5. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information. ### Auto-Pipelining @@ -167,7 +190,7 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each ### Links -- [Multi](../../docs/multi.md). +- [Transactions (`MULTI`/`EXEC`)](../../docs/transactions.md). - [Pub/Sub](../../docs/pub-sub.md). - [Scan Iterators](../../docs/scan-iterators.md). - [Programmability](../../docs/programmability.md). @@ -181,6 +204,7 @@ Node Redis is supported with the following versions of Redis: | Version | Supported | |---------|--------------------| +| 7.2.z | :heavy_check_mark: | | 7.0.z | :heavy_check_mark: | | 6.2.z | :heavy_check_mark: | | 6.0.z | :heavy_check_mark: | From d8cb5de8b1268f8ec0c5df91d15c7d7f73374073 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 10:02:07 -0500 Subject: [PATCH 284/325] fix #2563 - add support for MONITOR --- packages/client/lib/RESP/decoder.ts | 58 +++++++++-------- packages/client/lib/client/commands-queue.ts | 68 +++++++++++++++----- packages/client/lib/client/index.spec.ts | 64 +++++++++++++++++- packages/client/lib/client/index.ts | 31 ++++++++- 4 files changed, 177 insertions(+), 44 deletions(-) diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 2fbadd0f5ee..7e2a4885873 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -49,14 +49,18 @@ interface DecoderOptions { } export class Decoder { - private readonly _config; - + onReply; + onErrorReply; + onPush; + getTypeMapping; private _cursor = 0; - private _next; constructor(config: DecoderOptions) { - this._config = config; + this.onReply = config.onReply; + this.onErrorReply = config.onErrorReply; + this.onPush = config.onPush; + this.getTypeMapping = config.getTypeMapping; } reset() { @@ -99,102 +103,102 @@ export class Decoder { private _decodeTypeValue(type, chunk) { switch (type) { case RESP_TYPES.NULL: - this._config.onReply(this._decodeNull()); + this.onReply(this._decodeNull()); return false; case RESP_TYPES.BOOLEAN: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeBoolean(chunk) ); case RESP_TYPES.NUMBER: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeNumber( - this._config.getTypeMapping()[RESP_TYPES.NUMBER], + this.getTypeMapping()[RESP_TYPES.NUMBER], chunk ) ); case RESP_TYPES.BIG_NUMBER: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeBigNumber( - this._config.getTypeMapping()[RESP_TYPES.BIG_NUMBER], + this.getTypeMapping()[RESP_TYPES.BIG_NUMBER], chunk ) ); case RESP_TYPES.DOUBLE: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeDouble( - this._config.getTypeMapping()[RESP_TYPES.DOUBLE], + this.getTypeMapping()[RESP_TYPES.DOUBLE], chunk ) ); case RESP_TYPES.SIMPLE_STRING: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeSimpleString( - this._config.getTypeMapping()[RESP_TYPES.SIMPLE_STRING], + this.getTypeMapping()[RESP_TYPES.SIMPLE_STRING], chunk ) ); case RESP_TYPES.BLOB_STRING: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeBlobString( - this._config.getTypeMapping()[RESP_TYPES.BLOB_STRING], + this.getTypeMapping()[RESP_TYPES.BLOB_STRING], chunk ) ); case RESP_TYPES.VERBATIM_STRING: return this._handleDecodedValue( - this._config.onReply, + this.onReply, this._decodeVerbatimString( - this._config.getTypeMapping()[RESP_TYPES.VERBATIM_STRING], + this.getTypeMapping()[RESP_TYPES.VERBATIM_STRING], chunk ) ); case RESP_TYPES.SIMPLE_ERROR: return this._handleDecodedValue( - this._config.onErrorReply, + this.onErrorReply, this._decodeSimpleError(chunk) ); case RESP_TYPES.BLOB_ERROR: return this._handleDecodedValue( - this._config.onErrorReply, + this.onErrorReply, this._decodeBlobError(chunk) ); case RESP_TYPES.ARRAY: return this._handleDecodedValue( - this._config.onReply, - this._decodeArray(this._config.getTypeMapping(), chunk) + this.onReply, + this._decodeArray(this.getTypeMapping(), chunk) ); case RESP_TYPES.SET: return this._handleDecodedValue( - this._config.onReply, - this._decodeSet(this._config.getTypeMapping(), chunk) + this.onReply, + this._decodeSet(this.getTypeMapping(), chunk) ); case RESP_TYPES.MAP: return this._handleDecodedValue( - this._config.onReply, - this._decodeMap(this._config.getTypeMapping(), chunk) + this.onReply, + this._decodeMap(this.getTypeMapping(), chunk) ); case RESP_TYPES.PUSH: return this._handleDecodedValue( - this._config.onPush, + this.onPush, this._decodeArray(PUSH_TYPE_MAPPING, chunk) ); diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 5a25674a7ee..dcfbd335fe6 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -5,6 +5,7 @@ import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; import { EventEmitter } from 'node:stream'; +import { MonitorCallback } from '.'; export interface CommandOptions { chainId?: symbol; @@ -23,6 +24,7 @@ export interface CommandToWrite extends CommandWaitingForReply { signal: AbortSignal; listener: () => unknown; }; + resolveOnWrite?: boolean; } interface CommandWaitingForReply { @@ -151,8 +153,33 @@ export default class RedisCommandsQueue { } }); } + + async monitor(callback: MonitorCallback, typeMapping: TypeMapping = {}, asap = false) { + await this.addCommand( + ['MONITOR'], + { asap }, + true + ); + + const { onReply, getTypeMapping } = this.decoder; + this.decoder.onReply = callback; + this.decoder.getTypeMapping = () => typeMapping; + return () => new Promise(async resolve => { + await this.addCommand(['RESET'], undefined, true); + this.decoder.onReply = (reply: string) => { + if (reply !== 'RESET') return callback(reply); + this.decoder.onReply = onReply; + this.decoder.getTypeMapping = getTypeMapping; + resolve(); + }; + }); + } - addCommand(args: CommandArguments, options?: CommandOptions): Promise { + addCommand( + args: CommandArguments, + options?: CommandOptions, + resolveOnWrite?: boolean + ): Promise { if (this._maxLength && this._toWrite.length + this._waitingForReply.length >= this._maxLength) { return Promise.reject(new Error('The queue is full')); } else if (options?.abortSignal?.aborted) { @@ -164,10 +191,12 @@ export default class RedisCommandsQueue { const value: CommandToWrite = { args, chainId: options?.chainId, - typeMapping: options?.typeMapping, + abort: undefined, + resolveOnWrite, resolve, reject, - abort: undefined + channelsCounter: undefined, + typeMapping: options?.typeMapping }; const signal = options?.abortSignal; @@ -245,16 +274,19 @@ export default class RedisCommandsQueue { return new Promise((resolve, reject) => { this._toWrite.push({ args: command.args, - channelsCounter: command.channelsCounter, - typeMapping: PUSH_TYPE_MAPPING, - resolve: () => { + chainId: undefined, + abort: undefined, + resolveOnWrite: false, + resolve() { command.resolve(); resolve(); }, - reject: err => { + reject(err) { command.reject?.(); reject(err); - } + }, + channelsCounter: command.channelsCounter, + typeMapping: PUSH_TYPE_MAPPING }); }); } @@ -279,13 +311,19 @@ export default class RedisCommandsQueue { RedisCommandsQueue._removeAbortListener(toSend); toSend.abort = undefined; } - - // TODO reuse `toSend` or create new object? - (toSend as any).args = undefined; - (toSend as any).chainId = undefined; - - this._waitingForReply.push(toSend); - this._chainInExecution = toSend.chainId; + + if (toSend.resolveOnWrite) { + toSend.resolve(); + } else { + // TODO reuse `toSend` or create new object? + (toSend as any).args = undefined; + + this._chainInExecution = toSend.chainId; + toSend.chainId = undefined; + + this._waitingForReply.push(toSend); + } + yield encoded; toSend = this._toWrite.shift(); } diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 60e776b0ddb..cfdfba0455b 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -5,7 +5,7 @@ import RedisClient, { RedisClientType } from '.'; // import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; -// import { spy } from 'sinon'; +import { spy } from 'sinon'; import { once } from 'node:events'; // import { ClientKillFilters } from '../commands/CLIENT_KILL'; // import { promisify } from 'node:util'; @@ -741,4 +741,66 @@ describe('Client', () => { // }, // disableClientSetup: true // }); + + describe('MONITOR', () => { + testUtils.testWithClient('should be able to monitor commands', async client => { + const duplicate = await client.duplicate().connect(), + listener = spy(message => assert.equal(typeof message, 'string')); + await duplicate.monitor(listener); + + try { + await Promise.all([ + waitTillBeenCalled(listener), + client.ping() + ]); + } finally { + duplicate.destroy(); + } + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should keep monitoring after reconnection', async client => { + const duplicate = await client.duplicate().connect(), + listener = spy(message => assert.equal(typeof message, 'string')); + await duplicate.monitor(listener); + + try { + await Promise.all([ + once(duplicate, 'error'), + client.clientKill({ + filter: 'SKIPME', + skipMe: true + }) + ]); + await Promise.all([ + waitTillBeenCalled(listener), + client.ping() + ]); + } finally { + duplicate.destroy(); + } + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should be able to go back to "normal mode"', async client => { + const off = await client.monitor(() => {}); + await off(); + await assert.doesNotReject(client.ping()); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should respect type mapping', async client => { + const duplicate = await client.duplicate().connect(), + listener = spy(message => assert.ok(message instanceof Buffer)); + await duplicate.withTypeMapping({ + [RESP_TYPES.SIMPLE_STRING]: Buffer + }).monitor(listener); + + try { + await Promise.all([ + waitTillBeenCalled(listener), + client.ping() + ]); + } finally { + duplicate.destroy(); + } + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index c4bc2654e30..69b5ec6054b 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -7,7 +7,7 @@ import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchErr import { URL } from 'node:url'; import { TcpSocketConnectOpts } from 'node:net'; import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; -import { Command, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types'; +import { Command, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument, ReplyWithTypeMapping, SimpleStringReply } from '../RESP/types'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; import HELLO, { HelloOptions } from '../commands/HELLO'; @@ -138,6 +138,8 @@ interface ScanIteratorOptions { cursor?: RedisArgument; } +export type MonitorCallback = (reply: ReplyWithTypeMapping) => unknown; + export default class RedisClient< M extends RedisModules, F extends RedisFunctions, @@ -276,6 +278,7 @@ export default class RedisClient< private readonly _socket: RedisSocket; private readonly _queue: RedisCommandsQueue; private _selectedDB = 0; + private _monitorCallback?: MonitorCallback; private _commandOptions?: CommandOptions; get options(): RedisClientOptions | undefined { @@ -334,6 +337,16 @@ export default class RedisClient< const socketInitiator = async (): Promise => { const promises = []; + if (this._monitorCallback) { + promises.push( + this._queue.monitor( + this._monitorCallback, + this._commandOptions?.typeMapping, + true + ) + ); + } + if (this._selectedDB !== 0) { promises.push( this._queue.addCommand( @@ -855,6 +868,22 @@ export default class RedisClient< } while (cursor !== '0'); } + async MONITOR(callback: MonitorCallback) { + const promise = this._queue.monitor(callback, this._commandOptions?.typeMapping); + this._scheduleWrite(); + + const off = await promise; + this._monitorCallback = callback; + return async () => { + const promise = off(); + this._scheduleWrite(); + await promise; + this._monitorCallback = undefined; + }; + } + + monitor = this.MONITOR; + /** * @deprecated use .close instead */ From f804b0949d21acee37522b7d2b5ce4d5c7396e10 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 11:44:00 -0500 Subject: [PATCH 285/325] use asap fro pubsub resubscribe --- packages/client/lib/client/commands-queue.ts | 16 ++++++++-------- packages/client/lib/client/index.ts | 7 +------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index dcfbd335fe6..8806a50a9d1 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -223,7 +223,7 @@ export default class RedisCommandsQueue { listener: PubSubListener, returnBuffers?: T ) { - return this._pushPubSubCommand( + return this._addPubSubCommand( this._pubSub.subscribe(type, channels, listener, returnBuffers) ); } @@ -234,7 +234,7 @@ export default class RedisCommandsQueue { listener?: PubSubListener, returnBuffers?: T ) { - return this._pushPubSubCommand( + return this._addPubSubCommand( this._pubSub.unsubscribe(type, channels, listener, returnBuffers) ); } @@ -244,7 +244,7 @@ export default class RedisCommandsQueue { if (!commands.length) return; return Promise.all( - commands.map(command => this._pushPubSubCommand(command)) + commands.map(command => this._addPubSubCommand(command, true)) ); } @@ -253,13 +253,13 @@ export default class RedisCommandsQueue { channel: string, listeners: ChannelListeners ) { - return this._pushPubSubCommand( + return this._addPubSubCommand( this._pubSub.extendChannelListeners(type, channel, listeners) ); } extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this._pushPubSubCommand( + return this._addPubSubCommand( this._pubSub.extendTypeListeners(type, listeners) ); } @@ -268,11 +268,11 @@ export default class RedisCommandsQueue { return this._pubSub.getTypeListeners(type); } - private _pushPubSubCommand(command: PubSubCommand) { + private _addPubSubCommand(command: PubSubCommand, asap = false) { if (command === undefined) return; return new Promise((resolve, reject) => { - this._toWrite.push({ + (asap ? this._toWrite.unshift : this._toWrite.push)({ args: command.args, chainId: undefined, abort: undefined, @@ -287,7 +287,7 @@ export default class RedisCommandsQueue { }, channelsCounter: command.channelsCounter, typeMapping: PUSH_TYPE_MAPPING - }); + }); }); } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 69b5ec6054b..e47a5004208 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -335,7 +335,7 @@ export default class RedisClient< private _initiateSocket(): RedisSocket { const socketInitiator = async (): Promise => { - const promises = []; + const promises = [this._queue.resubscribe()]; if (this._monitorCallback) { promises.push( @@ -408,11 +408,6 @@ export default class RedisClient< } } - const resubscribePromise = this._queue.resubscribe(); - if (resubscribePromise) { - promises.push(resubscribePromise); - } - if (promises.length) { this._write(); await Promise.all(promises); From 0b3d5fa9e028d69d5100c2f085858203767e1643 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 11:44:16 -0500 Subject: [PATCH 286/325] remove .only from pool tests --- packages/client/lib/client/pool.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/pool.spec.ts b/packages/client/lib/client/pool.spec.ts index 8ab4bb556b2..8fc7a258df9 100644 --- a/packages/client/lib/client/pool.spec.ts +++ b/packages/client/lib/client/pool.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL } from '../test-utils'; -describe.only('RedisClientPool', () => { +describe('RedisClientPool', () => { testUtils.testWithClientPool('sendCommand', async pool => { assert.equal( await pool.sendCommand(['PING']), From b99502b8741edf528e07e49569ce2c079ad8d3ff Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 12:05:12 -0500 Subject: [PATCH 287/325] fix client pubsub and uncomment tests --- packages/client/lib/client/commands-queue.ts | 8 +- packages/client/lib/client/index.spec.ts | 381 +++++++++---------- packages/client/lib/client/linked-list.ts | 6 + 3 files changed, 197 insertions(+), 198 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 8806a50a9d1..22ea1aba96a 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -211,9 +211,7 @@ export default class RedisCommandsQueue { signal.addEventListener('abort', value.abort.listener, { once: true }); } - node = options?.asap ? - this._toWrite.unshift(value) : - this._toWrite.push(value); + node = this._toWrite.add(value, options?.asap); }); } @@ -272,7 +270,7 @@ export default class RedisCommandsQueue { if (command === undefined) return; return new Promise((resolve, reject) => { - (asap ? this._toWrite.unshift : this._toWrite.push)({ + this._toWrite.add({ args: command.args, chainId: undefined, abort: undefined, @@ -287,7 +285,7 @@ export default class RedisCommandsQueue { }, channelsCounter: command.channelsCounter, typeMapping: PUSH_TYPE_MAPPING - }); + }, asap); }); } diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index cfdfba0455b..fa3fbe55c4e 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -525,222 +525,217 @@ describe('Client', () => { assert.deepEqual(map, results); }, GLOBAL.SERVERS.OPEN); -// describe('PubSub', () => { -// testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { -// function assertStringListener(message: string, channel: string) { -// assert.equal(typeof message, 'string'); -// assert.equal(typeof channel, 'string'); -// } - -// function assertBufferListener(message: Buffer, channel: Buffer) { -// assert.ok(message instanceof Buffer); -// assert.ok(channel instanceof Buffer); -// } - -// const subscriber = publisher.duplicate(); - -// await subscriber.connect(); - -// try { -// const channelListener1 = spy(assertBufferListener), -// channelListener2 = spy(assertStringListener), -// patternListener = spy(assertStringListener); - -// await Promise.all([ -// subscriber.subscribe('channel', channelListener1, true), -// subscriber.subscribe('channel', channelListener2), -// subscriber.pSubscribe('channel*', patternListener) -// ]); -// await Promise.all([ -// waitTillBeenCalled(channelListener1), -// waitTillBeenCalled(channelListener2), -// waitTillBeenCalled(patternListener), -// publisher.publish(Buffer.from('channel'), Buffer.from('message')) -// ]); - -// assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); -// assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); -// assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); - -// await subscriber.unsubscribe('channel', channelListener1, true); -// await Promise.all([ -// waitTillBeenCalled(channelListener2), -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); -// assert.ok(patternListener.calledTwice); -// assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); -// await subscriber.unsubscribe('channel'); -// await Promise.all([ -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(patternListener.calledThrice); -// assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); -// await subscriber.pUnsubscribe(); -// await publisher.publish('channel', 'message'); -// assert.ok(channelListener1.calledOnce); -// assert.ok(channelListener2.calledTwice); -// assert.ok(patternListener.calledThrice); -// // should be able to send commands when unsubsribed from all channels (see #1652) -// await assert.doesNotReject(subscriber.ping()); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); + describe('PubSub', () => { + testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => { + function assertStringListener(message: string, channel: string) { + assert.equal(typeof message, 'string'); + assert.equal(typeof channel, 'string'); + } -// testUtils.testWithClient('should resubscribe', async publisher => { -// const subscriber = publisher.duplicate(); + function assertBufferListener(message: Buffer, channel: Buffer) { + assert.ok(message instanceof Buffer); + assert.ok(channel instanceof Buffer); + } -// await subscriber.connect(); + const subscriber = await publisher.duplicate().connect(); -// try { -// const channelListener = spy(); -// await subscriber.subscribe('channel', channelListener); + try { + const channelListener1 = spy(assertBufferListener), + channelListener2 = spy(assertStringListener), + patternListener = spy(assertStringListener); -// const patternListener = spy(); -// await subscriber.pSubscribe('channe*', patternListener); + await Promise.all([ + subscriber.subscribe('channel', channelListener1, true), + subscriber.subscribe('channel', channelListener2), + subscriber.pSubscribe('channel*', patternListener) + ]); + await Promise.all([ + waitTillBeenCalled(channelListener1), + waitTillBeenCalled(channelListener2), + waitTillBeenCalled(patternListener), + publisher.publish(Buffer.from('channel'), Buffer.from('message')) + ]); + assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel'))); + assert.ok(channelListener2.calledOnceWithExactly('message', 'channel')); + assert.ok(patternListener.calledOnceWithExactly('message', 'channel')); -// await Promise.all([ -// once(subscriber, 'error'), -// publisher.clientKill({ -// filter: ClientKillFilters.SKIP_ME, -// skipMe: true -// }) -// ]); + await subscriber.unsubscribe('channel', channelListener1, true); + await Promise.all([ + waitTillBeenCalled(channelListener2), + waitTillBeenCalled(patternListener), + publisher.publish('channel', 'message') + ]); + assert.ok(channelListener1.calledOnce); + assert.ok(channelListener2.calledTwice); + assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel')); + assert.ok(patternListener.calledTwice); + assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel')); + await subscriber.unsubscribe('channel'); + await Promise.all([ + waitTillBeenCalled(patternListener), + publisher.publish('channel', 'message') + ]); + assert.ok(channelListener1.calledOnce); + assert.ok(channelListener2.calledTwice); + assert.ok(patternListener.calledThrice); + assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel')); + + await subscriber.pUnsubscribe(); + await publisher.publish('channel', 'message'); + assert.ok(channelListener1.calledOnce); + assert.ok(channelListener2.calledTwice); + assert.ok(patternListener.calledThrice); + + // should be able to send commands when unsubsribed from all channels (see #1652) + await assert.doesNotReject(subscriber.ping()); + } finally { + subscriber.destroy(); + } + }, GLOBAL.SERVERS.OPEN); -// await once(subscriber, 'ready'); + testUtils.testWithClient('should resubscribe', async publisher => { + const subscriber = await publisher.duplicate().connect(); -// await Promise.all([ -// waitTillBeenCalled(channelListener), -// waitTillBeenCalled(patternListener), -// publisher.publish('channel', 'message') -// ]); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); + try { + const channelListener = spy(); + await subscriber.subscribe('channel', channelListener); -// testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { -// const subscriber = publisher.duplicate(); - -// await subscriber.connect(); - -// try { -// await assert.doesNotReject(Promise.all([ -// subscriber.subscribe('channel', () => { -// // noop -// }), -// publisher.publish('channel', 'message') -// ])); -// } finally { -// await subscriber.disconnect(); -// } -// }, GLOBAL.SERVERS.OPEN); + const patternListener = spy(); + await subscriber.pSubscribe('channe*', patternListener); -// testUtils.testWithClient('should be able to quit in PubSub mode', async client => { -// await client.subscribe('channel', () => { -// // noop -// }); + await Promise.all([ + once(subscriber, 'error'), + publisher.clientKill({ + filter: 'SKIPME', + skipMe: true + }) + ]); -// await assert.doesNotReject(client.quit()); + await once(subscriber, 'ready'); -// assert.equal(client.isOpen, false); -// }, GLOBAL.SERVERS.OPEN); -// }); + await Promise.all([ + waitTillBeenCalled(channelListener), + waitTillBeenCalled(patternListener), + publisher.publish('channel', 'message') + ]); + } finally { + subscriber.destroy(); + } + }, GLOBAL.SERVERS.OPEN); -// testUtils.testWithClient('ConnectionTimeoutError', async client => { -// const promise = assert.rejects(client.connect(), ConnectionTimeoutError), -// start = process.hrtime.bigint(); + testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => { + const subscriber = await publisher.duplicate().connect(); -// while (process.hrtime.bigint() - start < 1_000_000) { -// // block the event loop for 1ms, to make sure the connection will timeout -// } + try { + await assert.doesNotReject(Promise.all([ + subscriber.subscribe('channel', () => { + // noop + }), + publisher.publish('channel', 'message') + ])); + } finally { + subscriber.destroy(); + } + }, GLOBAL.SERVERS.OPEN); -// await promise; -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// socket: { -// connectTimeout: 1 -// } -// }, -// disableClientSetup: true -// }); + testUtils.testWithClient('should be able to quit in PubSub mode', async client => { + await client.subscribe('channel', () => { + // noop + }); -// testUtils.testWithClient('client.quit', async client => { -// await client.connect(); + await assert.doesNotReject(client.quit()); -// const pingPromise = client.ping(), -// quitPromise = client.quit(); -// assert.equal(client.isOpen, false); + assert.equal(client.isOpen, false); + }, GLOBAL.SERVERS.OPEN); + }); -// const [ping, quit] = await Promise.all([ -// pingPromise, -// quitPromise, -// assert.rejects(client.ping(), ClientClosedError) -// ]); + testUtils.testWithClient('ConnectionTimeoutError', async client => { + const promise = assert.rejects(client.connect(), ConnectionTimeoutError), + start = process.hrtime.bigint(); -// assert.equal(ping, 'PONG'); -// assert.equal(quit, 'OK'); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); + while (process.hrtime.bigint() - start < 1_000_000) { + // block the event loop for 1ms, to make sure the connection will timeout + } -// testUtils.testWithClient('client.disconnect', async client => { -// const pingPromise = client.ping(), -// disconnectPromise = client.disconnect(); -// assert.equal(client.isOpen, false); -// await Promise.all([ -// assert.rejects(pingPromise, DisconnectsClientError), -// assert.doesNotReject(disconnectPromise), -// assert.rejects(client.ping(), ClientClosedError) -// ]); -// }, GLOBAL.SERVERS.OPEN); + await promise; + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + socket: { + connectTimeout: 1 + } + }, + disableClientSetup: true + }); -// testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { -// await client.disconnect(); -// await client.connect(); -// }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('client.quit', async client => { + await client.connect(); -// testUtils.testWithClient('should be able to use ref and unref', client => { -// client.unref(); -// client.ref(); -// }, GLOBAL.SERVERS.OPEN); + const pingPromise = client.ping(), + quitPromise = client.quit(); + assert.equal(client.isOpen, false); -// testUtils.testWithClient('pingInterval', async client => { -// assert.deepEqual( -// await once(client, 'ping-interval'), -// ['PONG'] -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// pingInterval: 1 -// } -// }); + const [ping, quit] = await Promise.all([ + pingPromise, + quitPromise, + assert.rejects(client.ping(), ClientClosedError) + ]); -// testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { -// const connectPromise = client.connect(); -// await assert.rejects( -// client.ping(), -// ClientOfflineError -// ); -// await connectPromise; -// await client.disconnect(); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// clientOptions: { -// disableOfflineQueue: true -// }, -// disableClientSetup: true -// }); + assert.equal(ping, 'PONG'); + assert.equal(quit, 'OK'); + }, { + ...GLOBAL.SERVERS.OPEN, + disableClientSetup: true + }); + + testUtils.testWithClient('client.disconnect', async client => { + const pingPromise = client.ping(), + disconnectPromise = client.disconnect(); + assert.equal(client.isOpen, false); + await Promise.all([ + assert.rejects(pingPromise, DisconnectsClientError), + assert.doesNotReject(disconnectPromise), + assert.rejects(client.ping(), ClientClosedError) + ]); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => { + await client.disconnect(); + await client.connect(); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should be able to use ref and unref', client => { + client.unref(); + client.ref(); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('pingInterval', async client => { + assert.deepEqual( + await once(client, 'ping-interval'), + ['PONG'] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + pingInterval: 1 + } + }); + + testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => { + const connectPromise = client.connect(); + await assert.rejects( + client.ping(), + ClientOfflineError + ); + await connectPromise; + await client.disconnect(); + }, { + ...GLOBAL.SERVERS.OPEN, + clientOptions: { + disableOfflineQueue: true + }, + disableClientSetup: true + }); describe('MONITOR', () => { testUtils.testWithClient('should be able to monitor commands', async client => { diff --git a/packages/client/lib/client/linked-list.ts b/packages/client/lib/client/linked-list.ts index c2f49527383..7aed43cfd1a 100644 --- a/packages/client/lib/client/linked-list.ts +++ b/packages/client/lib/client/linked-list.ts @@ -59,6 +59,12 @@ export class DoublyLinkedList { }; } + add(value: T, prepend = false) { + return prepend ? + this.unshift(value) : + this.push(value); + } + shift() { if (this._head === undefined) return undefined; From cb779a3ed7f64f387dbd11f308624aa46d10c402 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 12:51:56 -0500 Subject: [PATCH 288/325] #2666 for v5 --- packages/client/lib/client/index.spec.ts | 19 ++++++++++++++++++- packages/client/lib/errors.ts | 11 +++++++++++ packages/client/lib/multi-command.ts | 18 ++++++++++++++---- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index fa3fbe55c4e..9590ed68680 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -3,7 +3,7 @@ import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; import RedisClient, { RedisClientType } from '.'; // import { RedisClientMultiCommandType } from './multi-command'; // import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; -import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, SocketClosedUnexpectedlyError, WatchError } from '../errors'; +import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, ErrorReply, MultiErrorReply, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; import { spy } from 'sinon'; import { once } from 'node:events'; @@ -282,6 +282,23 @@ describe('Client', () => { // ...GLOBAL.SERVERS.OPEN, // minimumDockerVersion: [6, 2] // CLIENT INFO // }); + + + testUtils.testWithClient('should handle error replies (#2665)', async client => { + await assert.rejects( + client.multi() + .set('key', 'value') + .hGetAll('key') + .exec(), + err => { + assert.ok(err instanceof MultiErrorReply); + assert.equal(err.replies.length, 2); + assert.deepEqual(err.errorIndexes, [1]); + assert.ok(err.replies[1] instanceof ErrorReply); + return true; + } + ); + }, GLOBAL.SERVERS.OPEN); }); testUtils.testWithClient('scripts', async client => { diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index 33a2129b2b4..14533055236 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -69,3 +69,14 @@ export class SimpleError extends ErrorReply {} export class BlobError extends ErrorReply {} export class TimeoutError extends Error {} + +export class MultiErrorReply extends ErrorReply { + replies: Array; + errorIndexes: Array; + + constructor(replies: Array, errorIndexes: Array) { + super(`${errorIndexes.length} commands failed, see .replies and .errorIndexes for more information`); + this.replies = replies; + this.errorIndexes = errorIndexes; + } +} diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 7396b1219a5..019a0203284 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -1,4 +1,5 @@ import { CommandArguments, RedisScript, ReplyUnion, TransformReply } from './RESP/types'; +import { ErrorReply, MultiErrorReply } from './errors'; export type MULTI_REPLY = { GENERIC: 'generic'; @@ -46,9 +47,18 @@ export default class RedisMultiCommand { } transformReplies(rawReplies: Array): Array { - return rawReplies.map((reply, i) => { - const { transformReply, args } = this.queue[i]; - return transformReply ? transformReply(reply, args.preserve) : reply; - }); + const errorIndexes: Array = [], + replies = rawReplies.map((reply, i) => { + if (reply instanceof ErrorReply) { + errorIndexes.push(i); + return reply; + } + + const { transformReply, args } = this.queue[i]; + return transformReply ? transformReply(reply, args.preserve) : reply; + }); + + if (errorIndexes.length) throw new MultiErrorReply(replies, errorIndexes); + return replies; } } From 98cbdd0a7beb1f3b981214f74fc06bf744b5aab5 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 5 Dec 2023 12:55:15 -0500 Subject: [PATCH 289/325] upgrade deps --- package-lock.json | 950 +++++++++++++++++-------------- package.json | 18 +- packages/client/package.json | 7 +- packages/test-utils/package.json | 2 +- 4 files changed, 527 insertions(+), 450 deletions(-) diff --git a/package-lock.json b/package-lock.json index d1244c15c42..9fd72db78b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,17 +10,17 @@ ], "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.3", - "@types/node": "^20.8.10", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", - "gh-pages": "^6.0.0", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.3", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "gh-pages": "^6.1.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "release-it": "^16.2.1", - "tsx": "^3.14.0", - "typedoc": "^0.25.3", - "typescript": "^5.2.2" + "release-it": "^17.0.0", + "tsx": "^4.6.2", + "typedoc": "^0.25.4", + "typescript": "^5.3.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -47,12 +47,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -131,30 +131,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", - "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -185,12 +185,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", - "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.3", + "@babel/types": "^7.23.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -314,9 +314,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -332,32 +332,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -440,9 +440,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", - "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -466,19 +466,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", - "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -496,12 +496,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", - "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -886,9 +886,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "peer": true, "dependencies": { @@ -910,9 +910,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "peer": true, "engines": { @@ -1180,194 +1180,158 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", - "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", - "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.2.tgz", + "integrity": "sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg==", "dev": true, "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", - "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", + "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", "dev": true, "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^12.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", - "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", + "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", "dev": true, "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", + "@octokit/request": "^8.0.1", + "@octokit/types": "^12.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "18.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", - "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.1.0.tgz", + "integrity": "sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", - "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.5.tgz", + "integrity": "sha512-WKTQXxK+bu49qzwv4qKbMMRXej1DU2gq017euWyKVudA6MldaSSQuxtz+vGbhxV4CjxpUxjZu6rM2wfc1FiWVg==", "dev": true, "dependencies": { - "@octokit/tsconfig": "^1.0.2", - "@octokit/types": "^9.2.3" + "@octokit/types": "^12.4.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=4" + "@octokit/core": ">=5" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", "dev": true, + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": ">=5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", - "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.2.0.tgz", + "integrity": "sha512-ePbgBMYtGoRNXDyKGvr9cyHjQ163PbwD0y1MkDJCpkO2YH4OeXX40c4wYHKikHGZcpGPbcRLuy0unPUuafco8Q==", "dev": true, "dependencies": { - "@octokit/types": "^10.0.0" + "@octokit/types": "^12.3.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", - "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/core": ">=5" } }, "node_modules/@octokit/request": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", - "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", + "version": "8.1.6", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz", + "integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==", "dev": true, "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", "universal-user-agent": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", + "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", "dev": true, "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^12.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/request/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "19.0.13", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", - "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", + "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", "dev": true, "dependencies": { - "@octokit/core": "^4.2.1", - "@octokit/plugin-paginate-rest": "^6.1.2", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.1.2" + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, - "node_modules/@octokit/tsconfig": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", - "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", - "dev": true - }, "node_modules/@octokit/types": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", - "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz", + "integrity": "sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^19.1.0" } }, "node_modules/@pnpm/config.env-replace": { @@ -1451,6 +1415,18 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", + "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -1461,9 +1437,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0" @@ -1526,30 +1502,30 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz", - "integrity": "sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", - "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.20", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", - "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.2.tgz", + "integrity": "sha512-Zt6heIGsdqERkxctIpvN5Pv3edgBrhoeb3yHyxffd4InN0AX2SVNKSrhdDZKGQICVOxWP/q4DyhpfPNMSrpIiA==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -1562,9 +1538,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", - "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1577,16 +1553,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz", - "integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/type-utils": "6.10.0", - "@typescript-eslint/utils": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1612,15 +1588,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", - "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -1640,13 +1616,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", - "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1657,13 +1633,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz", - "integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.10.0", - "@typescript-eslint/utils": "6.10.0", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1684,9 +1660,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", - "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1697,13 +1673,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", - "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/visitor-keys": "6.10.0", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1724,17 +1700,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz", - "integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.10.0", - "@typescript-eslint/types": "6.10.0", - "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -1749,12 +1725,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", - "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2101,9 +2077,9 @@ "dev": true }, "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "dev": true, "engines": { "node": ">=0.6" @@ -2307,9 +2283,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -2326,9 +2302,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -2362,12 +2338,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", @@ -2410,6 +2380,18 @@ "node": ">=14.16" } }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -2458,9 +2440,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001561", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", - "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -2587,9 +2569,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "engines": { "node": ">=6" @@ -2911,6 +2893,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-require-extensions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", @@ -3066,9 +3104,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.580", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz", - "integrity": "sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw==", + "version": "1.4.603", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.603.tgz", + "integrity": "sha512-Dvo5OGjnl7AZTU632dFJtWj0uJK835eeOVQIuRcmBmsFsTNn3cL05FqOyHAfGQDIoHfLhyJ1Tya3PJ0ceMz54g==", "dev": true }, "node_modules/email-addresses": { @@ -3300,16 +3338,16 @@ } }, "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -3460,23 +3498,23 @@ } }, "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -3494,6 +3532,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -3723,9 +3773,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "peer": true, "dependencies": { @@ -3734,7 +3784,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -3808,9 +3858,9 @@ ] }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -3877,14 +3927,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "engines": { - "node": ">= 4" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3928,12 +3970,12 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4024,9 +4066,9 @@ } }, "node_modules/gh-pages": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.0.0.tgz", - "integrity": "sha512-FXZWJRsvP/fK2HJGY+Di6FRNHvqFF6gOIELaopDjXXgjeOYSNURcuYwEO/6bwuq6koP5Lnkvnr5GViXzuOB89g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.0.tgz", + "integrity": "sha512-MdXigvqN3I66Y+tAZsQJMzpBWQOI1snD6BYuECmP+GEdryYMMOQvzn4AConk/+qNg/XIuQhB1xNGrl3Rmj1iow==", "dev": true, "dependencies": { "async": "^3.2.4", @@ -4084,9 +4126,9 @@ } }, "node_modules/git-url-parse": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.1.tgz", + "integrity": "sha512-PCFJyeSSdtnbfhSNRw9Wk96dDCNx+sogTe4YNXeXSJxt7xz5hvXekuRn9JX7m+Mf4OscCu8h+mtAl3+h5Fo8lQ==", "dev": true, "dependencies": { "git-up": "^7.0.0" @@ -4228,6 +4270,18 @@ "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/got/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4309,18 +4363,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-yarn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", - "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -4393,9 +4435,9 @@ } }, "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, "dependencies": { "quick-lru": "^5.1.1", @@ -4419,12 +4461,12 @@ } }, "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "engines": { - "node": ">=14.18.0" + "node": ">=16.17.0" } }, "node_modules/iconv-lite": { @@ -4460,9 +4502,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -4537,12 +4579,12 @@ } }, "node_modules/inquirer": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.11.tgz", - "integrity": "sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==", + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", + "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", "dev": true, "dependencies": { - "@ljharb/through": "^2.3.9", + "@ljharb/through": "^2.3.11", "ansi-escapes": "^4.3.2", "chalk": "^5.3.0", "cli-cursor": "^3.1.0", @@ -4858,6 +4900,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-in-ci": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-0.1.0.tgz", + "integrity": "sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==", + "dev": true, + "bin": { + "is-in-ci": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -4988,15 +5045,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -5166,15 +5214,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-yarn-global": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", - "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -5907,6 +5946,24 @@ "type-detect": "4.0.8" } }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -5957,9 +6014,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -6192,13 +6249,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -6588,6 +6645,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json/node_modules/got": { "version": "12.6.1", "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", @@ -7101,21 +7170,21 @@ } }, "node_modules/release-it": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-16.2.1.tgz", - "integrity": "sha512-+bHiKPqkpld+NaiW+K/2WsjaHgfPB00J6uk8a+g8QyuBtzfFoMVe+GKsfaDO5ztEHRrSg+7luoXzd8IfvPNPig==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-17.0.0.tgz", + "integrity": "sha512-1A1sSQy8VXuAJcslZGhKtOD/LVBuf1sH4XqhKsQuh+2EIksC2STx/MdKmVE86jFd/zorHTXOpl7Lr/isD0dDrg==", "dev": true, "dependencies": { "@iarna/toml": "2.2.5", - "@octokit/rest": "19.0.13", + "@octokit/rest": "20.0.2", "async-retry": "1.3.3", "chalk": "5.3.0", "cosmiconfig": "8.3.6", - "execa": "7.2.0", - "git-url-parse": "13.1.0", - "globby": "13.2.2", + "execa": "8.0.1", + "git-url-parse": "13.1.1", + "globby": "14.0.0", "got": "13.0.0", - "inquirer": "9.2.11", + "inquirer": "9.2.12", "is-ci": "3.0.1", "issue-parser": "6.0.0", "lodash": "4.17.21", @@ -7129,7 +7198,7 @@ "proxy-agent": "6.3.1", "semver": "7.5.4", "shelljs": "0.8.5", - "update-notifier": "6.0.2", + "update-notifier": "7.0.0", "url-join": "5.0.0", "wildcard-match": "5.1.2", "yargs-parser": "21.1.1" @@ -7138,7 +7207,7 @@ "release-it": "bin/release-it.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/release-it/node_modules/chalk": { @@ -7154,28 +7223,29 @@ } }, "node_modules/release-it/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", "dev": true, "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", + "@sindresorhus/merge-streams": "^1.0.0", + "fast-glob": "^3.3.2", "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/release-it/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/release-it/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { "node": ">=12" @@ -7184,6 +7254,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/release-it/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/release-it/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", @@ -7385,6 +7467,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/run-applescript/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-applescript/node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -7701,16 +7795,16 @@ "dev": true }, "node_modules/sinon": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz", - "integrity": "sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", + "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.3.0", + "@sinonjs/fake-timers": "^11.2.2", "@sinonjs/samsam": "^8.0.0", "diff": "^5.1.0", - "nise": "^5.1.4", + "nise": "^5.1.5", "supports-color": "^7.2.0" }, "funding": { @@ -7789,16 +7883,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -8073,12 +8157,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -8119,18 +8197,20 @@ "dev": true }, "node_modules/tsx": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", - "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.6.2.tgz", + "integrity": "sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==", "dev": true, "dependencies": { "esbuild": "~0.18.20", - "get-tsconfig": "^4.7.2", - "source-map-support": "^0.5.21" + "get-tsconfig": "^4.7.2" }, "bin": { "tsx": "dist/cli.mjs" }, + "engines": { + "node": ">=18.0.0" + }, "optionalDependencies": { "fsevents": "~2.3.3" } @@ -8245,9 +8325,9 @@ } }, "node_modules/typedoc": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", - "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.4.tgz", + "integrity": "sha512-Du9ImmpBCw54bX275yJrxPVnjdIyJO/84co0/L9mwe0R3G4FSR6rQ09AlXVRvZEGMUg09+z/usc8mgygQ1aidA==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -8262,7 +8342,7 @@ "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -8290,9 +8370,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -8323,6 +8403,18 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", @@ -8393,28 +8485,26 @@ } }, "node_modules/update-notifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", - "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.0.0.tgz", + "integrity": "sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==", "dev": true, "dependencies": { - "boxen": "^7.0.0", - "chalk": "^5.0.1", + "boxen": "^7.1.1", + "chalk": "^5.3.0", "configstore": "^6.0.0", - "has-yarn": "^3.0.0", "import-lazy": "^4.0.0", - "is-ci": "^3.0.1", + "is-in-ci": "^0.1.0", "is-installed-globally": "^0.4.0", "is-npm": "^6.0.0", - "is-yarn-global": "^0.4.0", "latest-version": "^7.0.0", "pupa": "^3.1.0", - "semver": "^7.3.7", + "semver": "^7.5.4", "semver-diff": "^4.0.0", "xdg-basedir": "^5.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/yeoman/update-notifier?sponsor=1" @@ -8496,22 +8586,6 @@ "node": ">= 8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8677,6 +8751,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/windows-release/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/windows-release/node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -8875,7 +8961,6 @@ } }, "packages/bloom": { - "name": "@redis/bloom", "version": "2.0.0-next.3", "license": "MIT", "devDependencies": { @@ -8886,24 +8971,21 @@ } }, "packages/client": { - "name": "@redis/client", "version": "2.0.0-next.4", "license": "MIT", "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0" + "cluster-key-slot": "1.1.2" }, "devDependencies": { "@redis/test-utils": "*", - "@types/sinon": "^10.0.16", - "sinon": "^16.0.0" + "@types/sinon": "^17.0.2", + "sinon": "^17.0.1" }, "engines": { "node": ">=14" } }, "packages/graph": { - "name": "@redis/graph", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -8914,7 +8996,6 @@ } }, "packages/json": { - "name": "@redis/json", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -8925,7 +9006,7 @@ } }, "packages/redis": { - "version": "5.0.0-next.3", + "version": "5.0.0-next.4", "license": "MIT", "dependencies": { "@redis/bloom": "2.0.0-next.3", @@ -8937,7 +9018,6 @@ } }, "packages/search": { - "name": "@redis/search", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -8948,9 +9028,8 @@ } }, "packages/test-utils": { - "name": "@redis/test-utils", "devDependencies": { - "@types/yargs": "^17.0.24", + "@types/yargs": "^17.0.32", "yargs": "^17.7.2" }, "peerDependencies": { @@ -9016,7 +9095,6 @@ } }, "packages/time-series": { - "name": "@redis/time-series", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index f15b0e0fce0..7f2375e1228 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,16 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.3", - "@types/node": "^20.8.10", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", - "gh-pages": "^6.0.0", + "@types/mocha": "^10.0.6", + "@types/node": "^20.10.3", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "gh-pages": "^6.1.0", "mocha": "^10.2.0", "nyc": "^15.1.0", - "release-it": "^16.2.1", - "tsx": "^3.14.0", - "typedoc": "^0.25.3", - "typescript": "^5.2.2" + "release-it": "^17.0.0", + "tsx": "^4.6.2", + "typedoc": "^0.25.4", + "typescript": "^5.3.2" } } diff --git a/packages/client/package.json b/packages/client/package.json index 7526e7e034e..ce6d28ff348 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -12,13 +12,12 @@ "test": "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'" }, "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0" + "cluster-key-slot": "1.1.2" }, "devDependencies": { "@redis/test-utils": "*", - "@types/sinon": "^10.0.16", - "sinon": "^16.0.0" + "@types/sinon": "^17.0.2", + "sinon": "^17.0.1" }, "engines": { "node": ">=14" diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 8da954f0f76..5e291211b6c 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -7,7 +7,7 @@ "@redis/client": "*" }, "devDependencies": { - "@types/yargs": "^17.0.24", + "@types/yargs": "^17.0.32", "yargs": "^17.7.2" } } From 3b28aa6c8172a2159905b9a1e42ffcb6f2692048 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 7 Dec 2023 09:01:43 -0500 Subject: [PATCH 290/325] add errors iterator to MultiErrorReply --- packages/client/lib/client/index.spec.ts | 1 + packages/client/lib/errors.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 9590ed68680..1aaf767b0d1 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -295,6 +295,7 @@ describe('Client', () => { assert.equal(err.replies.length, 2); assert.deepEqual(err.errorIndexes, [1]); assert.ok(err.replies[1] instanceof ErrorReply); + assert.deepEqual([...err.errors()], [err.replies[1]]); return true; } ); diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index 14533055236..b7345ac76e9 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -79,4 +79,10 @@ export class MultiErrorReply extends ErrorReply { this.replies = replies; this.errorIndexes = errorIndexes; } + + *errors() { + for (const index of this.errorIndexes) { + yield this.replies[index]; + } + } } From 7f7a53a1b1fce9d5fcb42a20f0decdcd1100e431 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 7 Dec 2023 09:42:04 -0500 Subject: [PATCH 291/325] uncomment some tests, fix bugs with `_selectedDB` --- packages/client/lib/client/index.spec.ts | 180 +++++++------------- packages/client/lib/client/index.ts | 21 ++- packages/client/lib/client/multi-command.ts | 9 +- 3 files changed, 82 insertions(+), 128 deletions(-) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 1aaf767b0d1..d8ac7487cc6 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -1,17 +1,13 @@ import { strict as assert } from 'node:assert'; import testUtils, { GLOBAL, waitTillBeenCalled } from '../test-utils'; import RedisClient, { RedisClientType } from '.'; -// import { RedisClientMultiCommandType } from './multi-command'; -// import { RedisCommandRawReply, RedisModules, RedisFunctions, RedisScripts } from '../commands'; import { AbortError, ClientClosedError, ClientOfflineError, ConnectionTimeoutError, DisconnectsClientError, ErrorReply, MultiErrorReply, SocketClosedUnexpectedlyError, WatchError } from '../errors'; import { defineScript } from '../lua-script'; import { spy } from 'sinon'; import { once } from 'node:events'; -// import { ClientKillFilters } from '../commands/CLIENT_KILL'; -// import { promisify } from 'node:util'; import { MATH_FUNCTION, loadMathFunction } from '../commands/FUNCTION_LOAD.spec'; import { RESP_TYPES } from '../RESP/decoder'; -import { NumberReply } from '../RESP/types'; +import { BlobStringReply, NumberReply } from '../RESP/types'; import { SortedSetMember } from '../commands/generic-transformers'; export const SQUARE_SCRIPT = defineScript({ @@ -232,24 +228,26 @@ describe('Client', () => { } }); - // testUtils.testWithClient('WatchError', async client => { - // await client.watch('key'); - - // await client.set( - // RedisClient.commandOptions({ - // isolated: true - // }), - // 'key', - // '1' - // ); - - // await assert.rejects( - // client.multi() - // .decr('key') - // .exec(), - // WatchError - // ); - // }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('WatchError', async client => { + await client.watch('key'); + + const duplicate = await client.duplicate().connect(); + try { + await client.set( + 'key', + '1' + ); + } finally { + duplicate.destroy(); + } + + await assert.rejects( + client.multi() + .decr('key') + .exec(), + WatchError + ); + }, GLOBAL.SERVERS.OPEN); describe('execAsPipeline', () => { testUtils.testWithClient('exec(true)', async client => { @@ -269,20 +267,19 @@ describe('Client', () => { }, GLOBAL.SERVERS.OPEN); }); - // testUtils.testWithClient('should remember selected db', async client => { - // await client.multi() - // .select(1) - // .exec(); - // await killClient(client); - // assert.equal( - // (await client.clientInfo()).db, - // 1 - // ); - // }, { - // ...GLOBAL.SERVERS.OPEN, - // minimumDockerVersion: [6, 2] // CLIENT INFO - // }); - + testUtils.testWithClient('should remember selected db', async client => { + await client.multi() + .select(1) + .exec(); + await killClient(client); + assert.equal( + (await client.clientInfo()).db, + 1 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] // CLIENT INFO + }); testUtils.testWithClient('should handle error replies (#2665)', async client => { await assert.rejects( @@ -320,12 +317,10 @@ describe('Client', () => { const module = { echo: { - transformArguments(message: string): Array { + transformArguments(message: string) { return ['ECHO', message]; }, - transformReply(reply: string): string { - return reply; - } + transformReply: undefined as unknown as () => BlobStringReply } }; @@ -386,81 +381,34 @@ describe('Client', () => { disableClientSetup: true, }); -// describe('isolationPool', () => { -// testUtils.testWithClient('executeIsolated', async client => { -// const id = await client.clientId(), -// isolatedId = await client.executeIsolated(isolatedClient => isolatedClient.clientId()); -// assert.ok(id !== isolatedId); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should be able to use pool even before connect', async client => { -// await client.executeIsolated(() => Promise.resolve()); -// // make sure to destroy isolation pool -// await client.connect(); -// await client.disconnect(); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); - -// testUtils.testWithClient('should work after reconnect (#2406)', async client => { -// await client.disconnect(); -// await client.connect(); -// await client.executeIsolated(() => Promise.resolve()); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should throw ClientClosedError after disconnect', async client => { -// await client.connect(); -// await client.disconnect(); -// await assert.rejects( -// client.executeIsolated(() => Promise.resolve()), -// ClientClosedError -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// disableClientSetup: true -// }); -// }); - -// async function killClient< -// M extends RedisModules, -// F extends RedisFunctions, -// S extends RedisScripts -// >( -// client: RedisClientType, -// errorClient: RedisClientType = client -// ): Promise { -// const onceErrorPromise = once(errorClient, 'error'); -// await client.sendCommand(['QUIT']); -// await Promise.all([ -// onceErrorPromise, -// assert.rejects(client.ping(), SocketClosedUnexpectedlyError) -// ]); -// } - -// testUtils.testWithClient('should reconnect when socket disconnects', async client => { -// await killClient(client); -// await assert.doesNotReject(client.ping()); -// }, GLOBAL.SERVERS.OPEN); - -// testUtils.testWithClient('should remember selected db', async client => { -// await client.select(1); -// await killClient(client); -// assert.equal( -// (await client.clientInfo()).db, -// 1 -// ); -// }, { -// ...GLOBAL.SERVERS.OPEN, -// minimumDockerVersion: [6, 2] // CLIENT INFO -// }); - -// testUtils.testWithClient('should propagated errors from "isolated" clients', client => { -// client.on('error', () => { -// // ignore errors -// }); -// return client.executeIsolated(isolated => killClient(isolated, client)); -// }, GLOBAL.SERVERS.OPEN); + async function killClient( + client: RedisClientType, + errorClient: RedisClientType = client + ): Promise { + const onceErrorPromise = once(errorClient, 'error'); + await client.sendCommand(['QUIT']); + await Promise.all([ + onceErrorPromise, + assert.rejects(client.ping(), SocketClosedUnexpectedlyError) + ]); + } + + testUtils.testWithClient('should reconnect when socket disconnects', async client => { + await killClient(client); + await assert.doesNotReject(client.ping()); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should remember selected db', async client => { + await client.select(1); + await killClient(client); + assert.equal( + (await client.clientInfo()).db, + 1 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] // CLIENT INFO + }); testUtils.testWithClient('scanIterator', async client => { const entries: Array = [], diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index e47a5004208..1f33ca44835 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -315,7 +315,7 @@ export default class RedisClient< } if (options?.database) { - this._selectedDB = options.database; + this.self._selectedDB = options.database; } if (options?.commandOptions) { @@ -584,7 +584,7 @@ export default class RedisClient< async SELECT(db: number): Promise { await this.sendCommand(['SELECT', db.toString()]); - this._selectedDB = db; + this.self._selectedDB = db; } select = this.SELECT; @@ -742,7 +742,10 @@ export default class RedisClient< /** * @internal */ - _executePipeline(commands: Array) { + async _executePipeline( + commands: Array, + selectedDB?: number + ) { if (!this._socket.isOpen) { return Promise.reject(new ClientClosedError()); } @@ -753,7 +756,13 @@ export default class RedisClient< })) ); this._scheduleWrite(); - return promise; + const result = await promise; + + if (selectedDB !== undefined) { + this.self._selectedDB = selectedDB; + } + + return result; } /** @@ -764,7 +773,7 @@ export default class RedisClient< selectedDB?: number ) { if (!this._socket.isOpen) { - return Promise.reject(new ClientClosedError()); + throw new ClientClosedError(); } const typeMapping = this._commandOptions?.typeMapping, @@ -796,7 +805,7 @@ export default class RedisClient< } if (selectedDB !== undefined) { - this._selectedDB = selectedDB; + this.self._selectedDB = selectedDB; } return execResult as Array; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 5f7679d2b17..7daf4b5d801 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -85,8 +85,6 @@ export type RedisClientMultiCommandType< type ExecuteMulti = (commands: Array, selectedDB?: number) => Promise>; -type ExecutePipeline = (commands: Array) => Promise>; - export default class RedisClientMultiCommand { private static _createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); @@ -153,13 +151,12 @@ export default class RedisClientMultiCommand { private readonly _multi = new RedisMultiCommand(); private readonly _executeMulti: ExecuteMulti; - private readonly _executePipeline: ExecutePipeline; + private readonly _executePipeline: ExecuteMulti; private _selectedDB?: number; - constructor(executeMulti: ExecuteMulti, executePipeline: ExecutePipeline) { + constructor(executeMulti: ExecuteMulti, executePipeline: ExecuteMulti) { this._executeMulti = executeMulti; this._executePipeline = executePipeline; - // this._client = client; } SELECT(db: number, transformReply?: TransformReply): this { @@ -193,7 +190,7 @@ export default class RedisClientMultiCommand { if (this._multi.queue.length === 0) return [] as MultiReplyType; return this._multi.transformReplies( - await this._executePipeline(this._multi.queue) + await this._executePipeline(this._multi.queue, this._selectedDB) ) as MultiReplyType; } From 94cb86f605364a71c491b1ad2a3e46e4d5358942 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 12 Dec 2023 16:15:50 -0500 Subject: [PATCH 292/325] test RESP decoder + fix some bugs --- packages/client/lib/RESP/decoder.spec.ts | 504 +++++++++++++---------- packages/client/lib/RESP/decoder.ts | 23 +- 2 files changed, 295 insertions(+), 232 deletions(-) diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index e4e447fab6b..5f0267911aa 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -1,226 +1,286 @@ -// import { strict as assert } from 'node:assert'; -// import { SinonSpy, spy } from 'sinon'; -// import { Decoder, RESP_TYPES } from './decoder'; -// import { ErrorReply } from '../errors'; -// import { TypeMapping } from './types'; - -// function createDecoderAndSpies(typeMapping: TypeMapping = {}) { -// const typeMappingSpy = spy(() => typeMapping), -// onReplySpy = spy(), -// onErrorReplySpy = spy(), -// onPushSpy = spy(); - -// return { -// decoder: new Decoder({ -// getTypeMapping: typeMappingSpy, -// onReply: onReplySpy, -// onErrorReply: onErrorReplySpy, -// onPush: onPushSpy -// }), -// typeMappingSpy, -// onReplySpy, -// onErrorReplySpy, -// onPushSpy -// }; -// } - -// function writeChunks(stream: Decoder, buffer: Buffer) { -// let i = 0; -// while (i < buffer.length) { -// stream.write(buffer.subarray(i, ++i)); -// } -// } - -// type Replies = Array>; - -// function generateTests(toWrite: Buffer, tests: Array): void { -// for (const test of tests) { -// describe(test.name, () => { -// generateTests(toWrite, test); -// }); -// } -// } - -// interface Test { -// typeMapping?: TypeMapping; -// replies?: Replies; -// errorReplies?: Replies; -// pushReplies?: Replies; -// } - -// function genetareTypeTests(toWrite: Buffer, { typeMapping, replies, errorReplies, pushReplies }: Test) { -// const total = (replies?.length ?? 0) + (errorReplies?.length ?? 0) + (pushReplies?.length ?? 0); -// it('single chunk', () => { -// const { decoder, typeMappingSpy, onReplySpy, onErrorReplySpy, onPushSpy } = createDecoderAndSpies(typeMapping); -// decoder.write(toWrite); -// assert.equal(typeMappingSpy.callCount, total); -// testReplies(onReplySpy, replies); -// testReplies(onErrorReplySpy, errorReplies); -// testReplies(onPushSpy, pushReplies); -// }); - -// it('multiple chunks', () => { -// const { decoder, typeMappingSpy, onReplySpy, onErrorReplySpy, onPushSpy } = createDecoderAndSpies(typeMapping); -// writeChunks(decoder, toWrite); -// assert.equal(typeMappingSpy.callCount, total); -// testReplies(onReplySpy, replies); -// testReplies(onErrorReplySpy, errorReplies); -// testReplies(onPushSpy, pushReplies); -// }); -// } - -// function testReplies(spy: SinonSpy, replies?: Replies): void { -// if (!replies) { -// assert.equal(spy.callCount, 0); -// return; -// } - -// assert.equal(spy.callCount, replies.length); -// for (const [i, reply] of replies.entries()) { -// assert.deepEqual( -// spy.getCall(i).args, -// reply -// ); -// } -// } - -// describe('RESP2Parser', () => { -// describe('Null', () => { -// genetareTypeTests(Buffer.from('_\r\n'), { -// replies: [[null]] -// }); -// }); - -// describe('Boolean', () => { -// genetareTypeTests(Buffer.from('#t\r\n'), { -// replies: [[null]] -// }); -// }); - -// describe('Number', () => { -// generateTests(Buffer.from(':-1\r\n')) -// describe('as number', () => { -// describe('-1', () => { -// generateTests({ -// toWrite: , -// replies: [[-1]] -// }); -// }); - -// describe('0', () => { -// generateTests({ -// toWrite: Buffer.from(':0\r\n'), -// replies: [[0]] -// }); -// }); +import { strict as assert } from 'node:assert'; +import { SinonSpy, spy } from 'sinon'; +import { Decoder, RESP_TYPES } from './decoder'; +import { BlobError, ErrorReply, SimpleError } from '../errors'; +import { TypeMapping } from './types'; + +interface Test { + toWrite: Buffer; + typeMapping?: TypeMapping; + replies?: Array; + errorReplies?: Array; + pushReplies?: Array; +} + +function test(name: string, config: Test) { + describe(name, () => { + it('single chunk', () => { + const setup = setupTest(config); + setup.decoder.write(config.toWrite); + assertCalls(config, setup); + }); + + it('byte by byte', () => { + const setup = setupTest(config); + for (let i = 0; i < config.toWrite.length; i++) { + setup.decoder.write(config.toWrite.subarray(i, i + 1)); + } + assertCalls(config, setup); + }); + }) +} + +function setupTest(config: Test) { + const onReplySpy = spy(), + onErrorReplySpy = spy(), + onPushSpy = spy(); + + return { + decoder: new Decoder({ + getTypeMapping: () => config.typeMapping ?? {}, + onReply: onReplySpy, + onErrorReply: onErrorReplySpy, + onPush: onPushSpy + }), + onReplySpy, + onErrorReplySpy, + onPushSpy + }; +} + +function assertCalls(config: Test, spies: ReturnType) { + assertSpyCalls(spies.onReplySpy, config.replies); + assertSpyCalls(spies.onErrorReplySpy, config.errorReplies); + assertSpyCalls(spies.onPushSpy, config.pushReplies); +} + +function assertSpyCalls(spy: SinonSpy, replies?: Array) { + if (!replies) { + assert.equal(spy.callCount, 0); + return; + } + + assert.equal(spy.callCount, replies.length); + for (const [i, reply] of replies.entries()) { + assert.deepEqual( + spy.getCall(i).args, + [reply] + ); + } +} + +describe.only('RESP Decoder', () => { + test('Null', { + toWrite: Buffer.from('_\r\n'), + replies: [null] + }); -// describe('+1', () => { -// generateTests({ -// toWrite: Buffer.from(':+1\r\n'), -// replies: [[1]] -// }); -// }); -// }); -// }); + describe('Boolean', () => { + test('true', { + toWrite: Buffer.from('#t\r\n'), + replies: [true] + }); -// describe('Simple String', () => { -// describe('as strings', () => { -// generateTests({ -// toWrite: Buffer.from('+OK\r\n'), -// replies: [['OK']] -// }); -// }); - -// describe('as buffers', () => { -// generateTests({ -// toWrite: Buffer.from('+OK\r\n'), -// typeMapping: { -// [RESP_TYPES.SIMPLE_STRING]: Buffer -// }, -// replies: [[Buffer.from('OK')]] -// }); -// }); -// }); - -// describe('Error', () => { -// generateTests({ -// toWrite: Buffer.from('-ERR\r\n'), -// errorReplies: [[new ErrorReply('ERR')]] -// }); -// }); + test('false', { + toWrite: Buffer.from('#f\r\n'), + replies: [false] + }); + }); - + describe('Number', () => { + test('0', { + toWrite: Buffer.from(':0\r\n'), + replies: [0] + }); + + test('1', { + toWrite: Buffer.from(':+1\r\n'), + replies: [1] + }); + + test('+1', { + toWrite: Buffer.from(':+1\r\n'), + replies: [1] + }); + + test('-1', { + toWrite: Buffer.from(':-1\r\n'), + replies: [-1] + }); + }); + + describe('BigNumber', () => { + test('0', { + toWrite: Buffer.from('(0\r\n'), + replies: [0n] + }); + + test('1', { + toWrite: Buffer.from('(1\r\n'), + replies: [1n] + }); + + test('+1', { + toWrite: Buffer.from('(+1\r\n'), + replies: [1n] + }); + + test('-1', { + toWrite: Buffer.from('(-1\r\n'), + replies: [-1n] + }); + }); + + describe('Double', () => { + test('0', { + toWrite: Buffer.from(',0\r\n'), + replies: [0] + }); + + test('1', { + toWrite: Buffer.from(',1\r\n'), + replies: [1] + }); + + test('+1', { + toWrite: Buffer.from(',+1\r\n'), + replies: [1] + }); + + test('-1', { + toWrite: Buffer.from(',-1\r\n'), + replies: [-1] + }); + + test('1.1', { + toWrite: Buffer.from(',1.1\r\n'), + replies: [1.1] + }); + + test('nan', { + toWrite: Buffer.from(',nan\r\n'), + replies: [NaN] + }); + + test('inf', { + toWrite: Buffer.from(',inf\r\n'), + replies: [Infinity] + }); + + test('+inf', { + toWrite: Buffer.from(',+inf\r\n'), + replies: [Infinity] + }); + + test('-inf', { + toWrite: Buffer.from(',-inf\r\n'), + replies: [-Infinity] + }); + + test('1e1', { + toWrite: Buffer.from(',1e1\r\n'), + replies: [1e1] + }); + + test('-1.1E1', { + toWrite: Buffer.from(',-1.1E1\r\n'), + replies: [-1.1E1] + }); + }); + + test('SimpleString', { + toWrite: Buffer.from('+OK\r\n'), + replies: ['OK'] + }); + + describe('BlobString', () => { + test("''", { + toWrite: Buffer.from('$0\r\n\r\n'), + replies: [''] + }); + + test("'1234567890'", { + toWrite: Buffer.from('$10\r\n1234567890\r\n'), + replies: ['1234567890'] + }); + + test('null (RESP2 backwards compatibility)', { + toWrite: Buffer.from('$-1\r\n'), + replies: [null] + }); + }); + + describe('VerbatimString', () => { + test("''", { + toWrite: Buffer.from('=4\r\ntxt:\r\n'), + replies: [''] + }); + + test("'123456'", { + toWrite: Buffer.from('=10\r\ntxt:123456\r\n'), + replies: ['123456'] + }); + }); + + test('SimpleError', { + toWrite: Buffer.from('-ERROR\r\n'), + errorReplies: [new SimpleError('ERROR')] + }); + + test('BlobError', { + toWrite: Buffer.from('!5\r\nERROR\r\n'), + errorReplies: [new BlobError('ERROR')] + }); + + describe('Array', () => { + test('[]', { + toWrite: Buffer.from('*0\r\n'), + replies: [[]] + }); + + test('[0..9]', { + toWrite: Buffer.from(`*10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), + replies: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + }); + + test('null (RESP2 backwards compatibility)', { + toWrite: Buffer.from('*-1\r\n'), + replies: [null] + }); + }); + + describe('Set', () => { + test('empty', { + toWrite: Buffer.from('~0\r\n'), + replies: [[]] + }); + + test('of 0..9', { + toWrite: Buffer.from(`*10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), + replies: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + }); + }); + + describe('Map', () => { + test('{}', { + toWrite: Buffer.from('%0\r\n'), + replies: [Object.create(null)] + }); -// describe('Bulk String', () => { -// describe('null', () => { -// generateTests({ -// toWrite: Buffer.from('$-1\r\n'), -// returnStringsAsBuffers: false, -// replies: [[null]] -// }); -// }); - -// describe('as strings', () => { -// generateTests({ -// toWrite: Buffer.from('$2\r\naa\r\n'), -// returnStringsAsBuffers: false, -// replies: [['aa']] -// }); -// }); - -// describe('as buffers', () => { -// generateTests({ -// toWrite: Buffer.from('$2\r\naa\r\n'), -// returnStringsAsBuffers: true, -// replies: [[Buffer.from('aa')]] -// }); -// }); -// }); - -// describe('Array', () => { -// describe('null', () => { -// generateTests({ -// toWrite: Buffer.from('*-1\r\n'), -// returnStringsAsBuffers: false, -// replies: [[null]] -// }); -// }); - -// const arrayBuffer = Buffer.from( -// '*5\r\n' + -// '+OK\r\n' + -// '-ERR\r\n' + -// ':0\r\n' + -// '$1\r\na\r\n' + -// '*0\r\n' -// ); - -// describe('as strings', () => { -// generateTests({ -// toWrite: arrayBuffer, -// returnStringsAsBuffers: false, -// replies: [[[ -// 'OK', -// new ErrorReply('ERR'), -// 0, -// 'a', -// [] -// ]]] -// }); -// }); - -// describe('as buffers', () => { -// generateTests({ -// toWrite: arrayBuffer, -// returnStringsAsBuffers: true, -// replies: [[[ -// Buffer.from('OK'), -// new ErrorReply('ERR'), -// 0, -// Buffer.from('a'), -// [] -// ]]] -// }); -// }); -// }); -// }); + test("{ '0'..'9': }", { + toWrite: Buffer.from(`%10\r\n+0\r\n+0\r\n+1\r\n+1\r\n+2\r\n+2\r\n+3\r\n+3\r\n+4\r\n+4\r\n+5\r\n+5\r\n+6\r\n+6\r\n+7\r\n+7\r\n+8\r\n+8\r\n+9\r\n+9\r\n`), + replies: [Object.create(null, { + 0: { value: '0', enumerable: true }, + 1: { value: '1', enumerable: true }, + 2: { value: '2', enumerable: true }, + 3: { value: '3', enumerable: true }, + 4: { value: '4', enumerable: true }, + 5: { value: '5', enumerable: true }, + 6: { value: '6', enumerable: true }, + 7: { value: '7', enumerable: true }, + 8: { value: '8', enumerable: true }, + 9: { value: '9', enumerable: true } + })] + }); + }); +}); diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 7e2a4885873..7c48f1f783f 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -257,7 +257,7 @@ export class Decoder { private _maybeDecodeNumberValue(isNegative, chunk) { const cb = this._decodeUnsingedNumber.bind(this, 0); return ++this._cursor === chunk.length ? - this._decodeNumberValue.bind(isNegative, cb) : + this._decodeNumberValue.bind(this, isNegative, cb) : this._decodeNumberValue(isNegative, cb, chunk); } @@ -306,8 +306,8 @@ export class Decoder { private _maybeDecodeBigNumberValue(isNegative, chunk) { const cb = this._decodeUnsingedBigNumber.bind(this, 0n); - return this._cursor === chunk.length ? - this._decodeBigNumberValue.bind(isNegative, cb) : + return ++this._cursor === chunk.length ? + this._decodeBigNumberValue.bind(this, isNegative, cb) : this._decodeBigNumberValue(isNegative, cb, chunk); } @@ -357,7 +357,7 @@ export class Decoder { private _maybeDecodeDoubleInteger(isNegative, chunk) { return ++this._cursor === chunk.length ? this._decodeDoubleInteger.bind(this, isNegative, 0) : - this._decodeDoubleInteger(true, 0, chunk); + this._decodeDoubleInteger(isNegative, 0, chunk); } private _decodeDoubleInteger(isNegative, integer, chunk) { @@ -376,14 +376,17 @@ export class Decoder { switch (byte) { case ASCII['.']: this._cursor = cursor + 1; // skip . - return cursor < chunk.length ? + return this._cursor < chunk.length ? this._decodeDoubleDecimal(isNegative, 0, integer, chunk) : this._decodeDoubleDecimal.bind(this, isNegative, 0, integer); case ASCII.E: case ASCII.e: - this._cursor = cursor + 1; // skip e - return this._decodeDoubleExponent(isNegative ? -integer : integer, chunk); + this._cursor = cursor + 1; // skip E/e + const i = isNegative ? -integer : integer; + return this._cursor < chunk.length ? + this._decodeDoubleExponent(i, chunk) : + this._decodeDoubleExponent.bind(this, i); case ASCII['\r']: this._cursor = cursor + 2; // skip \r\n @@ -414,11 +417,11 @@ export class Decoder { switch (byte) { case ASCII.E: case ASCII.e: - this._cursor = cursor + 1; // skip e + this._cursor = cursor + 1; // skip E/e const d = isNegative ? -double : double; return this._cursor === chunk.length ? - this._decodeDoubleExponent.bind(this, d, false, 0) : - this._decodeDoubleExponent(d, false, 0, chunk); + this._decodeDoubleExponent.bind(this, d) : + this._decodeDoubleExponent(d, chunk); case ASCII['\r']: this._cursor = cursor + 2; // skip \r\n From c56f628cf8881a3637dd6448324090aa854e2b33 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 12 Dec 2023 17:02:21 -0500 Subject: [PATCH 293/325] remove .only --- packages/client/lib/RESP/decoder.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index 5f0267911aa..d587aea43cd 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -69,7 +69,7 @@ function assertSpyCalls(spy: SinonSpy, replies?: Array) { } } -describe.only('RESP Decoder', () => { +describe('RESP Decoder', () => { test('Null', { toWrite: Buffer.from('_\r\n'), replies: [null] From f3631f8e73014de0fa2b9d9a8f222be909aaa97b Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 13 Dec 2023 12:27:29 -0500 Subject: [PATCH 294/325] improve decoder coverage + fix some bugs --- packages/client/lib/RESP/decoder.spec.ts | 122 +++++++++++++++++++++-- packages/client/lib/RESP/decoder.ts | 11 +- 2 files changed, 119 insertions(+), 14 deletions(-) diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index d587aea43cd..37945ff699d 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -1,8 +1,9 @@ import { strict as assert } from 'node:assert'; import { SinonSpy, spy } from 'sinon'; import { Decoder, RESP_TYPES } from './decoder'; -import { BlobError, ErrorReply, SimpleError } from '../errors'; +import { BlobError, SimpleError } from '../errors'; import { TypeMapping } from './types'; +import { VerbatimString } from './verbatim-string'; interface Test { toWrite: Buffer; @@ -107,6 +108,14 @@ describe('RESP Decoder', () => { toWrite: Buffer.from(':-1\r\n'), replies: [-1] }); + + test('1 as string', { + typeMapping: { + [RESP_TYPES.NUMBER]: String + }, + toWrite: Buffer.from(':1\r\n'), + replies: ['1'] + }); }); describe('BigNumber', () => { @@ -129,6 +138,14 @@ describe('RESP Decoder', () => { toWrite: Buffer.from('(-1\r\n'), replies: [-1n] }); + + test('1 as string', { + typeMapping: { + [RESP_TYPES.BIG_NUMBER]: String + }, + toWrite: Buffer.from('(1\r\n'), + replies: ['1'] + }); }); describe('Double', () => { @@ -182,15 +199,33 @@ describe('RESP Decoder', () => { replies: [1e1] }); - test('-1.1E1', { - toWrite: Buffer.from(',-1.1E1\r\n'), - replies: [-1.1E1] + test('-1.1E+1', { + toWrite: Buffer.from(',-1.1E+1\r\n'), + replies: [-1.1E+1] + }); + + test('1 as string', { + typeMapping: { + [RESP_TYPES.DOUBLE]: String + }, + toWrite: Buffer.from(',1\r\n'), + replies: ['1'] }); }); - test('SimpleString', { - toWrite: Buffer.from('+OK\r\n'), - replies: ['OK'] + describe('SimpleString', () => { + test("'OK'", { + toWrite: Buffer.from('+OK\r\n'), + replies: ['OK'] + }); + + test("'OK' as Buffer", { + typeMapping: { + [RESP_TYPES.SIMPLE_STRING]: Buffer + }, + toWrite: Buffer.from('+OK\r\n'), + replies: [Buffer.from('OK')] + }); }); describe('BlobString', () => { @@ -208,6 +243,14 @@ describe('RESP Decoder', () => { toWrite: Buffer.from('$-1\r\n'), replies: [null] }); + + test("'OK' as Buffer", { + typeMapping: { + [RESP_TYPES.BLOB_STRING]: Buffer + }, + toWrite: Buffer.from('$2\r\nOK\r\n'), + replies: [Buffer.from('OK')] + }); }); describe('VerbatimString', () => { @@ -220,6 +263,22 @@ describe('RESP Decoder', () => { toWrite: Buffer.from('=10\r\ntxt:123456\r\n'), replies: ['123456'] }); + + test("'OK' as VerbatimString", { + typeMapping: { + [RESP_TYPES.VERBATIM_STRING]: VerbatimString + }, + toWrite: Buffer.from('=6\r\ntxt:OK\r\n'), + replies: [new VerbatimString('txt', 'OK')] + }); + + test("'OK' as Buffer", { + typeMapping: { + [RESP_TYPES.VERBATIM_STRING]: Buffer + }, + toWrite: Buffer.from('=6\r\ntxt:OK\r\n'), + replies: [Buffer.from('OK')] + }); }); test('SimpleError', { @@ -256,9 +315,17 @@ describe('RESP Decoder', () => { }); test('of 0..9', { - toWrite: Buffer.from(`*10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), + toWrite: Buffer.from(`~10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), replies: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] }); + + test('0..9 as Set', { + typeMapping: { + [RESP_TYPES.SET]: Set + }, + toWrite: Buffer.from(`~10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), + replies: [new Set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])] + }); }); describe('Map', () => { @@ -282,5 +349,44 @@ describe('RESP Decoder', () => { 9: { value: '9', enumerable: true } })] }); + + test("{ '0'..'9': } as Map", { + typeMapping: { + [RESP_TYPES.MAP]: Map + }, + toWrite: Buffer.from(`%10\r\n+0\r\n+0\r\n+1\r\n+1\r\n+2\r\n+2\r\n+3\r\n+3\r\n+4\r\n+4\r\n+5\r\n+5\r\n+6\r\n+6\r\n+7\r\n+7\r\n+8\r\n+8\r\n+9\r\n+9\r\n`), + replies: [new Map([ + ['0', '0'], + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ['9', '9'] + ])] + }); + + test("{ '0'..'9': } as Array", { + typeMapping: { + [RESP_TYPES.MAP]: Array + }, + toWrite: Buffer.from(`%10\r\n+0\r\n+0\r\n+1\r\n+1\r\n+2\r\n+2\r\n+3\r\n+3\r\n+4\r\n+4\r\n+5\r\n+5\r\n+6\r\n+6\r\n+7\r\n+7\r\n+8\r\n+8\r\n+9\r\n+9\r\n`), + replies: [['0', '0', '1', '1', '2', '2', '3', '3', '4', '4', '5', '5', '6', '6', '7', '7', '8', '8', '9', '9']] + }); + }); + + describe('Push', () => { + test('[]', { + toWrite: Buffer.from('>0\r\n'), + pushReplies: [[]] + }); + + test('[0..9]', { + toWrite: Buffer.from(`>10\r\n:0\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n`), + pushReplies: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + }); }); }); diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 7c48f1f783f..7ca80634eb8 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -598,7 +598,7 @@ export class Decoder { private _continueDecodeVerbatimStringLength(lengthCb, type, chunk) { const length = lengthCb(chunk); - return typeof length === 'function'? + return typeof length === 'function' ? this._continueDecodeVerbatimStringLength.bind(this, length, type) : this._decodeVerbatimStringWithLength(length, type, chunk); } @@ -616,11 +616,10 @@ export class Decoder { } private _decodeVerbatimStringFormat(stringLength, chunk) { - return this._continueDecodeVerbatimStringFormat( - stringLength, - this._decodeStringWithLength.bind(this, 3, 1, String), - chunk - ); + const formatCb = this._decodeStringWithLength.bind(this, 3, 1, String); + return this._cursor >= chunk.length ? + this._continueDecodeVerbatimStringFormat.bind(this, stringLength, formatCb) : + this._continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk); } private _continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { From d1f50df192805628d3d9efd31de1d52cea60f4c0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Dec 2023 16:00:19 -0500 Subject: [PATCH 295/325] improve decoder tests coverage, use actual private ("#") instead of TypeScript private --- packages/client/lib/RESP/decoder.spec.ts | 40 +- packages/client/lib/RESP/decoder.ts | 681 +++++++++++------------ 2 files changed, 377 insertions(+), 344 deletions(-) diff --git a/packages/client/lib/RESP/decoder.spec.ts b/packages/client/lib/RESP/decoder.spec.ts index 37945ff699d..c034815c9cd 100644 --- a/packages/client/lib/RESP/decoder.spec.ts +++ b/packages/client/lib/RESP/decoder.spec.ts @@ -18,7 +18,7 @@ function test(name: string, config: Test) { it('single chunk', () => { const setup = setupTest(config); setup.decoder.write(config.toWrite); - assertCalls(config, setup); + assertSpiesCalls(config, setup); }); it('byte by byte', () => { @@ -26,7 +26,7 @@ function test(name: string, config: Test) { for (let i = 0; i < config.toWrite.length; i++) { setup.decoder.write(config.toWrite.subarray(i, i + 1)); } - assertCalls(config, setup); + assertSpiesCalls(config, setup); }); }) } @@ -49,7 +49,7 @@ function setupTest(config: Test) { }; } -function assertCalls(config: Test, spies: ReturnType) { +function assertSpiesCalls(config: Test, spies: ReturnType) { assertSpyCalls(spies.onReplySpy, config.replies); assertSpyCalls(spies.onErrorReplySpy, config.errorReplies); assertSpyCalls(spies.onPushSpy, config.pushReplies); @@ -302,6 +302,40 @@ describe('RESP Decoder', () => { replies: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] }); + test('with all types', { + toWrite: Buffer.from([ + '*13\r\n', + '_\r\n', + '#f\r\n', + ':0\r\n', + '(0\r\n', + ',0\r\n', + '+\r\n', + '$0\r\n\r\n', + '=4\r\ntxt:\r\n', + '-\r\n', + '!0\r\n\r\n', + '*0\r\n', + '~0\r\n', + '%0\r\n' + ].join('')), + replies: [[ + null, + false, + 0, + 0n, + 0, + '', + '', + '', + new SimpleError(''), + new BlobError(''), + [], + [], + Object.create(null) + ]] + }); + test('null (RESP2 backwards compatibility)', { toWrite: Buffer.from('*-1\r\n'), replies: [null] diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 7ca80634eb8..2485ea23b37 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -39,7 +39,6 @@ export const PUSH_TYPE_MAPPING = { }; // this was written with performance in mind, so it's not very readable... sorry :( -// using `private _` instead of `#` to boost performance interface DecoderOptions { onReply(reply: any): unknown; @@ -53,8 +52,8 @@ export class Decoder { onErrorReply; onPush; getTypeMapping; - private _cursor = 0; - private _next; + #cursor = 0; + #next; constructor(config: DecoderOptions) { this.onReply = config.onReply; @@ -64,142 +63,142 @@ export class Decoder { } reset() { - this._cursor = 0; - this._next = undefined; + this.#cursor = 0; + this.#next = undefined; } write(chunk) { - if (this._cursor >= chunk.length) { - this._cursor -= chunk.length; + if (this.#cursor >= chunk.length) { + this.#cursor -= chunk.length; return; } - if (this._next) { - if (this._next(chunk) || this._cursor >= chunk.length) { - this._cursor -= chunk.length; + if (this.#next) { + if (this.#next(chunk) || this.#cursor >= chunk.length) { + this.#cursor -= chunk.length; return; } } do { - const type = chunk[this._cursor]; - if (++this._cursor === chunk.length) { - this._next = this._continueDecodeTypeValue.bind(this, type); + const type = chunk[this.#cursor]; + if (++this.#cursor === chunk.length) { + this.#next = this.#continueDecodeTypeValue.bind(this, type); break; } - if (this._decodeTypeValue(type, chunk)) { + if (this.#decodeTypeValue(type, chunk)) { break; } - } while (this._cursor < chunk.length); - this._cursor -= chunk.length; + } while (this.#cursor < chunk.length); + this.#cursor -= chunk.length; } - private _continueDecodeTypeValue(type, chunk) { - this._next = undefined; - return this._decodeTypeValue(type, chunk); + #continueDecodeTypeValue(type, chunk) { + this.#next = undefined; + return this.#decodeTypeValue(type, chunk); } - private _decodeTypeValue(type, chunk) { + #decodeTypeValue(type, chunk) { switch (type) { case RESP_TYPES.NULL: - this.onReply(this._decodeNull()); + this.onReply(this.#decodeNull()); return false; case RESP_TYPES.BOOLEAN: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeBoolean(chunk) + this.#decodeBoolean(chunk) ); case RESP_TYPES.NUMBER: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeNumber( + this.#decodeNumber( this.getTypeMapping()[RESP_TYPES.NUMBER], chunk ) ); case RESP_TYPES.BIG_NUMBER: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeBigNumber( + this.#decodeBigNumber( this.getTypeMapping()[RESP_TYPES.BIG_NUMBER], chunk ) ); case RESP_TYPES.DOUBLE: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeDouble( + this.#decodeDouble( this.getTypeMapping()[RESP_TYPES.DOUBLE], chunk ) ); case RESP_TYPES.SIMPLE_STRING: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeSimpleString( + this.#decodeSimpleString( this.getTypeMapping()[RESP_TYPES.SIMPLE_STRING], chunk ) ); case RESP_TYPES.BLOB_STRING: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeBlobString( + this.#decodeBlobString( this.getTypeMapping()[RESP_TYPES.BLOB_STRING], chunk ) ); case RESP_TYPES.VERBATIM_STRING: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeVerbatimString( + this.#decodeVerbatimString( this.getTypeMapping()[RESP_TYPES.VERBATIM_STRING], chunk ) ); case RESP_TYPES.SIMPLE_ERROR: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onErrorReply, - this._decodeSimpleError(chunk) + this.#decodeSimpleError(chunk) ); case RESP_TYPES.BLOB_ERROR: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onErrorReply, - this._decodeBlobError(chunk) + this.#decodeBlobError(chunk) ); case RESP_TYPES.ARRAY: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeArray(this.getTypeMapping(), chunk) + this.#decodeArray(this.getTypeMapping(), chunk) ); case RESP_TYPES.SET: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeSet(this.getTypeMapping(), chunk) + this.#decodeSet(this.getTypeMapping(), chunk) ); case RESP_TYPES.MAP: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onReply, - this._decodeMap(this.getTypeMapping(), chunk) + this.#decodeMap(this.getTypeMapping(), chunk) ); case RESP_TYPES.PUSH: - return this._handleDecodedValue( + return this.#handleDecodedValue( this.onPush, - this._decodeArray(PUSH_TYPE_MAPPING, chunk) + this.#decodeArray(PUSH_TYPE_MAPPING, chunk) ); default: @@ -207,9 +206,9 @@ export class Decoder { } } - private _handleDecodedValue(cb, value) { + #handleDecodedValue(cb, value) { if (typeof value === 'function') { - this._next = this._continueDecodeValue.bind(this, cb, value); + this.#next = this.#continueDecodeValue.bind(this, cb, value); return true; } @@ -217,179 +216,179 @@ export class Decoder { return false; } - private _continueDecodeValue(cb, next, chunk) { - this._next = undefined; - return this._handleDecodedValue(cb, next(chunk)); + #continueDecodeValue(cb, next, chunk) { + this.#next = undefined; + return this.#handleDecodedValue(cb, next(chunk)); } - private _decodeNull() { - this._cursor += 2; // skip \r\n + #decodeNull() { + this.#cursor += 2; // skip \r\n return null; } - private _decodeBoolean(chunk) { - const boolean = chunk[this._cursor] === ASCII.t; - this._cursor += 3; // skip {t | f}\r\n + #decodeBoolean(chunk) { + const boolean = chunk[this.#cursor] === ASCII.t; + this.#cursor += 3; // skip {t | f}\r\n return boolean; } - private _decodeNumber(type, chunk) { + #decodeNumber(type, chunk) { if (type === String) { - return this._decodeSimpleString(String, chunk); + return this.#decodeSimpleString(String, chunk); } - switch (chunk[this._cursor]) { + switch (chunk[this.#cursor]) { case ASCII['+']: - return this._maybeDecodeNumberValue(false, chunk); + return this.#maybeDecodeNumberValue(false, chunk); case ASCII['-']: - return this._maybeDecodeNumberValue(true, chunk); + return this.#maybeDecodeNumberValue(true, chunk); default: - return this._decodeNumberValue( + return this.#decodeNumberValue( false, - this._decodeUnsingedNumber.bind(this, 0), + this.#decodeUnsingedNumber.bind(this, 0), chunk ); } } - private _maybeDecodeNumberValue(isNegative, chunk) { - const cb = this._decodeUnsingedNumber.bind(this, 0); - return ++this._cursor === chunk.length ? - this._decodeNumberValue.bind(this, isNegative, cb) : - this._decodeNumberValue(isNegative, cb, chunk); + #maybeDecodeNumberValue(isNegative, chunk) { + const cb = this.#decodeUnsingedNumber.bind(this, 0); + return ++this.#cursor === chunk.length ? + this.#decodeNumberValue.bind(this, isNegative, cb) : + this.#decodeNumberValue(isNegative, cb, chunk); } - private _decodeNumberValue(isNegative, numberCb, chunk) { + #decodeNumberValue(isNegative, numberCb, chunk) { const number = numberCb(chunk); return typeof number === 'function' ? - this._decodeNumberValue.bind(this, isNegative, number) : + this.#decodeNumberValue.bind(this, isNegative, number) : isNegative ? -number : number; } - private _decodeUnsingedNumber(number, chunk) { - let cursor = this._cursor; + #decodeUnsingedNumber(number, chunk) { + let cursor = this.#cursor; do { const byte = chunk[cursor]; if (byte === ASCII['\r']) { - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return number; } number = number * 10 + byte - ASCII['0']; } while (++cursor < chunk.length); - this._cursor = cursor; - return this._decodeUnsingedNumber.bind(this, number); + this.#cursor = cursor; + return this.#decodeUnsingedNumber.bind(this, number); } - private _decodeBigNumber(type, chunk) { + #decodeBigNumber(type, chunk) { if (type === String) { - return this._decodeSimpleString(String, chunk); + return this.#decodeSimpleString(String, chunk); } - switch (chunk[this._cursor]) { + switch (chunk[this.#cursor]) { case ASCII['+']: - return this._maybeDecodeBigNumberValue(false, chunk); + return this.#maybeDecodeBigNumberValue(false, chunk); case ASCII['-']: - return this._maybeDecodeBigNumberValue(true, chunk); + return this.#maybeDecodeBigNumberValue(true, chunk); default: - return this._decodeBigNumberValue( + return this.#decodeBigNumberValue( false, - this._decodeUnsingedBigNumber.bind(this, 0n), + this.#decodeUnsingedBigNumber.bind(this, 0n), chunk ); } } - private _maybeDecodeBigNumberValue(isNegative, chunk) { - const cb = this._decodeUnsingedBigNumber.bind(this, 0n); - return ++this._cursor === chunk.length ? - this._decodeBigNumberValue.bind(this, isNegative, cb) : - this._decodeBigNumberValue(isNegative, cb, chunk); + #maybeDecodeBigNumberValue(isNegative, chunk) { + const cb = this.#decodeUnsingedBigNumber.bind(this, 0n); + return ++this.#cursor === chunk.length ? + this.#decodeBigNumberValue.bind(this, isNegative, cb) : + this.#decodeBigNumberValue(isNegative, cb, chunk); } - private _decodeBigNumberValue(isNegative, bigNumberCb, chunk) { + #decodeBigNumberValue(isNegative, bigNumberCb, chunk) { const bigNumber = bigNumberCb(chunk); return typeof bigNumber === 'function' ? - this._decodeBigNumberValue.bind(this, isNegative, bigNumber) : + this.#decodeBigNumberValue.bind(this, isNegative, bigNumber) : isNegative ? -bigNumber : bigNumber; } - private _decodeUnsingedBigNumber(bigNumber, chunk) { - let cursor = this._cursor; + #decodeUnsingedBigNumber(bigNumber, chunk) { + let cursor = this.#cursor; do { const byte = chunk[cursor]; if (byte === ASCII['\r']) { - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return bigNumber; } bigNumber = bigNumber * 10n + BigInt(byte - ASCII['0']); } while (++cursor < chunk.length); - this._cursor = cursor; - return this._decodeUnsingedBigNumber.bind(this, bigNumber); + this.#cursor = cursor; + return this.#decodeUnsingedBigNumber.bind(this, bigNumber); } - private _decodeDouble(type, chunk) { + #decodeDouble(type, chunk) { if (type === String) { - return this._decodeSimpleString(String, chunk); + return this.#decodeSimpleString(String, chunk); } - switch (chunk[this._cursor]) { + switch (chunk[this.#cursor]) { case ASCII.n: - this._cursor += 5; // skip nan\r\n + this.#cursor += 5; // skip nan\r\n return NaN; case ASCII['+']: - return this._maybeDecodeDoubleInteger(false, chunk); + return this.#maybeDecodeDoubleInteger(false, chunk); case ASCII['-']: - return this._maybeDecodeDoubleInteger(true, chunk); + return this.#maybeDecodeDoubleInteger(true, chunk); default: - return this._decodeDoubleInteger(false, 0, chunk); + return this.#decodeDoubleInteger(false, 0, chunk); } } - private _maybeDecodeDoubleInteger(isNegative, chunk) { - return ++this._cursor === chunk.length ? - this._decodeDoubleInteger.bind(this, isNegative, 0) : - this._decodeDoubleInteger(isNegative, 0, chunk); + #maybeDecodeDoubleInteger(isNegative, chunk) { + return ++this.#cursor === chunk.length ? + this.#decodeDoubleInteger.bind(this, isNegative, 0) : + this.#decodeDoubleInteger(isNegative, 0, chunk); } - private _decodeDoubleInteger(isNegative, integer, chunk) { - if (chunk[this._cursor] === ASCII.i) { - this._cursor += 5; // skip inf\r\n + #decodeDoubleInteger(isNegative, integer, chunk) { + if (chunk[this.#cursor] === ASCII.i) { + this.#cursor += 5; // skip inf\r\n return isNegative ? -Infinity : Infinity; } - return this._continueDecodeDoubleInteger(isNegative, integer, chunk); + return this.#continueDecodeDoubleInteger(isNegative, integer, chunk); } - private _continueDecodeDoubleInteger(isNegative, integer, chunk) { - let cursor = this._cursor; + #continueDecodeDoubleInteger(isNegative, integer, chunk) { + let cursor = this.#cursor; do { const byte = chunk[cursor]; switch (byte) { case ASCII['.']: - this._cursor = cursor + 1; // skip . - return this._cursor < chunk.length ? - this._decodeDoubleDecimal(isNegative, 0, integer, chunk) : - this._decodeDoubleDecimal.bind(this, isNegative, 0, integer); + this.#cursor = cursor + 1; // skip . + return this.#cursor < chunk.length ? + this.#decodeDoubleDecimal(isNegative, 0, integer, chunk) : + this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer); case ASCII.E: case ASCII.e: - this._cursor = cursor + 1; // skip E/e + this.#cursor = cursor + 1; // skip E/e const i = isNegative ? -integer : integer; - return this._cursor < chunk.length ? - this._decodeDoubleExponent(i, chunk) : - this._decodeDoubleExponent.bind(this, i); + return this.#cursor < chunk.length ? + this.#decodeDoubleExponent(i, chunk) : + this.#decodeDoubleExponent.bind(this, i); case ASCII['\r']: - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return isNegative ? -integer : integer; default: @@ -397,95 +396,95 @@ export class Decoder { } } while (++cursor < chunk.length); - this._cursor = cursor; - return this._continueDecodeDoubleInteger.bind(this, isNegative, integer); + this.#cursor = cursor; + return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer); } // Precalculated multipliers for decimal points to improve performance // "... about 15 to 17 decimal places ..." // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#:~:text=about%2015%20to%2017%20decimal%20places - static _DOUBLE_DECIMAL_MULTIPLIERS = [ + static #DOUBLE_DECIMAL_MULTIPLIERS = [ 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17 ]; - private _decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { - let cursor = this._cursor; + #decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { + let cursor = this.#cursor; do { const byte = chunk[cursor]; switch (byte) { case ASCII.E: case ASCII.e: - this._cursor = cursor + 1; // skip E/e + this.#cursor = cursor + 1; // skip E/e const d = isNegative ? -double : double; - return this._cursor === chunk.length ? - this._decodeDoubleExponent.bind(this, d) : - this._decodeDoubleExponent(d, chunk); + return this.#cursor === chunk.length ? + this.#decodeDoubleExponent.bind(this, d) : + this.#decodeDoubleExponent(d, chunk); case ASCII['\r']: - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return isNegative ? -double : double; } - if (decimalIndex < Decoder._DOUBLE_DECIMAL_MULTIPLIERS.length) { - double += (byte - ASCII['0']) * Decoder._DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; + if (decimalIndex < Decoder.#DOUBLE_DECIMAL_MULTIPLIERS.length) { + double += (byte - ASCII['0']) * Decoder.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; } } while (++cursor < chunk.length); - this._cursor = cursor; - return this._decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); + this.#cursor = cursor; + return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); } - private _decodeDoubleExponent(double, chunk) { - switch (chunk[this._cursor]) { + #decodeDoubleExponent(double, chunk) { + switch (chunk[this.#cursor]) { case ASCII['+']: - return ++this._cursor === chunk.length ? - this._continueDecodeDoubleExponent.bind(this, false, double, 0) : - this._continueDecodeDoubleExponent(false, double, 0, chunk); + return ++this.#cursor === chunk.length ? + this.#continueDecodeDoubleExponent.bind(this, false, double, 0) : + this.#continueDecodeDoubleExponent(false, double, 0, chunk); case ASCII['-']: - return ++this._cursor === chunk.length ? - this._continueDecodeDoubleExponent.bind(this, true, double, 0) : - this._continueDecodeDoubleExponent(true, double, 0, chunk); + return ++this.#cursor === chunk.length ? + this.#continueDecodeDoubleExponent.bind(this, true, double, 0) : + this.#continueDecodeDoubleExponent(true, double, 0, chunk); } - return this._continueDecodeDoubleExponent(false, double, 0, chunk); + return this.#continueDecodeDoubleExponent(false, double, 0, chunk); } - private _continueDecodeDoubleExponent(isNegative, double, exponent, chunk) { - let cursor = this._cursor; + #continueDecodeDoubleExponent(isNegative, double, exponent, chunk) { + let cursor = this.#cursor; do { const byte = chunk[cursor]; if (byte === ASCII['\r']) { - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return double * 10 ** (isNegative ? -exponent : exponent); } exponent = exponent * 10 + byte - ASCII['0']; } while (++cursor < chunk.length); - this._cursor = cursor; - return this._continueDecodeDoubleExponent.bind(this, isNegative, double, exponent); + this.#cursor = cursor; + return this.#continueDecodeDoubleExponent.bind(this, isNegative, double, exponent); } - private _findCRLF(chunk, cursor) { + #findCRLF(chunk, cursor) { while (chunk[cursor] !== ASCII['\r']) { if (++cursor === chunk.length) { - this._cursor = chunk.length; + this.#cursor = chunk.length; return -1; } } - this._cursor = cursor + 2; // skip \r\n + this.#cursor = cursor + 2; // skip \r\n return cursor; } - private _decodeSimpleString(type, chunk) { - const start = this._cursor, - crlfIndex = this._findCRLF(chunk, start); + #decodeSimpleString(type, chunk) { + const start = this.#cursor, + crlfIndex = this.#findCRLF(chunk, start); if (crlfIndex === -1) { - return this._continueDecodeSimpleString.bind( + return this.#continueDecodeSimpleString.bind( this, [chunk.subarray(start)], type @@ -498,12 +497,12 @@ export class Decoder { slice.toString(); } - private _continueDecodeSimpleString(chunks, type, chunk) { - const start = this._cursor, - crlfIndex = this._findCRLF(chunk, start); + #continueDecodeSimpleString(chunks, type, chunk) { + const start = this.#cursor, + crlfIndex = this.#findCRLF(chunk, start); if (crlfIndex === -1) { chunks.push(chunk.subarray(start)); - return this._continueDecodeSimpleString.bind(this, chunks, type); + return this.#continueDecodeSimpleString.bind(this, chunks, type); } chunks.push(chunk.subarray(start, crlfIndex)); @@ -512,41 +511,41 @@ export class Decoder { chunks.join(''); } - private _decodeBlobString(type, chunk) { + #decodeBlobString(type, chunk) { // RESP 2 bulk string null // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-bulk-strings - if (chunk[this._cursor] === ASCII['-']) { - this._cursor += 4; // skip -1\r\n + if (chunk[this.#cursor] === ASCII['-']) { + this.#cursor += 4; // skip -1\r\n return null; } - const length = this._decodeUnsingedNumber(0, chunk); + const length = this.#decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeBlobStringLength.bind(this, length, type); - } else if (this._cursor >= chunk.length) { - return this._decodeBlobStringWithLength.bind(this, length, type); + return this.#continueDecodeBlobStringLength.bind(this, length, type); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length, type); } - return this._decodeBlobStringWithLength(length, type, chunk); + return this.#decodeBlobStringWithLength(length, type, chunk); } - private _continueDecodeBlobStringLength(lengthCb, type, chunk) { + #continueDecodeBlobStringLength(lengthCb, type, chunk) { const length = lengthCb(chunk); if (typeof length === 'function') { - return this._continueDecodeBlobStringLength.bind(this, length, type); - } else if (this._cursor >= chunk.length) { - return this._decodeBlobStringWithLength.bind(this, length, type); + return this.#continueDecodeBlobStringLength.bind(this, length, type); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length, type); } - return this._decodeBlobStringWithLength(length, type, chunk); + return this.#decodeBlobStringWithLength(length, type, chunk); } - private _decodeStringWithLength(length, skip, type, chunk) { - const end = this._cursor + length; + #decodeStringWithLength(length, skip, type, chunk) { + const end = this.#cursor + length; if (end >= chunk.length) { - const slice = chunk.subarray(this._cursor); - this._cursor = chunk.length; - return this._continueDecodeStringWithLength.bind( + const slice = chunk.subarray(this.#cursor); + this.#cursor = chunk.length; + return this.#continueDecodeStringWithLength.bind( this, length - slice.length, [slice], @@ -555,20 +554,20 @@ export class Decoder { ); } - const slice = chunk.subarray(this._cursor, end); - this._cursor = end + skip; + const slice = chunk.subarray(this.#cursor, end); + this.#cursor = end + skip; return type === Buffer ? slice : slice.toString(); } - private _continueDecodeStringWithLength(length, chunks, skip, type, chunk) { - const end = this._cursor + length; + #continueDecodeStringWithLength(length, chunks, skip, type, chunk) { + const end = this.#cursor + length; if (end >= chunk.length) { - const slice = chunk.subarray(this._cursor); + const slice = chunk.subarray(this.#cursor); chunks.push(slice); - this._cursor = chunk.length; - return this._continueDecodeStringWithLength.bind( + this.#cursor = chunk.length; + return this.#continueDecodeStringWithLength.bind( this, length - slice.length, chunks, @@ -577,173 +576,173 @@ export class Decoder { ); } - chunks.push(chunk.subarray(this._cursor, end)); - this._cursor = end + skip; + chunks.push(chunk.subarray(this.#cursor, end)); + this.#cursor = end + skip; return type === Buffer ? Buffer.concat(chunks) : chunks.join(''); } - private _decodeBlobStringWithLength(length, type, chunk) { - return this._decodeStringWithLength(length, 2, type, chunk); + #decodeBlobStringWithLength(length, type, chunk) { + return this.#decodeStringWithLength(length, 2, type, chunk); } - private _decodeVerbatimString(type, chunk) { - return this._continueDecodeVerbatimStringLength( - this._decodeUnsingedNumber.bind(this, 0), + #decodeVerbatimString(type, chunk) { + return this.#continueDecodeVerbatimStringLength( + this.#decodeUnsingedNumber.bind(this, 0), type, chunk ); } - private _continueDecodeVerbatimStringLength(lengthCb, type, chunk) { + #continueDecodeVerbatimStringLength(lengthCb, type, chunk) { const length = lengthCb(chunk); return typeof length === 'function' ? - this._continueDecodeVerbatimStringLength.bind(this, length, type) : - this._decodeVerbatimStringWithLength(length, type, chunk); + this.#continueDecodeVerbatimStringLength.bind(this, length, type) : + this.#decodeVerbatimStringWithLength(length, type, chunk); } - private _decodeVerbatimStringWithLength(length, type, chunk) { + #decodeVerbatimStringWithLength(length, type, chunk) { const stringLength = length - 4; // skip : if (type === VerbatimString) { - return this._decodeVerbatimStringFormat(stringLength, chunk); + return this.#decodeVerbatimStringFormat(stringLength, chunk); } - this._cursor += 4; // skip : - return this._cursor >= chunk.length ? - this._decodeBlobStringWithLength.bind(this, stringLength, type) : - this._decodeBlobStringWithLength(stringLength, type, chunk); + this.#cursor += 4; // skip : + return this.#cursor >= chunk.length ? + this.#decodeBlobStringWithLength.bind(this, stringLength, type) : + this.#decodeBlobStringWithLength(stringLength, type, chunk); } - private _decodeVerbatimStringFormat(stringLength, chunk) { - const formatCb = this._decodeStringWithLength.bind(this, 3, 1, String); - return this._cursor >= chunk.length ? - this._continueDecodeVerbatimStringFormat.bind(this, stringLength, formatCb) : - this._continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk); + #decodeVerbatimStringFormat(stringLength, chunk) { + const formatCb = this.#decodeStringWithLength.bind(this, 3, 1, String); + return this.#cursor >= chunk.length ? + this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, formatCb) : + this.#continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk); } - private _continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { + #continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { const format = formatCb(chunk); return typeof format === 'function' ? - this._continueDecodeVerbatimStringFormat.bind(this, stringLength, format) : - this._decodeVerbatimStringWithFormat(stringLength, format, chunk); + this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, format) : + this.#decodeVerbatimStringWithFormat(stringLength, format, chunk); } - private _decodeVerbatimStringWithFormat(stringLength, format, chunk) { - return this._continueDecodeVerbatimStringWithFormat( + #decodeVerbatimStringWithFormat(stringLength, format, chunk) { + return this.#continueDecodeVerbatimStringWithFormat( format, - this._decodeBlobStringWithLength.bind(this, stringLength, String), + this.#decodeBlobStringWithLength.bind(this, stringLength, String), chunk ); } - private _continueDecodeVerbatimStringWithFormat(format, stringCb, chunk) { + #continueDecodeVerbatimStringWithFormat(format, stringCb, chunk) { const string = stringCb(chunk); return typeof string === 'function' ? - this._continueDecodeVerbatimStringWithFormat.bind(this, format, string) : + this.#continueDecodeVerbatimStringWithFormat.bind(this, format, string) : new VerbatimString(format, string); } - private _decodeSimpleError(chunk) { - const string = this._decodeSimpleString(String, chunk); + #decodeSimpleError(chunk) { + const string = this.#decodeSimpleString(String, chunk); return typeof string === 'function' ? - this._continueDecodeSimpleError.bind(this, string) : + this.#continueDecodeSimpleError.bind(this, string) : new SimpleError(string); } - private _continueDecodeSimpleError(stringCb, chunk) { + #continueDecodeSimpleError(stringCb, chunk) { const string = stringCb(chunk); return typeof string === 'function' ? - this._continueDecodeSimpleError.bind(this, string) : + this.#continueDecodeSimpleError.bind(this, string) : new SimpleError(string); } - private _decodeBlobError(chunk) { - const string = this._decodeBlobString(String, chunk); + #decodeBlobError(chunk) { + const string = this.#decodeBlobString(String, chunk); return typeof string === 'function' ? - this._continueDecodeBlobError.bind(this, string) : + this.#continueDecodeBlobError.bind(this, string) : new BlobError(string); } - private _continueDecodeBlobError(stringCb, chunk) { + #continueDecodeBlobError(stringCb, chunk) { const string = stringCb(chunk); return typeof string === 'function' ? - this._continueDecodeBlobError.bind(this, string) : + this.#continueDecodeBlobError.bind(this, string) : new BlobError(string); } - private _decodeNestedType(typeMapping, chunk) { - const type = chunk[this._cursor]; - return ++this._cursor === chunk.length ? - this._decodeNestedTypeValue.bind(this, type, typeMapping) : - this._decodeNestedTypeValue(type, typeMapping, chunk); + #decodeNestedType(typeMapping, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? + this.#decodeNestedTypeValue.bind(this, type, typeMapping) : + this.#decodeNestedTypeValue(type, typeMapping, chunk); } - private _decodeNestedTypeValue(type, typeMapping, chunk) { + #decodeNestedTypeValue(type, typeMapping, chunk) { switch (type) { case RESP_TYPES.NULL: - return this._decodeNull(); + return this.#decodeNull(); case RESP_TYPES.BOOLEAN: - return this._decodeBoolean(chunk); + return this.#decodeBoolean(chunk); case RESP_TYPES.NUMBER: - return this._decodeNumber(typeMapping[RESP_TYPES.NUMBER], chunk); + return this.#decodeNumber(typeMapping[RESP_TYPES.NUMBER], chunk); case RESP_TYPES.BIG_NUMBER: - return this._decodeBigNumber(typeMapping[RESP_TYPES.BIG_NUMBER], chunk); + return this.#decodeBigNumber(typeMapping[RESP_TYPES.BIG_NUMBER], chunk); case RESP_TYPES.DOUBLE: - return this._decodeDouble(typeMapping[RESP_TYPES.DOUBLE], chunk); + return this.#decodeDouble(typeMapping[RESP_TYPES.DOUBLE], chunk); case RESP_TYPES.SIMPLE_STRING: - return this._decodeSimpleString(typeMapping[RESP_TYPES.SIMPLE_STRING], chunk); + return this.#decodeSimpleString(typeMapping[RESP_TYPES.SIMPLE_STRING], chunk); case RESP_TYPES.BLOB_STRING: - return this._decodeBlobString(typeMapping[RESP_TYPES.BLOB_STRING], chunk); + return this.#decodeBlobString(typeMapping[RESP_TYPES.BLOB_STRING], chunk); case RESP_TYPES.VERBATIM_STRING: - return this._decodeVerbatimString(typeMapping[RESP_TYPES.VERBATIM_STRING], chunk); + return this.#decodeVerbatimString(typeMapping[RESP_TYPES.VERBATIM_STRING], chunk); case RESP_TYPES.SIMPLE_ERROR: - return this._decodeSimpleError(chunk); + return this.#decodeSimpleError(chunk); case RESP_TYPES.BLOB_ERROR: - return this._decodeBlobError(chunk); + return this.#decodeBlobError(chunk); case RESP_TYPES.ARRAY: - return this._decodeArray(typeMapping, chunk); + return this.#decodeArray(typeMapping, chunk); case RESP_TYPES.SET: - return this._decodeSet(typeMapping, chunk); + return this.#decodeSet(typeMapping, chunk); case RESP_TYPES.MAP: - return this._decodeMap(typeMapping, chunk); + return this.#decodeMap(typeMapping, chunk); default: throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); } } - private _decodeArray(typeMapping, chunk) { + #decodeArray(typeMapping, chunk) { // RESP 2 null // https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md#resp-arrays - if (chunk[this._cursor] === ASCII['-']) { - this._cursor += 4; // skip -1\r\n + if (chunk[this.#cursor] === ASCII['-']) { + this.#cursor += 4; // skip -1\r\n return null; } - return this._decodeArrayWithLength( - this._decodeUnsingedNumber(0, chunk), + return this.#decodeArrayWithLength( + this.#decodeUnsingedNumber(0, chunk), typeMapping, chunk ); } - private _decodeArrayWithLength(length, typeMapping, chunk) { + #decodeArrayWithLength(length, typeMapping, chunk) { return typeof length === 'function' ? - this._continueDecodeArrayLength.bind(this, length, typeMapping) : - this._decodeArrayItems( + this.#continueDecodeArrayLength.bind(this, length, typeMapping) : + this.#decodeArrayItems( new Array(length), 0, typeMapping, @@ -751,18 +750,18 @@ export class Decoder { ); } - private _continueDecodeArrayLength(lengthCb, typeMapping, chunk) { - return this._decodeArrayWithLength( + #continueDecodeArrayLength(lengthCb, typeMapping, chunk) { + return this.#decodeArrayWithLength( lengthCb(chunk), typeMapping, chunk ); } - private _decodeArrayItems(array, filled, typeMapping, chunk) { + #decodeArrayItems(array, filled, typeMapping, chunk) { for (let i = filled; i < array.length; i++) { - if (this._cursor >= chunk.length) { - return this._decodeArrayItems.bind( + if (this.#cursor >= chunk.length) { + return this.#decodeArrayItems.bind( this, array, i, @@ -770,9 +769,9 @@ export class Decoder { ); } - const item = this._decodeNestedType(typeMapping, chunk); + const item = this.#decodeNestedType(typeMapping, chunk); if (typeof item === 'function') { - return this._continueDecodeArrayItems.bind( + return this.#continueDecodeArrayItems.bind( this, array, i, @@ -787,10 +786,10 @@ export class Decoder { return array; } - private _continueDecodeArrayItems(array, filled, itemCb, typeMapping, chunk) { + #continueDecodeArrayItems(array, filled, itemCb, typeMapping, chunk) { const item = itemCb(chunk); if (typeof item === 'function') { - return this._continueDecodeArrayItems.bind( + return this.#continueDecodeArrayItems.bind( this, array, filled, @@ -801,38 +800,38 @@ export class Decoder { array[filled++] = item; - return this._decodeArrayItems(array, filled, typeMapping, chunk); + return this.#decodeArrayItems(array, filled, typeMapping, chunk); } - private _decodeSet(typeMapping, chunk) { - const length = this._decodeUnsingedNumber(0, chunk); + #decodeSet(typeMapping, chunk) { + const length = this.#decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeSetLength.bind(this, length, typeMapping); + return this.#continueDecodeSetLength.bind(this, length, typeMapping); } - return this._decodeSetItems( + return this.#decodeSetItems( length, typeMapping, chunk ); } - private _continueDecodeSetLength(lengthCb, typeMapping, chunk) { + #continueDecodeSetLength(lengthCb, typeMapping, chunk) { const length = lengthCb(chunk); return typeof length === 'function' ? - this._continueDecodeSetLength.bind(this, length, typeMapping) : - this._decodeSetItems(length, typeMapping, chunk); + this.#continueDecodeSetLength.bind(this, length, typeMapping) : + this.#decodeSetItems(length, typeMapping, chunk); } - private _decodeSetItems(length, typeMapping, chunk) { + #decodeSetItems(length, typeMapping, chunk) { return typeMapping[RESP_TYPES.SET] === Set ? - this._decodeSetAsSet( + this.#decodeSetAsSet( new Set(), length, typeMapping, chunk ) : - this._decodeArrayItems( + this.#decodeArrayItems( new Array(length), 0, typeMapping, @@ -840,11 +839,11 @@ export class Decoder { ); } - private _decodeSetAsSet(set, remaining, typeMapping, chunk) { + #decodeSetAsSet(set, remaining, typeMapping, chunk) { // using `remaining` instead of `length` & `set.size` to make it work even if the set contains duplicates while (remaining > 0) { - if (this._cursor >= chunk.length) { - return this._decodeSetAsSet.bind( + if (this.#cursor >= chunk.length) { + return this.#decodeSetAsSet.bind( this, set, remaining, @@ -852,9 +851,9 @@ export class Decoder { ); } - const item = this._decodeNestedType(typeMapping, chunk); + const item = this.#decodeNestedType(typeMapping, chunk); if (typeof item === 'function') { - return this._continueDecodeSetAsSet.bind( + return this.#continueDecodeSetAsSet.bind( this, set, remaining, @@ -870,10 +869,10 @@ export class Decoder { return set; } - private _continueDecodeSetAsSet(set, remaining, itemCb, typeMapping, chunk) { + #continueDecodeSetAsSet(set, remaining, itemCb, typeMapping, chunk) { const item = itemCb(chunk); if (typeof item === 'function') { - return this._continueDecodeSetAsSet.bind( + return this.#continueDecodeSetAsSet.bind( this, set, remaining, @@ -884,33 +883,33 @@ export class Decoder { set.add(item); - return this._decodeSetAsSet(set, remaining - 1, typeMapping, chunk); + return this.#decodeSetAsSet(set, remaining - 1, typeMapping, chunk); } - private _decodeMap(typeMapping, chunk) { - const length = this._decodeUnsingedNumber(0, chunk); + #decodeMap(typeMapping, chunk) { + const length = this.#decodeUnsingedNumber(0, chunk); if (typeof length === 'function') { - return this._continueDecodeMapLength.bind(this, length, typeMapping); + return this.#continueDecodeMapLength.bind(this, length, typeMapping); } - return this._decodeMapItems( + return this.#decodeMapItems( length, typeMapping, chunk ); } - private _continueDecodeMapLength(lengthCb, typeMapping, chunk) { + #continueDecodeMapLength(lengthCb, typeMapping, chunk) { const length = lengthCb(chunk); return typeof length === 'function' ? - this._continueDecodeMapLength.bind(this, length, typeMapping) : - this._decodeMapItems(length, typeMapping, chunk); + this.#continueDecodeMapLength.bind(this, length, typeMapping) : + this.#decodeMapItems(length, typeMapping, chunk); } - private _decodeMapItems(length, typeMapping, chunk) { + #decodeMapItems(length, typeMapping, chunk) { switch (typeMapping[RESP_TYPES.MAP]) { case Map: - return this._decodeMapAsMap( + return this.#decodeMapAsMap( new Map(), length, typeMapping, @@ -918,7 +917,7 @@ export class Decoder { ); case Array: - return this._decodeArrayItems( + return this.#decodeArrayItems( new Array(length * 2), 0, typeMapping, @@ -926,7 +925,7 @@ export class Decoder { ); default: - return this._decodeMapAsObject( + return this.#decodeMapAsObject( Object.create(null), length, typeMapping, @@ -935,11 +934,11 @@ export class Decoder { } } - private _decodeMapAsMap(map, remaining, typeMapping, chunk) { + #decodeMapAsMap(map, remaining, typeMapping, chunk) { // using `remaining` instead of `length` & `map.size` to make it work even if the map contains duplicate keys while (remaining > 0) { - if (this._cursor >= chunk.length) { - return this._decodeMapAsMap.bind( + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsMap.bind( this, map, remaining, @@ -947,9 +946,9 @@ export class Decoder { ); } - const key = this._decodeMapKey(typeMapping, chunk); + const key = this.#decodeMapKey(typeMapping, chunk); if (typeof key === 'function') { - return this._continueDecodeMapKey.bind( + return this.#continueDecodeMapKey.bind( this, map, remaining, @@ -958,20 +957,20 @@ export class Decoder { ); } - if (this._cursor >= chunk.length) { - return this._continueDecodeMapValue.bind( + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind( this, map, remaining, key, - this._decodeNestedType.bind(this, typeMapping), + this.#decodeNestedType.bind(this, typeMapping), typeMapping ); } - const value = this._decodeNestedType(typeMapping, chunk); + const value = this.#decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { - return this._continueDecodeMapValue.bind( + return this.#continueDecodeMapValue.bind( this, map, remaining, @@ -988,32 +987,32 @@ export class Decoder { return map; } - private _decodeMapKey(typeMapping, chunk) { - const type = chunk[this._cursor]; - return ++this._cursor === chunk.length ? - this._decodeMapKeyValue.bind(this, type, typeMapping) : - this._decodeMapKeyValue(type, typeMapping, chunk); + #decodeMapKey(typeMapping, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? + this.#decodeMapKeyValue.bind(this, type, typeMapping) : + this.#decodeMapKeyValue(type, typeMapping, chunk); } - private _decodeMapKeyValue(type, typeMapping, chunk) { + #decodeMapKeyValue(type, typeMapping, chunk) { switch (type) { // decode simple string map key as string (and not as buffer) case RESP_TYPES.SIMPLE_STRING: - return this._decodeSimpleString(String, chunk); + return this.#decodeSimpleString(String, chunk); // decode blob string map key as string (and not as buffer) case RESP_TYPES.BLOB_STRING: - return this._decodeBlobString(String, chunk); + return this.#decodeBlobString(String, chunk); default: - return this._decodeNestedTypeValue(type, typeMapping, chunk); + return this.#decodeNestedTypeValue(type, typeMapping, chunk); } } - private _continueDecodeMapKey(map, remaining, keyCb, typeMapping, chunk) { + #continueDecodeMapKey(map, remaining, keyCb, typeMapping, chunk) { const key = keyCb(chunk); if (typeof key === 'function') { - return this._continueDecodeMapKey.bind( + return this.#continueDecodeMapKey.bind( this, map, remaining, @@ -1022,20 +1021,20 @@ export class Decoder { ); } - if (this._cursor >= chunk.length) { - return this._continueDecodeMapValue.bind( + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind( this, map, remaining, key, - this._decodeNestedType.bind(this, typeMapping), + this.#decodeNestedType.bind(this, typeMapping), typeMapping ); } - const value = this._decodeNestedType(typeMapping, chunk); + const value = this.#decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { - return this._continueDecodeMapValue.bind( + return this.#continueDecodeMapValue.bind( this, map, remaining, @@ -1046,13 +1045,13 @@ export class Decoder { } map.set(key, value); - return this._decodeMapAsMap(map, remaining - 1, typeMapping, chunk); + return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - private _continueDecodeMapValue(map, remaining, key, valueCb, typeMapping, chunk) { + #continueDecodeMapValue(map, remaining, key, valueCb, typeMapping, chunk) { const value = valueCb(chunk); if (typeof value === 'function') { - return this._continueDecodeMapValue.bind( + return this.#continueDecodeMapValue.bind( this, map, remaining, @@ -1064,13 +1063,13 @@ export class Decoder { map.set(key, value); - return this._decodeMapAsMap(map, remaining - 1, typeMapping, chunk); + return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - private _decodeMapAsObject(object, remaining, typeMapping, chunk) { + #decodeMapAsObject(object, remaining, typeMapping, chunk) { while (remaining > 0) { - if (this._cursor >= chunk.length) { - return this._decodeMapAsObject.bind( + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsObject.bind( this, object, remaining, @@ -1078,9 +1077,9 @@ export class Decoder { ); } - const key = this._decodeMapKey(typeMapping, chunk); + const key = this.#decodeMapKey(typeMapping, chunk); if (typeof key === 'function') { - return this._continueDecodeMapAsObjectKey.bind( + return this.#continueDecodeMapAsObjectKey.bind( this, object, remaining, @@ -1089,20 +1088,20 @@ export class Decoder { ); } - if (this._cursor >= chunk.length) { - return this._continueDecodeMapAsObjectValue.bind( + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind( this, object, remaining, key, - this._decodeNestedType.bind(this, typeMapping), + this.#decodeNestedType.bind(this, typeMapping), typeMapping ); } - const value = this._decodeNestedType(typeMapping, chunk); + const value = this.#decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { - return this._continueDecodeMapAsObjectValue.bind( + return this.#continueDecodeMapAsObjectValue.bind( this, object, remaining, @@ -1119,10 +1118,10 @@ export class Decoder { return object; } - private _continueDecodeMapAsObjectKey(object, remaining, keyCb, typeMapping, chunk) { + #continueDecodeMapAsObjectKey(object, remaining, keyCb, typeMapping, chunk) { const key = keyCb(chunk); if (typeof key === 'function') { - return this._continueDecodeMapAsObjectKey.bind( + return this.#continueDecodeMapAsObjectKey.bind( this, object, remaining, @@ -1131,20 +1130,20 @@ export class Decoder { ); } - if (this._cursor >= chunk.length) { - return this._continueDecodeMapAsObjectValue.bind( + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind( this, object, remaining, key, - this._decodeNestedType.bind(this, typeMapping), + this.#decodeNestedType.bind(this, typeMapping), typeMapping ); } - const value = this._decodeNestedType(typeMapping, chunk); + const value = this.#decodeNestedType(typeMapping, chunk); if (typeof value === 'function') { - return this._continueDecodeMapAsObjectValue.bind( + return this.#continueDecodeMapAsObjectValue.bind( this, object, remaining, @@ -1156,13 +1155,13 @@ export class Decoder { object[key] = value; - return this._decodeMapAsObject(object, remaining - 1, typeMapping, chunk); + return this.#decodeMapAsObject(object, remaining - 1, typeMapping, chunk); } - private _continueDecodeMapAsObjectValue(object, remaining, key, valueCb, typeMapping, chunk) { + #continueDecodeMapAsObjectValue(object, remaining, key, valueCb, typeMapping, chunk) { const value = valueCb(chunk); if (typeof value === 'function') { - return this._continueDecodeMapAsObjectValue.bind( + return this.#continueDecodeMapAsObjectValue.bind( this, object, remaining, @@ -1174,6 +1173,6 @@ export class Decoder { object[key] = value; - return this._decodeMapAsObject(object, remaining - 1, typeMapping, chunk); + return this.#decodeMapAsObject(object, remaining - 1, typeMapping, chunk); } } From 6686f44d3b83d29888daccf75007de90617c6eb8 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 18 Dec 2023 17:03:21 -0500 Subject: [PATCH 296/325] move from TypeScript privates to "#" --- packages/client/lib/client/commands-queue.ts | 164 +++++------ packages/client/lib/client/index.ts | 293 +++++++++---------- packages/client/lib/client/legacy-mode.ts | 51 ++-- packages/client/lib/client/linked-list.ts | 110 +++---- packages/client/lib/client/multi-command.ts | 54 ++-- packages/client/lib/client/pool.ts | 172 +++++------ packages/client/lib/client/socket.ts | 146 ++++----- packages/client/lib/cluster/cluster-slots.ts | 172 +++++------ packages/client/lib/cluster/index.ts | 109 +++---- packages/client/lib/cluster/multi-command.ts | 76 ++--- packages/client/lib/commander.ts | 2 +- 11 files changed, 671 insertions(+), 678 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 22ea1aba96a..6261b5dd191 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -44,18 +44,18 @@ const RESP2_PUSH_TYPE_MAPPING = { }; export default class RedisCommandsQueue { - private readonly _maxLength: number | null | undefined; - private readonly _toWrite = new DoublyLinkedList(); - private readonly _waitingForReply = new SinglyLinkedList(); - private readonly _onShardedChannelMoved: OnShardedChannelMoved; + readonly #maxLength: number | null | undefined; + readonly #toWrite = new DoublyLinkedList(); + readonly #waitingForReply = new SinglyLinkedList(); + readonly #onShardedChannelMoved: OnShardedChannelMoved; - private readonly _pubSub = new PubSub(); + readonly #pubSub = new PubSub(); get isPubSubActive() { - return this._pubSub.isActive; + return this.#pubSub.isActive; } - private _chainInExecution: symbol | undefined; + #chainInExecution: symbol | undefined; decoder: Decoder; @@ -64,92 +64,92 @@ export default class RedisCommandsQueue { maxLength: number | null | undefined, onShardedChannelMoved: EventEmitter['emit'] ) { - this.decoder = this._initiateDecoder(respVersion); - this._maxLength = maxLength; - this._onShardedChannelMoved = onShardedChannelMoved; + this.decoder = this.#initiateDecoder(respVersion); + this.#maxLength = maxLength; + this.#onShardedChannelMoved = onShardedChannelMoved; } - private _initiateDecoder(respVersion: RespVersions | null | undefined) { + #initiateDecoder(respVersion: RespVersions | null | undefined) { return respVersion === 3 ? - this._initiateResp3Decoder() : - this._initiateResp2Decoder(); + this.#initiateResp3Decoder() : + this.#initiateResp2Decoder(); } - private _onReply(reply: ReplyUnion) { - this._waitingForReply.shift()!.resolve(reply); + #onReply(reply: ReplyUnion) { + this.#waitingForReply.shift()!.resolve(reply); } - private _onErrorReply(err: ErrorReply) { - this._waitingForReply.shift()!.reject(err); + #onErrorReply(err: ErrorReply) { + this.#waitingForReply.shift()!.reject(err); } - private _onPush(push: Array) { + #onPush(push: Array) { // TODO: type - if (this._pubSub.handleMessageReply(push)) return true; + if (this.#pubSub.handleMessageReply(push)) return true; const isShardedUnsubscribe = PubSub.isShardedUnsubscribe(push); - if (isShardedUnsubscribe && !this._waitingForReply.length) { + if (isShardedUnsubscribe && !this.#waitingForReply.length) { const channel = push[1].toString(); - this._onShardedChannelMoved( + this.#onShardedChannelMoved( channel, - this._pubSub.removeShardedListeners(channel) + this.#pubSub.removeShardedListeners(channel) ); return true; } else if (isShardedUnsubscribe || PubSub.isStatusReply(push)) { - const head = this._waitingForReply.head!.value; + const head = this.#waitingForReply.head!.value; if ( (Number.isNaN(head.channelsCounter!) && push[2] === 0) || --head.channelsCounter! === 0 ) { - this._waitingForReply.shift()!.resolve(); + this.#waitingForReply.shift()!.resolve(); } return true; } } - private _getTypeMapping() { - return this._waitingForReply.head!.value.typeMapping ?? {}; + #getTypeMapping() { + return this.#waitingForReply.head!.value.typeMapping ?? {}; } - private _initiateResp3Decoder() { + #initiateResp3Decoder() { return new Decoder({ - onReply: reply => this._onReply(reply), - onErrorReply: err => this._onErrorReply(err), + onReply: reply => this.#onReply(reply), + onErrorReply: err => this.#onErrorReply(err), onPush: push => { - if (!this._onPush(push)) { + if (!this.#onPush(push)) { } }, - getTypeMapping: () => this._getTypeMapping() + getTypeMapping: () => this.#getTypeMapping() }); } - private _initiateResp2Decoder() { + #initiateResp2Decoder() { return new Decoder({ onReply: reply => { - if (this._pubSub.isActive && Array.isArray(reply)) { - if (this._onPush(reply)) return; + if (this.#pubSub.isActive && Array.isArray(reply)) { + if (this.#onPush(reply)) return; if (PONG.equals(reply[0] as Buffer)) { - const { resolve, typeMapping } = this._waitingForReply.shift()!, + const { resolve, typeMapping } = this.#waitingForReply.shift()!, buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); return; } } - this._onReply(reply); + this.#onReply(reply); }, - onErrorReply: err => this._onErrorReply(err), + onErrorReply: err => this.#onErrorReply(err), // PUSH type does not exist in RESP2 // PubSub is handled in onReply // @ts-expect-error onPush: undefined, getTypeMapping: () => { // PubSub push is an Array in RESP2 - return this._pubSub.isActive ? + return this.#pubSub.isActive ? RESP2_PUSH_TYPE_MAPPING : - this._getTypeMapping(); + this.#getTypeMapping(); } }); } @@ -180,7 +180,7 @@ export default class RedisCommandsQueue { options?: CommandOptions, resolveOnWrite?: boolean ): Promise { - if (this._maxLength && this._toWrite.length + this._waitingForReply.length >= this._maxLength) { + if (this.#maxLength && this.#toWrite.length + this.#waitingForReply.length >= this.#maxLength) { return Promise.reject(new Error('The queue is full')); } else if (options?.abortSignal?.aborted) { return Promise.reject(new AbortError()); @@ -204,14 +204,14 @@ export default class RedisCommandsQueue { value.abort = { signal, listener: () => { - this._toWrite.remove(node); + this.#toWrite.remove(node); value.reject(new AbortError()); } }; signal.addEventListener('abort', value.abort.listener, { once: true }); } - node = this._toWrite.add(value, options?.asap); + node = this.#toWrite.add(value, options?.asap); }); } @@ -221,8 +221,8 @@ export default class RedisCommandsQueue { listener: PubSubListener, returnBuffers?: T ) { - return this._addPubSubCommand( - this._pubSub.subscribe(type, channels, listener, returnBuffers) + return this.#addPubSubCommand( + this.#pubSub.subscribe(type, channels, listener, returnBuffers) ); } @@ -232,17 +232,17 @@ export default class RedisCommandsQueue { listener?: PubSubListener, returnBuffers?: T ) { - return this._addPubSubCommand( - this._pubSub.unsubscribe(type, channels, listener, returnBuffers) + return this.#addPubSubCommand( + this.#pubSub.unsubscribe(type, channels, listener, returnBuffers) ); } resubscribe(): Promise | undefined { - const commands = this._pubSub.resubscribe(); + const commands = this.#pubSub.resubscribe(); if (!commands.length) return; return Promise.all( - commands.map(command => this._addPubSubCommand(command, true)) + commands.map(command => this.#addPubSubCommand(command, true)) ); } @@ -251,26 +251,26 @@ export default class RedisCommandsQueue { channel: string, listeners: ChannelListeners ) { - return this._addPubSubCommand( - this._pubSub.extendChannelListeners(type, channel, listeners) + return this.#addPubSubCommand( + this.#pubSub.extendChannelListeners(type, channel, listeners) ); } extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this._addPubSubCommand( - this._pubSub.extendTypeListeners(type, listeners) + return this.#addPubSubCommand( + this.#pubSub.extendTypeListeners(type, listeners) ); } getPubSubListeners(type: PubSubType) { - return this._pubSub.getTypeListeners(type); + return this.#pubSub.getTypeListeners(type); } - private _addPubSubCommand(command: PubSubCommand, asap = false) { + #addPubSubCommand(command: PubSubCommand, asap = false) { if (command === undefined) return; return new Promise((resolve, reject) => { - this._toWrite.add({ + this.#toWrite.add({ args: command.args, chainId: undefined, abort: undefined, @@ -290,23 +290,23 @@ export default class RedisCommandsQueue { } isWaitingToWrite() { - return this._toWrite.length > 0; + return this.#toWrite.length > 0; } *commandsToWrite() { - let toSend = this._toWrite.shift(); + let toSend = this.#toWrite.shift(); while (toSend) { let encoded: CommandArguments; try { encoded = encodeCommand(toSend.args); } catch (err) { toSend.reject(err); - toSend = this._toWrite.shift(); + toSend = this.#toWrite.shift(); continue; } if (toSend.abort) { - RedisCommandsQueue._removeAbortListener(toSend); + RedisCommandsQueue.#removeAbortListener(toSend); toSend.abort = undefined; } @@ -316,31 +316,31 @@ export default class RedisCommandsQueue { // TODO reuse `toSend` or create new object? (toSend as any).args = undefined; - this._chainInExecution = toSend.chainId; + this.#chainInExecution = toSend.chainId; toSend.chainId = undefined; - this._waitingForReply.push(toSend); + this.#waitingForReply.push(toSend); } yield encoded; - toSend = this._toWrite.shift(); + toSend = this.#toWrite.shift(); } } - private _flushWaitingForReply(err: Error): void { - for (const node of this._waitingForReply) { + #flushWaitingForReply(err: Error): void { + for (const node of this.#waitingForReply) { node.reject(err); } - this._waitingForReply.reset(); + this.#waitingForReply.reset(); } - private static _removeAbortListener(command: CommandToWrite) { + static #removeAbortListener(command: CommandToWrite) { command.abort!.signal.removeEventListener('abort', command.abort!.listener); } - private static _flushToWrite(toBeSent: CommandToWrite, err: Error) { + static #flushToWrite(toBeSent: CommandToWrite, err: Error) { if (toBeSent.abort) { - RedisCommandsQueue._removeAbortListener(toBeSent); + RedisCommandsQueue.#removeAbortListener(toBeSent); } toBeSent.reject(err); @@ -348,36 +348,36 @@ export default class RedisCommandsQueue { flushWaitingForReply(err: Error): void { this.decoder.reset(); - this._pubSub.reset(); + this.#pubSub.reset(); - this._flushWaitingForReply(err); + this.#flushWaitingForReply(err); - if (!this._chainInExecution) return; + if (!this.#chainInExecution) return; - while (this._toWrite.head?.value.chainId === this._chainInExecution) { - RedisCommandsQueue._flushToWrite( - this._toWrite.shift()!, + while (this.#toWrite.head?.value.chainId === this.#chainInExecution) { + RedisCommandsQueue.#flushToWrite( + this.#toWrite.shift()!, err ); } - this._chainInExecution = undefined; + this.#chainInExecution = undefined; } flushAll(err: Error): void { this.decoder.reset(); - this._pubSub.reset(); - this._flushWaitingForReply(err); - for (const node of this._toWrite) { - RedisCommandsQueue._flushToWrite(node, err); + this.#pubSub.reset(); + this.#flushWaitingForReply(err); + for (const node of this.#toWrite) { + RedisCommandsQueue.#flushToWrite(node, err); } - this._toWrite.reset(); + this.#toWrite.reset(); } isEmpty() { return ( - this._toWrite.length === 0 && - this._waitingForReply.length === 0 + this.#toWrite.length === 0 && + this.#waitingForReply.length === 0 ); } } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 1f33ca44835..51a4a478d5f 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -132,7 +132,7 @@ export type RedisClientType< type ProxyClient = RedisClient; -type NamespaceProxyClient = { self: ProxyClient }; +type NamespaceProxyClient = { _self: ProxyClient }; interface ScanIteratorOptions { cursor?: RedisArgument; @@ -147,7 +147,7 @@ export default class RedisClient< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > extends EventEmitter { - private static _createCommand(command: Command, resp: RespVersions) { + static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyClient, ...args: Array) { const redisArgs = command.transformArguments(...args), @@ -158,25 +158,25 @@ export default class RedisClient< }; } - private static _createModuleCommand(command: Command, resp: RespVersions) { + static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyClient, ...args: Array) { const redisArgs = command.transformArguments(...args), - reply = await this.self.sendCommand(redisArgs, this.self._commandOptions); + reply = await this._self.sendCommand(redisArgs, this._self._commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; }; } - private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyClient, ...args: Array) { const fnArgs = fn.transformArguments(...args), - reply = await this.self.sendCommand( + reply = await this._self.sendCommand( prefix.concat(fnArgs), - this.self._commandOptions + this._self._commandOptions ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -184,7 +184,7 @@ export default class RedisClient< }; } - private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + static #createScriptCommand(script: RedisScript, resp: RespVersions) { const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyClient, ...args: Array) { @@ -206,10 +206,10 @@ export default class RedisClient< const Client = attachConfig({ BaseClass: RedisClient, commands: COMMANDS, - createCommand: RedisClient._createCommand, - createModuleCommand: RedisClient._createModuleCommand, - createFunctionCommand: RedisClient._createFunctionCommand, - createScriptCommand: RedisClient._createScriptCommand, + createCommand: RedisClient.#createCommand, + createModuleCommand: RedisClient.#createModuleCommand, + createFunctionCommand: RedisClient.#createFunctionCommand, + createScriptCommand: RedisClient.#createScriptCommand, config }); @@ -218,7 +218,7 @@ export default class RedisClient< return ( options?: Omit, keyof Exclude> ) => { - // returning a "proxy" to prevent the namespaces.self to leak between "proxies" + // returning a "proxy" to prevent the namespaces._self to leak between "proxies" return Object.create(new Client(options)) as RedisClientType; }; } @@ -272,39 +272,38 @@ export default class RedisClient< return parsed; } - self = this; - - private readonly _options?: RedisClientOptions; - private readonly _socket: RedisSocket; - private readonly _queue: RedisCommandsQueue; - private _selectedDB = 0; - private _monitorCallback?: MonitorCallback; + readonly #options?: RedisClientOptions; + readonly #socket: RedisSocket; + readonly #queue: RedisCommandsQueue; + #selectedDB = 0; + #monitorCallback?: MonitorCallback; + private _self = this; private _commandOptions?: CommandOptions; get options(): RedisClientOptions | undefined { - return this._options; + return this._self.#options; } get isOpen(): boolean { - return this._socket.isOpen; + return this._self.#socket.isOpen; } get isReady(): boolean { - return this._socket.isReady; + return this._self.#socket.isReady; } get isPubSubActive() { - return this._queue.isPubSubActive; + return this._self.#queue.isPubSubActive; } constructor(options?: RedisClientOptions) { super(); - this._options = this._initiateOptions(options); - this._queue = this._initiateQueue(); - this._socket = this._initiateSocket(); + this.#options = this.#initiateOptions(options); + this.#queue = this.#initiateQueue(); + this.#socket = this.#initiateSocket(); } - private _initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { + #initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { if (options?.url) { const parsed = RedisClient.parseURL(options.url); if (options.socket) { @@ -315,7 +314,7 @@ export default class RedisClient< } if (options?.database) { - this.self._selectedDB = options.database; + this._self.#selectedDB = options.database; } if (options?.commandOptions) { @@ -325,82 +324,82 @@ export default class RedisClient< return options; } - private _initiateQueue(): RedisCommandsQueue { + #initiateQueue(): RedisCommandsQueue { return new RedisCommandsQueue( - this._options?.RESP, - this._options?.commandsQueueMaxLength, + this.#options?.RESP, + this.#options?.commandsQueueMaxLength, (channel, listeners) => this.emit('sharded-channel-moved', channel, listeners) ); } - private _initiateSocket(): RedisSocket { + #initiateSocket(): RedisSocket { const socketInitiator = async (): Promise => { - const promises = [this._queue.resubscribe()]; + const promises = [this.#queue.resubscribe()]; - if (this._monitorCallback) { + if (this.#monitorCallback) { promises.push( - this._queue.monitor( - this._monitorCallback, + this.#queue.monitor( + this.#monitorCallback, this._commandOptions?.typeMapping, true ) ); } - if (this._selectedDB !== 0) { + if (this.#selectedDB !== 0) { promises.push( - this._queue.addCommand( - ['SELECT', this._selectedDB.toString()], + this.#queue.addCommand( + ['SELECT', this.#selectedDB.toString()], { asap: true } ) ); } - if (this._options?.readonly) { + if (this.#options?.readonly) { promises.push( - this._queue.addCommand( + this.#queue.addCommand( COMMANDS.READONLY.transformArguments(), { asap: true } ) ); } - if (this._options?.RESP) { + if (this.#options?.RESP) { const hello: HelloOptions = {}; - if (this._options.password) { + if (this.#options.password) { hello.AUTH = { - username: this._options.username ?? 'default', - password: this._options.password + username: this.#options.username ?? 'default', + password: this.#options.password }; } - if (this._options.name) { - hello.SETNAME = this._options.name; + if (this.#options.name) { + hello.SETNAME = this.#options.name; } promises.push( - this._queue.addCommand( - HELLO.transformArguments(this._options.RESP, hello), + this.#queue.addCommand( + HELLO.transformArguments(this.#options.RESP, hello), { asap: true } ) ); } else { - if (this._options?.name) { + if (this.#options?.name) { promises.push( - this._queue.addCommand( - COMMANDS.CLIENT_SETNAME.transformArguments(this._options.name), + this.#queue.addCommand( + COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), { asap: true } ) ); } - if (this._options?.username || this._options?.password) { + if (this.#options?.username || this.#options?.password) { promises.push( - this._queue.addCommand( + this.#queue.addCommand( COMMANDS.AUTH.transformArguments({ - username: this._options.username, - password: this._options.password ?? '' + username: this.#options.username, + password: this.#options.password ?? '' }), { asap: true } ) @@ -409,60 +408,60 @@ export default class RedisClient< } if (promises.length) { - this._write(); + this.#write(); await Promise.all(promises); } }; - return new RedisSocket(socketInitiator, this._options?.socket) + return new RedisSocket(socketInitiator, this.#options?.socket) .on('data', chunk => { try { - this._queue.decoder.write(chunk); + this.#queue.decoder.write(chunk); } catch (err) { - this._queue.decoder.reset(); + this.#queue.decoder.reset(); this.emit('error', err); } }) .on('error', err => { this.emit('error', err); - if (this._socket.isOpen && !this._options?.disableOfflineQueue) { - this._queue.flushWaitingForReply(err); + if (this.#socket.isOpen && !this.#options?.disableOfflineQueue) { + this.#queue.flushWaitingForReply(err); } else { - this._queue.flushAll(err); + this.#queue.flushAll(err); } }) .on('connect', () => this.emit('connect')) .on('ready', () => { this.emit('ready'); - this._setPingTimer(); - this._maybeScheduleWrite(); + this.#setPingTimer(); + this.#maybeScheduleWrite(); }) .on('reconnecting', () => this.emit('reconnecting')) - .on('drain', () => this._maybeScheduleWrite()) + .on('drain', () => this.#maybeScheduleWrite()) .on('end', () => this.emit('end')); } - private _pingTimer?: NodeJS.Timeout; + #pingTimer?: NodeJS.Timeout; - private _setPingTimer(): void { - if (!this._options?.pingInterval || !this._socket.isReady) return; - clearTimeout(this._pingTimer); + #setPingTimer(): void { + if (!this.#options?.pingInterval || !this.#socket.isReady) return; + clearTimeout(this.#pingTimer); - this._pingTimer = setTimeout(() => { - if (!this._socket.isReady) return; + this.#pingTimer = setTimeout(() => { + if (!this.#socket.isReady) return; this.sendCommand(['PING']) .then(reply => this.emit('ping-interval', reply)) .catch(err => this.emit('error', err)) - .finally(() => this._setPingTimer()); - }, this._options.pingInterval); + .finally(() => this.#setPingTimer()); + }, this.#options.pingInterval); } withCommandOptions< OPTIONS extends CommandOptions, TYPE_MAPPING extends TypeMapping >(options: OPTIONS) { - const proxy = Object.create(this.self); + const proxy = Object.create(this._self); proxy._commandOptions = options; return proxy as RedisClientType< M, @@ -480,7 +479,7 @@ export default class RedisClient< key: K, value: V ) { - const proxy = Object.create(this.self); + const proxy = Object.create(this._self); proxy._commandOptions = Object.create(this._commandOptions ?? null); proxy._commandOptions[key] = value; return proxy as RedisClientType< @@ -527,7 +526,7 @@ export default class RedisClient< */ createPool(options?: Partial) { return RedisClientPool.create( - this._options, + this._self.#options, options ); } @@ -540,14 +539,14 @@ export default class RedisClient< _TYPE_MAPPING extends TypeMapping = TYPE_MAPPING >(overrides?: Partial>) { return new (Object.getPrototypeOf(this).constructor)({ - ...this._options, + ...this._self.#options, commandOptions: this._commandOptions, ...overrides }) as RedisClientType<_M, _F, _S, _RESP, _TYPE_MAPPING>; } async connect() { - await this._socket.connect(); + await this._self.#socket.connect(); return this as unknown as RedisClientType; } @@ -555,14 +554,14 @@ export default class RedisClient< args: Array, options?: CommandOptions ): Promise { - if (!this._socket.isOpen) { + if (!this._self.#socket.isOpen) { return Promise.reject(new ClientClosedError()); - } else if (!this._socket.isReady && this._options?.disableOfflineQueue) { + } else if (!this._self.#socket.isReady && this._self.#options?.disableOfflineQueue) { return Promise.reject(new ClientOfflineError()); } - const promise = this._queue.addCommand(args, options); - this._scheduleWrite(); + const promise = this._self.#queue.addCommand(args, options); + this._self.#scheduleWrite(); return promise; } @@ -584,15 +583,15 @@ export default class RedisClient< async SELECT(db: number): Promise { await this.sendCommand(['SELECT', db.toString()]); - this.self._selectedDB = db; + this._self.#selectedDB = db; } select = this.SELECT; - private _pubSubCommand(promise: Promise | undefined) { + #pubSubCommand(promise: Promise | undefined) { if (promise === undefined) return Promise.resolve(); - this._scheduleWrite(); + this.#scheduleWrite(); return promise; } @@ -601,8 +600,8 @@ export default class RedisClient< listener: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.subscribe( + return this._self.#pubSubCommand( + this._self.#queue.subscribe( PubSubType.CHANNELS, channels, listener, @@ -618,8 +617,8 @@ export default class RedisClient< listener?: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.unsubscribe( + return this._self.#pubSubCommand( + this._self.#queue.unsubscribe( PubSubType.CHANNELS, channels, listener, @@ -635,8 +634,8 @@ export default class RedisClient< listener: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.subscribe( + return this._self.#pubSubCommand( + this._self.#queue.subscribe( PubSubType.PATTERNS, patterns, listener, @@ -652,8 +651,8 @@ export default class RedisClient< listener?: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.unsubscribe( + return this._self.#pubSubCommand( + this._self.#queue.unsubscribe( PubSubType.PATTERNS, patterns, listener, @@ -669,8 +668,8 @@ export default class RedisClient< listener: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.subscribe( + return this._self.#pubSubCommand( + this._self.#queue.subscribe( PubSubType.SHARDED, channels, listener, @@ -686,8 +685,8 @@ export default class RedisClient< listener?: PubSubListener, bufferMode?: T ): Promise { - return this._pubSubCommand( - this._queue.unsubscribe( + return this._self.#pubSubCommand( + this._self.#queue.unsubscribe( PubSubType.SHARDED, channels, listener, @@ -699,7 +698,7 @@ export default class RedisClient< sUnsubscribe = this.SUNSUBSCRIBE; getPubSubListeners(type: PubSubType) { - return this._queue.getPubSubListeners(type); + return this._self.#queue.getPubSubListeners(type); } extendPubSubChannelListeners( @@ -707,36 +706,36 @@ export default class RedisClient< channel: string, listeners: ChannelListeners ) { - return this._pubSubCommand( - this._queue.extendPubSubChannelListeners(type, channel, listeners) + return this._self.#pubSubCommand( + this._self.#queue.extendPubSubChannelListeners(type, channel, listeners) ); } extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this._pubSubCommand( - this._queue.extendPubSubListeners(type, listeners) + return this._self.#pubSubCommand( + this._self.#queue.extendPubSubListeners(type, listeners) ); } - private _write() { - this._socket.write(this._queue.commandsToWrite()); + #write() { + this.#socket.write(this.#queue.commandsToWrite()); } - private _scheduledWrite?: NodeJS.Immediate; + #scheduledWrite?: NodeJS.Immediate; - private _scheduleWrite() { - if (!this.isReady || this._scheduledWrite) return; + #scheduleWrite() { + if (!this.#socket.isReady || this.#scheduledWrite) return; - this._scheduledWrite = setImmediate(() => { - this._write(); - this._scheduledWrite = undefined; + this.#scheduledWrite = setImmediate(() => { + this.#write(); + this.#scheduledWrite = undefined; }); } - private _maybeScheduleWrite() { - if (!this._queue.isWaitingToWrite()) return; + #maybeScheduleWrite() { + if (!this.#queue.isWaitingToWrite()) return; - this._scheduleWrite(); + this.#scheduleWrite(); } /** @@ -746,20 +745,20 @@ export default class RedisClient< commands: Array, selectedDB?: number ) { - if (!this._socket.isOpen) { + if (!this._self.#socket.isOpen) { return Promise.reject(new ClientClosedError()); } const promise = Promise.all( - commands.map(({ args }) => this._queue.addCommand(args, { + commands.map(({ args }) => this._self.#queue.addCommand(args, { typeMapping: this._commandOptions?.typeMapping })) ); - this._scheduleWrite(); + this._self.#scheduleWrite(); const result = await promise; if (selectedDB !== undefined) { - this.self._selectedDB = selectedDB; + this._self.#selectedDB = selectedDB; } return result; @@ -772,19 +771,19 @@ export default class RedisClient< commands: Array, selectedDB?: number ) { - if (!this._socket.isOpen) { + if (!this._self.#socket.isOpen) { throw new ClientClosedError(); } const typeMapping = this._commandOptions?.typeMapping, chainId = Symbol('MULTI Chain'), promises = [ - this._queue.addCommand(['MULTI'], { chainId }), + this._self.#queue.addCommand(['MULTI'], { chainId }), ]; for (const { args } of commands) { promises.push( - this._queue.addCommand(args, { + this._self.#queue.addCommand(args, { chainId, typeMapping }) @@ -792,10 +791,10 @@ export default class RedisClient< } promises.push( - this._queue.addCommand(['EXEC'], { chainId }) + this._self.#queue.addCommand(['EXEC'], { chainId }) ); - this._scheduleWrite(); + this._self.#scheduleWrite(); const results = await Promise.all(promises), execResult = results[results.length - 1]; @@ -805,7 +804,7 @@ export default class RedisClient< } if (selectedDB !== undefined) { - this.self._selectedDB = selectedDB; + this._self.#selectedDB = selectedDB; } return execResult as Array; @@ -873,16 +872,16 @@ export default class RedisClient< } async MONITOR(callback: MonitorCallback) { - const promise = this._queue.monitor(callback, this._commandOptions?.typeMapping); - this._scheduleWrite(); + const promise = this._self.#queue.monitor(callback, this._commandOptions?.typeMapping); + this._self.#scheduleWrite(); const off = await promise; - this._monitorCallback = callback; + this._self.#monitorCallback = callback; return async () => { const promise = off(); - this._scheduleWrite(); + this._self.#scheduleWrite(); await promise; - this._monitorCallback = undefined; + this._self.#monitorCallback = undefined; }; } @@ -892,10 +891,10 @@ export default class RedisClient< * @deprecated use .close instead */ QUIT(): Promise { - return this._socket.quit(async () => { - clearTimeout(this._pingTimer); - const quitPromise = this._queue.addCommand(['QUIT']); - this._scheduleWrite(); + return this._self.#socket.quit(async () => { + clearTimeout(this._self.#pingTimer); + const quitPromise = this._self.#queue.addCommand(['QUIT']); + this._self.#scheduleWrite(); return quitPromise; }); } @@ -914,22 +913,22 @@ export default class RedisClient< */ close() { return new Promise(resolve => { - clearTimeout(this._pingTimer); - this._socket.close(); + clearTimeout(this._self.#pingTimer); + this._self.#socket.close(); - if (this._queue.isEmpty()) { - this._socket.destroySocket(); + if (this._self.#queue.isEmpty()) { + this._self.#socket.destroySocket(); return resolve(); } const maybeClose = () => { - if (!this._queue.isEmpty()) return; + if (!this._self.#queue.isEmpty()) return; - this._socket.off('data', maybeClose); - this._socket.destroySocket(); + this._self.#socket.off('data', maybeClose); + this._self.#socket.destroySocket(); resolve(); }; - this._socket.on('data', maybeClose); + this._self.#socket.on('data', maybeClose); }); } @@ -937,16 +936,16 @@ export default class RedisClient< * Destroy the client. Rejects all commands immediately. */ destroy() { - clearTimeout(this._pingTimer); - this._queue.flushAll(new DisconnectsClientError()); - this._socket.destroy(); + clearTimeout(this._self.#pingTimer); + this._self.#queue.flushAll(new DisconnectsClientError()); + this._self.#socket.destroy(); } ref() { - this._socket.ref(); + this._self.#socket.ref(); } unref() { - this._socket.unref(); + this._self.#socket.unref(); } } diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 555c4eaae52..b30ebc68bc2 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -23,7 +23,7 @@ type WithCommands = { export type RedisLegacyClientType = RedisLegacyClient & WithCommands; export class RedisLegacyClient { - private static _transformArguments(redisArgs: CommandArguments, args: LegacyCommandArguments) { + static #transformArguments(redisArgs: CommandArguments, args: LegacyCommandArguments) { let callback: LegacyCallback | undefined; if (typeof args[args.length - 1] === 'function') { callback = args.pop() as LegacyCallback; @@ -55,15 +55,15 @@ export class RedisLegacyClient { undefined; } - private static _createCommand(name: string, command: Command, resp: RespVersions) { + static #createCommand(name: string, command: Command, resp: RespVersions) { const transformReply = RedisLegacyClient.getTransformReply(command, resp); return async function (this: RedisLegacyClient, ...args: LegacyCommandArguments) { const redisArgs = [name], - callback = RedisLegacyClient._transformArguments(redisArgs, args), - promise = this._client.sendCommand(redisArgs); + callback = RedisLegacyClient.#transformArguments(redisArgs, args), + promise = this.#client.sendCommand(redisArgs); if (!callback) { - promise.catch(err => this._client.emit('error', err)); + promise.catch(err => this.#client.emit('error', err)); return; } @@ -73,31 +73,34 @@ export class RedisLegacyClient { }; } - private _Multi: ReturnType; + #client: RedisClientType; + #Multi: ReturnType; constructor( - private _client: RedisClientType + client: RedisClientType ) { - const RESP = _client.options?.RESP ?? 2; + this.#client = client; + + const RESP = client.options?.RESP ?? 2; for (const [name, command] of Object.entries(COMMANDS)) { // TODO: as any? - (this as any)[name] = RedisLegacyClient._createCommand( + (this as any)[name] = RedisLegacyClient.#createCommand( name, command, RESP ); } - this._Multi = LegacyMultiCommand.factory(RESP); + this.#Multi = LegacyMultiCommand.factory(RESP); } sendCommand(...args: LegacyCommandArguments) { const redisArgs: CommandArguments = [], - callback = RedisLegacyClient._transformArguments(redisArgs, args), - promise = this._client.sendCommand(redisArgs); + callback = RedisLegacyClient.#transformArguments(redisArgs, args), + promise = this.#client.sendCommand(redisArgs); if (!callback) { - promise.catch(err => this._client.emit('error', err)); + promise.catch(err => this.#client.emit('error', err)); return; } @@ -107,7 +110,7 @@ export class RedisLegacyClient { } multi() { - return this._Multi(this._client); + return this.#Multi(this.#client); } } @@ -118,12 +121,12 @@ type MultiWithCommands = { export type RedisLegacyMultiType = LegacyMultiCommand & MultiWithCommands; class LegacyMultiCommand { - private static _createCommand(name: string, command: Command, resp: RespVersions) { + static #createCommand(name: string, command: Command, resp: RespVersions) { const transformReply = RedisLegacyClient.getTransformReply(command, resp); return function (this: LegacyMultiCommand, ...args: LegacyArguments) { const redisArgs = [name]; RedisLegacyClient.pushArguments(redisArgs, args); - this._multi.addCommand(redisArgs, transformReply); + this.#multi.addCommand(redisArgs, transformReply); return this; }; } @@ -133,7 +136,7 @@ class LegacyMultiCommand { for (const [name, command] of Object.entries(COMMANDS)) { // TODO: as any? - (Multi as any).prototype[name] = LegacyMultiCommand._createCommand( + (Multi as any).prototype[name] = LegacyMultiCommand.#createCommand( name, command, resp @@ -145,30 +148,30 @@ class LegacyMultiCommand { }; } - private readonly _multi = new RedisMultiCommand(); - private readonly _client: RedisClientType; + readonly #multi = new RedisMultiCommand(); + readonly #client: RedisClientType; constructor(client: RedisClientType) { - this._client = client; + this.#client = client; } sendCommand(...args: LegacyArguments) { const redisArgs: CommandArguments = []; RedisLegacyClient.pushArguments(redisArgs, args); - this._multi.addCommand(redisArgs); + this.#multi.addCommand(redisArgs); return this; } exec(cb?: (err: ErrorReply | null, replies?: Array) => unknown) { - const promise = this._client._executeMulti(this._multi.queue); + const promise = this.#client._executeMulti(this.#multi.queue); if (!cb) { - promise.catch(err => this._client.emit('error', err)); + promise.catch(err => this.#client.emit('error', err)); return; } promise - .then(results => cb(null, this._multi.transformReplies(results))) + .then(results => cb(null, this.#multi.transformReplies(results))) .catch(err => cb?.(err)); } } diff --git a/packages/client/lib/client/linked-list.ts b/packages/client/lib/client/linked-list.ts index 7aed43cfd1a..ac1d021be91 100644 --- a/packages/client/lib/client/linked-list.ts +++ b/packages/client/lib/client/linked-list.ts @@ -5,56 +5,56 @@ export interface DoublyLinkedNode { } export class DoublyLinkedList { - private _length = 0; + #length = 0; get length() { - return this._length; + return this.#length; } - private _head?: DoublyLinkedNode; + #head?: DoublyLinkedNode; get head() { - return this._head; + return this.#head; } - private _tail?: DoublyLinkedNode; + #tail?: DoublyLinkedNode; get tail() { - return this._tail; + return this.#tail; } push(value: T) { - ++this._length; + ++this.#length; - if (this._tail === undefined) { - return this._tail = this._head = { - previous: this._head, + if (this.#tail === undefined) { + return this.#tail = this.#head = { + previous: this.#head, next: undefined, value }; } - return this._tail = this._tail.next = { - previous: this._tail, + return this.#tail = this.#tail.next = { + previous: this.#tail, next: undefined, value }; } unshift(value: T) { - ++this._length; + ++this.#length; - if (this._head === undefined) { - return this._head = this._tail = { + if (this.#head === undefined) { + return this.#head = this.#tail = { previous: undefined, next: undefined, value }; } - return this._head = this._head.previous = { + return this.#head = this.#head.previous = { previous: undefined, - next: this._head, + next: this.#head, value }; } @@ -66,29 +66,29 @@ export class DoublyLinkedList { } shift() { - if (this._head === undefined) return undefined; + if (this.#head === undefined) return undefined; - --this._length; - const node = this._head; + --this.#length; + const node = this.#head; if (node.next) { node.next.previous = node.previous; - this._head = node.next; + this.#head = node.next; node.next = undefined; } else { - this._head = this._tail = undefined; + this.#head = this.#tail = undefined; } return node.value; } remove(node: DoublyLinkedNode) { - --this._length; + --this.#length; - if (this._tail === node) { - this._tail = node.previous; + if (this.#tail === node) { + this.#tail = node.previous; } - if (this._head === node) { - this._head = node.next; + if (this.#head === node) { + this.#head = node.next; } else { node.previous!.next = node.next; node.previous = undefined; @@ -98,12 +98,12 @@ export class DoublyLinkedList { } reset() { - this._length = 0; - this._head = this._tail = undefined; + this.#length = 0; + this.#head = this.#tail = undefined; } *[Symbol.iterator]() { - let node = this._head; + let node = this.#head; while (node !== undefined) { yield node.value; node = node.next; @@ -117,50 +117,50 @@ export interface SinglyLinkedNode { } export class SinglyLinkedList { - private _length = 0; + #length = 0; get length() { - return this._length; + return this.#length; } - private _head?: SinglyLinkedNode; + #head?: SinglyLinkedNode; get head() { - return this._head; + return this.#head; } - private _tail?: SinglyLinkedNode; + #tail?: SinglyLinkedNode; get tail() { - return this._tail; + return this.#tail; } push(value: T) { - ++this._length; + ++this.#length; const node = { value, next: undefined }; - if (this._head === undefined) { - return this._head = this._tail = node; + if (this.#head === undefined) { + return this.#head = this.#tail = node; } - return this._tail!.next = this._tail = node; + return this.#tail!.next = this.#tail = node; } remove(node: SinglyLinkedNode, parent: SinglyLinkedNode | undefined) { - --this._length; + --this.#length; - if (this._head === node) { - if (this._tail === node) { - this._head = this._tail = undefined; + if (this.#head === node) { + if (this.#tail === node) { + this.#head = this.#tail = undefined; } else { - this._head = node.next; + this.#head = node.next; } - } else if (this._tail === node) { - this._tail = parent; + } else if (this.#tail === node) { + this.#tail = parent; parent!.next = undefined; } else { parent!.next = node.next; @@ -168,25 +168,25 @@ export class SinglyLinkedList { } shift() { - if (this._head === undefined) return undefined; + if (this.#head === undefined) return undefined; - const node = this._head; - if (--this._length === 0) { - this._head = this._tail = undefined; + const node = this.#head; + if (--this.#length === 0) { + this.#head = this.#tail = undefined; } else { - this._head = node.next; + this.#head = node.next; } return node.value; } reset() { - this._length = 0; - this._head = this._tail = undefined; + this.#length = 0; + this.#head = this.#tail = undefined; } *[Symbol.iterator]() { - let node = this._head; + let node = this.#head; while (node !== undefined) { yield node.value; node = node.next; diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 7daf4b5d801..ef65144d56b 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -86,7 +86,7 @@ export type RedisClientMultiCommandType< type ExecuteMulti = (commands: Array, selectedDB?: number) => Promise>; export default class RedisClientMultiCommand { - private static _createCommand(command: Command, resp: RespVersions) { + static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return function (this: RedisClientMultiCommand, ...args: Array) { return this.addCommand( @@ -96,34 +96,34 @@ export default class RedisClientMultiCommand { }; } - private static _createModuleCommand(command: Command, resp: RespVersions) { + static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return function (this: { self: RedisClientMultiCommand }, ...args: Array) { - return this.self.addCommand( + return function (this: { _self: RedisClientMultiCommand }, ...args: Array) { + return this._self.addCommand( command.transformArguments(...args), transformReply ); }; } - private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); - return function (this: { self: RedisClientMultiCommand }, ...args: Array) { + return function (this: { _self: RedisClientMultiCommand }, ...args: Array) { const fnArgs = fn.transformArguments(...args), redisArgs: CommandArguments = prefix.concat(fnArgs); redisArgs.preserve = fnArgs.preserve; - return this.self.addCommand( + return this._self.addCommand( redisArgs, transformReply ); }; } - private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + static #createScriptCommand(script: RedisScript, resp: RespVersions) { const transformReply = getTransformReply(script, resp); return function (this: RedisClientMultiCommand, ...args: Array) { - this._multi.addScript( + this.#multi.addScript( script, script.transformArguments(...args), transformReply @@ -141,42 +141,42 @@ export default class RedisClientMultiCommand { return attachConfig({ BaseClass: RedisClientMultiCommand, commands: COMMANDS, - createCommand: RedisClientMultiCommand._createCommand, - createModuleCommand: RedisClientMultiCommand._createModuleCommand, - createFunctionCommand: RedisClientMultiCommand._createFunctionCommand, - createScriptCommand: RedisClientMultiCommand._createScriptCommand, + createCommand: RedisClientMultiCommand.#createCommand, + createModuleCommand: RedisClientMultiCommand.#createModuleCommand, + createFunctionCommand: RedisClientMultiCommand.#createFunctionCommand, + createScriptCommand: RedisClientMultiCommand.#createScriptCommand, config }); } - private readonly _multi = new RedisMultiCommand(); - private readonly _executeMulti: ExecuteMulti; - private readonly _executePipeline: ExecuteMulti; - private _selectedDB?: number; + readonly #multi = new RedisMultiCommand(); + readonly #executeMulti: ExecuteMulti; + readonly #executePipeline: ExecuteMulti; + #selectedDB?: number; constructor(executeMulti: ExecuteMulti, executePipeline: ExecuteMulti) { - this._executeMulti = executeMulti; - this._executePipeline = executePipeline; + this.#executeMulti = executeMulti; + this.#executePipeline = executePipeline; } SELECT(db: number, transformReply?: TransformReply): this { - this._selectedDB = db; - this._multi.addCommand(['SELECT', db.toString()], transformReply); + this.#selectedDB = db; + this.#multi.addCommand(['SELECT', db.toString()], transformReply); return this; } select = this.SELECT; addCommand(args: CommandArguments, transformReply?: TransformReply) { - this._multi.addCommand(args, transformReply); + this.#multi.addCommand(args, transformReply); return this; } async exec(execAsPipeline = false): Promise> { if (execAsPipeline) return this.execAsPipeline(); - return this._multi.transformReplies( - await this._executeMulti(this._multi.queue, this._selectedDB) + return this.#multi.transformReplies( + await this.#executeMulti(this.#multi.queue, this.#selectedDB) ) as MultiReplyType; } @@ -187,10 +187,10 @@ export default class RedisClientMultiCommand { } async execAsPipeline(): Promise> { - if (this._multi.queue.length === 0) return [] as MultiReplyType; + if (this.#multi.queue.length === 0) return [] as MultiReplyType; - return this._multi.transformReplies( - await this._executePipeline(this._multi.queue, this._selectedDB) + return this.#multi.transformReplies( + await this.#executePipeline(this.#multi.queue, this.#selectedDB) ) as MultiReplyType; } diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 5ea76e3e30b..12d8f5fee5c 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -49,7 +49,7 @@ export type RedisClientPoolType< type ProxyPool = RedisClientPoolType; -type NamespaceProxyPool = { self: ProxyPool }; +type NamespaceProxyPool = { _self: ProxyPool }; export class RedisClientPool< M extends RedisModules = {}, @@ -58,7 +58,7 @@ export class RedisClientPool< RESP extends RespVersions = 2, TYPE_MAPPING extends TypeMapping = {} > extends EventEmitter { - private static _createCommand(command: Command, resp: RespVersions) { + static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyPool, ...args: Array) { const redisArgs = command.transformArguments(...args), @@ -69,25 +69,25 @@ export class RedisClientPool< }; } - private static _createModuleCommand(command: Command, resp: RespVersions) { + static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyPool, ...args: Array) { const redisArgs = command.transformArguments(...args), - reply = await this.self.sendCommand(redisArgs, this.self._commandOptions); + reply = await this._self.sendCommand(redisArgs, this._self._commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; }; } - private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyPool, ...args: Array) { const fnArgs = fn.transformArguments(...args), - reply = await this.self.sendCommand( + reply = await this._self.sendCommand( prefix.concat(fnArgs), - this.self._commandOptions + this._self._commandOptions ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -95,7 +95,7 @@ export class RedisClientPool< }; } - private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + static #createScriptCommand(script: RedisScript, resp: RespVersions) { const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyPool, ...args: Array) { @@ -115,23 +115,22 @@ export class RedisClientPool< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping = {} >( - // clientFactory: () => RedisClientType, clientOptions?: RedisClientOptions, options?: Partial ) { const Pool = attachConfig({ BaseClass: RedisClientPool, commands: COMMANDS, - createCommand: RedisClientPool._createCommand, - createModuleCommand: RedisClientPool._createModuleCommand, - createFunctionCommand: RedisClientPool._createFunctionCommand, - createScriptCommand: RedisClientPool._createScriptCommand, + createCommand: RedisClientPool.#createCommand, + createModuleCommand: RedisClientPool.#createModuleCommand, + createFunctionCommand: RedisClientPool.#createFunctionCommand, + createScriptCommand: RedisClientPool.#createScriptCommand, config: clientOptions }); Pool.prototype.Multi = RedisClientMultiCommand.extend(clientOptions); - // returning a "proxy" to prevent the namespaces.self to leak between "proxies" + // returning a "proxy" to prevent the namespaces._self to leak between "proxies" return Object.create( new Pool( RedisClient.factory(clientOptions).bind(undefined, clientOptions), @@ -141,51 +140,42 @@ export class RedisClientPool< } // TODO: defaults - private static _DEFAULTS = { + static #DEFAULTS = { minimum: 1, maximum: 100, acquireTimeout: 3000, cleanupDelay: 3000 } satisfies RedisPoolOptions; - private readonly _clientFactory: () => RedisClientType; - private readonly _options: RedisPoolOptions; + readonly #clientFactory: () => RedisClientType; + readonly #options: RedisPoolOptions; - private readonly _idleClients = new SinglyLinkedList>(); + readonly #idleClients = new SinglyLinkedList>(); /** * The number of idle clients. */ get idleClients() { - return this._idleClients.length; + return this._self.#idleClients.length; } - private readonly _clientsInUse = new DoublyLinkedList>(); + readonly #clientsInUse = new DoublyLinkedList>(); /** * The number of clients in use. */ get clientsInUse() { - return this._clientsInUse.length; - } - - private readonly _connectingClients = 0; - - /** - * The number of clients that are currently connecting. - */ - get connectingClients() { - return this._connectingClients; + return this._self.#clientsInUse.length; } /** * The total number of clients in the pool (including connecting, idle, and in use). */ get totalClients() { - return this._idleClients.length + this._clientsInUse.length; + return this._self.#idleClients.length + this._self.#clientsInUse.length; } - private readonly _tasksQueue = new SinglyLinkedList<{ + readonly #tasksQueue = new SinglyLinkedList<{ timeout: NodeJS.Timeout | undefined; resolve: (value: unknown) => unknown; reject: (reason?: unknown) => unknown; @@ -196,25 +186,25 @@ export class RedisClientPool< * The number of tasks waiting for a client to become available. */ get tasksQueueLength() { - return this._tasksQueue.length; + return this._self.#tasksQueue.length; } - private _isOpen = false; + #isOpen = false; /** * Whether the pool is open (either connecting or connected). */ get isOpen() { - return this._isOpen; + return this._self.#isOpen; } - private _isClosing = false; + #isClosing = false; /** * Whether the pool is closing (*not* closed). */ get isClosing() { - return this._isClosing; + return this._self.#isClosing; } /** @@ -228,9 +218,9 @@ export class RedisClientPool< ) { super(); - this._clientFactory = clientFactory; - this._options = { - ...RedisClientPool._DEFAULTS, + this.#clientFactory = clientFactory; + this.#options = { + ...RedisClientPool.#DEFAULTS, ...options }; } @@ -253,7 +243,7 @@ export class RedisClientPool< >; } - private _commandOptionsProxy< + #commandOptionsProxy< K extends keyof CommandOptions, V extends CommandOptions[K] >( @@ -276,14 +266,14 @@ export class RedisClientPool< * Override the `typeMapping` command option */ withTypeMapping(typeMapping: TYPE_MAPPING) { - return this._commandOptionsProxy('typeMapping', typeMapping); + return this._self.#commandOptionsProxy('typeMapping', typeMapping); } /** * Override the `abortSignal` command option */ withAbortSignal(abortSignal: AbortSignal) { - return this._commandOptionsProxy('abortSignal', abortSignal); + return this._self.#commandOptionsProxy('abortSignal', abortSignal); } /** @@ -291,17 +281,17 @@ export class RedisClientPool< * TODO: remove? */ asap() { - return this._commandOptionsProxy('asap', true); + return this._self.#commandOptionsProxy('asap', true); } async connect() { - if (this._isOpen) return; // TODO: throw error? + if (this._self.#isOpen) return; // TODO: throw error? - this._isOpen = true; + this._self.#isOpen = true; const promises = []; - while (promises.length < this._options.minimum) { - promises.push(this._create()); + while (promises.length < this._self.#options.minimum) { + promises.push(this._self.#create()); } try { @@ -313,39 +303,39 @@ export class RedisClientPool< } } - private async _create() { - const node = this._clientsInUse.push( - this._clientFactory() + async #create() { + const node = this._self.#clientsInUse.push( + this._self.#clientFactory() .on('error', (err: Error) => this.emit('error', err)) ); try { await node.value.connect(); } catch (err) { - this._clientsInUse.remove(node); + this._self.#clientsInUse.remove(node); throw err; } - this._returnClient(node); + this._self.#returnClient(node); } execute(fn: PoolTask) { return new Promise>((resolve, reject) => { - const client = this._idleClients.shift(), - { tail } = this._tasksQueue; + const client = this._self.#idleClients.shift(), + { tail } = this._self.#tasksQueue; if (!client) { let timeout; - if (this._options.acquireTimeout > 0) { + if (this._self.#options.acquireTimeout > 0) { timeout = setTimeout( () => { - this._tasksQueue.remove(task, tail); + this._self.#tasksQueue.remove(task, tail); reject(new TimeoutError('Timeout waiting for a client')); // TODO: message }, - this._options.acquireTimeout + this._self.#options.acquireTimeout ); } - const task = this._tasksQueue.push({ + const task = this._self.#tasksQueue.push({ timeout, // @ts-ignore resolve, @@ -353,20 +343,20 @@ export class RedisClientPool< fn }); - if (this.totalClients < this._options.maximum) { - this._create(); + if (this.totalClients < this._self.#options.maximum) { + this._self.#create(); } return; } - const node = this._clientsInUse.push(client); + const node = this._self.#clientsInUse.push(client); // @ts-ignore - this._executeTask(node, resolve, reject, fn); + this._self.#executeTask(node, resolve, reject, fn); }); } - private _executeTask( + #executeTask( node: DoublyLinkedNode>, resolve: (value: T | PromiseLike) => void, reject: (reason?: unknown) => void, @@ -375,40 +365,40 @@ export class RedisClientPool< const result = fn(node.value); if (result instanceof Promise) { result.then(resolve, reject); - result.finally(() => this._returnClient(node)) + result.finally(() => this.#returnClient(node)) } else { resolve(result); - this._returnClient(node); + this.#returnClient(node); } } - private _returnClient(node: DoublyLinkedNode>) { - const task = this._tasksQueue.shift(); + #returnClient(node: DoublyLinkedNode>) { + const task = this.#tasksQueue.shift(); if (task) { - this._executeTask(node, task.resolve, task.reject, task.fn); + this.#executeTask(node, task.resolve, task.reject, task.fn); return; } - this._clientsInUse.remove(node); - this._idleClients.push(node.value); + this.#clientsInUse.remove(node); + this.#idleClients.push(node.value); - this._scheduleCleanup(); + this.#scheduleCleanup(); } cleanupTimeout?: NodeJS.Timeout; - private _scheduleCleanup() { - if (this.totalClients <= this._options.minimum) return; + #scheduleCleanup() { + if (this.totalClients <= this.#options.minimum) return; clearTimeout(this.cleanupTimeout); - this.cleanupTimeout = setTimeout(() => this._cleanup(), this._options.cleanupDelay); + this.cleanupTimeout = setTimeout(() => this.#cleanup(), this.#options.cleanupDelay); } - private _cleanup() { - const toDestroy = Math.min(this._idleClients.length, this.totalClients - this._options.minimum); + #cleanup() { + const toDestroy = Math.min(this.#idleClients.length, this.totalClients - this.#options.minimum); for (let i = 0; i < toDestroy; i++) { // TODO: shift vs pop - this._idleClients.shift()!.destroy(); + this.#idleClients.shift()!.destroy(); } } @@ -438,44 +428,44 @@ export class RedisClientPool< multi = this.MULTI; async close() { - if (this._isClosing) return; // TODO: throw err? - if (!this._isOpen) return; // TODO: throw err? + if (this._self.#isClosing) return; // TODO: throw err? + if (!this._self.#isOpen) return; // TODO: throw err? - this._isClosing = true; + this._self.#isClosing = true; try { const promises = []; - for (const client of this._idleClients) { + for (const client of this._self.#idleClients) { promises.push(client.close()); } - for (const client of this._clientsInUse) { + for (const client of this._self.#clientsInUse) { promises.push(client.close()); } await Promise.all(promises); - this._idleClients.reset(); - this._clientsInUse.reset(); + this._self.#idleClients.reset(); + this._self.#clientsInUse.reset(); } catch (err) { } finally { - this._isClosing = false; + this._self.#isClosing = false; } } destroy() { - for (const client of this._idleClients) { + for (const client of this._self.#idleClients) { client.destroy(); } - this._idleClients.reset(); + this._self.#idleClients.reset(); - for (const client of this._clientsInUse) { + for (const client of this._self.#clientsInUse) { client.destroy(); } - this._clientsInUse.reset(); + this._self.#clientsInUse.reset(); - this._isOpen = false; + this._self.#isOpen = false; } } diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 01968c13036..129ace90397 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -46,7 +46,7 @@ interface CreateSocketReturn { export type RedisSocketInitiator = () => Promise; export default class RedisSocket extends EventEmitter { - private static _initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { + static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { options ??= {}; if (!(options as net.IpcSocketConnectOpts).path) { (options as net.TcpSocketConnectOpts).port ??= 6379; @@ -60,45 +60,45 @@ export default class RedisSocket extends EventEmitter { return options; } - private static _isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { + static #isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { return (options as RedisTlsSocketOptions).tls === true; } - private readonly _initiator: RedisSocketInitiator; + readonly #initiator: RedisSocketInitiator; - private readonly _options: RedisSocketOptions; + readonly #options: RedisSocketOptions; - private _socket?: net.Socket | tls.TLSSocket; + #socket?: net.Socket | tls.TLSSocket; - private _isOpen = false; + #isOpen = false; get isOpen(): boolean { - return this._isOpen; + return this.#isOpen; } - private _isReady = false; + #isReady = false; get isReady(): boolean { - return this._isReady; + return this.#isReady; } - private _isSocketUnrefed = false; + #isSocketUnrefed = false; constructor(initiator: RedisSocketInitiator, options?: RedisSocketOptions) { super(); - this._initiator = initiator; - this._options = RedisSocket._initiateOptions(options); + this.#initiator = initiator; + this.#options = RedisSocket.#initiateOptions(options); } - private _reconnectStrategy(retries: number, cause: Error) { - if (this._options.reconnectStrategy === false) { + #reconnectStrategy(retries: number, cause: Error) { + if (this.#options.reconnectStrategy === false) { return false; - } else if (typeof this._options.reconnectStrategy === 'number') { - return this._options.reconnectStrategy; - } else if (this._options.reconnectStrategy) { + } else if (typeof this.#options.reconnectStrategy === 'number') { + return this.#options.reconnectStrategy; + } else if (this.#options.reconnectStrategy) { try { - const retryIn = this._options.reconnectStrategy(retries, cause); + const retryIn = this.#options.reconnectStrategy(retries, cause); if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); } @@ -112,14 +112,14 @@ export default class RedisSocket extends EventEmitter { return Math.min(retries * 50, 500); } - private _shouldReconnect(retries: number, cause: Error) { - const retryIn = this._reconnectStrategy(retries, cause); + #shouldReconnect(retries: number, cause: Error) { + const retryIn = this.#reconnectStrategy(retries, cause); if (retryIn === false) { - this._isOpen = false; + this.#isOpen = false; this.emit('error', cause); return cause; } else if (retryIn instanceof Error) { - this._isOpen = false; + this.#isOpen = false; this.emit('error', cause); return new ReconnectStrategyError(retryIn, cause); } @@ -128,32 +128,32 @@ export default class RedisSocket extends EventEmitter { } async connect(): Promise { - if (this._isOpen) { + if (this.#isOpen) { throw new Error('Socket already opened'); } - this._isOpen = true; - return this._connect(); + this.#isOpen = true; + return this.#connect(); } - private async _connect(): Promise { + async #connect(): Promise { let retries = 0; do { try { - this._socket = await this._createSocket(); + this.#socket = await this.#createSocket(); this.emit('connect'); try { - await this._initiator(); + await this.#initiator(); } catch (err) { - this._socket.destroy(); - this._socket = undefined; + this.#socket.destroy(); + this.#socket = undefined; throw err; } - this._isReady = true; + this.#isReady = true; this.emit('ready'); } catch (err) { - const retryIn = this._shouldReconnect(retries++, err as Error); + const retryIn = this.#shouldReconnect(retries++, err as Error); if (typeof retryIn !== 'number') { throw retryIn; } @@ -162,36 +162,36 @@ export default class RedisSocket extends EventEmitter { await setTimeout(retryIn); this.emit('reconnecting'); } - } while (this._isOpen && !this._isReady); + } while (this.#isOpen && !this.#isReady); } - private _createSocket(): Promise { + #createSocket(): Promise { return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket._isTlsSocket(this._options) ? - this._createTlsSocket() : - this._createNetSocket(); + const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? + this.#createTlsSocket() : + this.#createNetSocket(); - if (this._options.connectTimeout) { - socket.setTimeout(this._options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); + if (this.#options.connectTimeout) { + socket.setTimeout(this.#options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); } - if (this._isSocketUnrefed) { + if (this.#isSocketUnrefed) { socket.unref(); } socket - .setNoDelay(this._options.noDelay) + .setNoDelay(this.#options.noDelay) .once('error', reject) .once(connectEvent, () => { socket .setTimeout(0) // https://github.com/nodejs/node/issues/31663 - .setKeepAlive(this._options.keepAlive !== false, this._options.keepAlive || 0) + .setKeepAlive(this.#options.keepAlive !== false, this.#options.keepAlive || 0) .off('error', reject) - .once('error', (err: Error) => this._onSocketError(err)) + .once('error', (err: Error) => this.#onSocketError(err)) .once('close', hadError => { - if (!hadError && this._isOpen && this._socket === socket) { - this._onSocketError(new SocketClosedUnexpectedlyError()); + if (!hadError && this.#isOpen && this.#socket === socket) { + this.#onSocketError(new SocketClosedUnexpectedlyError()); } }) .on('drain', () => this.emit('drain')) @@ -202,93 +202,93 @@ export default class RedisSocket extends EventEmitter { }); } - private _createNetSocket(): CreateSocketReturn { + #createNetSocket(): CreateSocketReturn { return { connectEvent: 'connect', - socket: net.connect(this._options as net.NetConnectOpts) // TODO + socket: net.connect(this.#options as net.NetConnectOpts) // TODO }; } - private _createTlsSocket(): CreateSocketReturn { + #createTlsSocket(): CreateSocketReturn { return { connectEvent: 'secureConnect', - socket: tls.connect(this._options as tls.ConnectionOptions) // TODO + socket: tls.connect(this.#options as tls.ConnectionOptions) // TODO }; } - private _onSocketError(err: Error): void { - const wasReady = this._isReady; - this._isReady = false; + #onSocketError(err: Error): void { + const wasReady = this.#isReady; + this.#isReady = false; this.emit('error', err); - if (!wasReady || !this._isOpen || typeof this._shouldReconnect(0, err) !== 'number') return; + if (!wasReady || !this.#isOpen || typeof this.#shouldReconnect(0, err) !== 'number') return; this.emit('reconnecting'); - this._connect().catch(() => { + this.#connect().catch(() => { // the error was already emitted, silently ignore it }); } write(iterator: IterableIterator>): void { - if (!this._socket) return; + if (!this.#socket) return; - this._socket.cork(); + this.#socket.cork(); for (const args of iterator) { for (const toWrite of args) { - this._socket.write(toWrite); + this.#socket.write(toWrite); } - if (this._socket.writableNeedDrain) break; + if (this.#socket.writableNeedDrain) break; } - this._socket.uncork(); + this.#socket.uncork(); } async quit(fn: () => Promise): Promise { - if (!this._isOpen) { + if (!this.#isOpen) { throw new ClientClosedError(); } - this._isOpen = false; + this.#isOpen = false; const reply = await fn(); this.destroySocket(); return reply; } close() { - if (!this._isOpen) { + if (!this.#isOpen) { throw new ClientClosedError(); } - this._isOpen = false; + this.#isOpen = false; } destroy() { - if (!this._isOpen) { + if (!this.#isOpen) { throw new ClientClosedError(); } - this._isOpen = false; + this.#isOpen = false; this.destroySocket(); } destroySocket() { - this._isReady = false; + this.#isReady = false; - if (this._socket) { - this._socket.destroy(); - this._socket = undefined; + if (this.#socket) { + this.#socket.destroy(); + this.#socket = undefined; } this.emit('end'); } ref(): void { - this._isSocketUnrefed = false; - this._socket?.ref(); + this.#isSocketUnrefed = false; + this.#socket?.ref(); } unref(): void { - this._isSocketUnrefed = true; - this._socket?.unref(); + this.#isSocketUnrefed = true; + this.#socket?.unref(); } } diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 514e7805855..dee133176a9 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -100,83 +100,83 @@ export default class RedisClusterSlots< RESP extends RespVersions, TYPE_MAPPING extends TypeMapping > { - private static _SLOTS = 16384; + static #SLOTS = 16384; - private readonly _options: RedisClusterOptions; - private readonly _clientFactory: ReturnType>; - private readonly _emit: EventEmitter['emit']; - slots = new Array>(RedisClusterSlots._SLOTS); + readonly #options: RedisClusterOptions; + readonly #clientFactory: ReturnType>; + readonly #emit: EventEmitter['emit']; + slots = new Array>(RedisClusterSlots.#SLOTS); masters = new Array>(); replicas = new Array>(); readonly nodeByAddress = new Map | ShardNode>(); pubSubNode?: PubSubNode; - private _isOpen = false; + #isOpen = false; get isOpen() { - return this._isOpen; + return this.#isOpen; } constructor( options: RedisClusterOptions, emit: EventEmitter['emit'] ) { - this._options = options; - this._clientFactory = RedisClient.factory(options); - this._emit = emit; + this.#options = options; + this.#clientFactory = RedisClient.factory(options); + this.#emit = emit; } async connect() { - if (this._isOpen) { + if (this.#isOpen) { throw new Error('Cluster already open'); } - this._isOpen = true; + this.#isOpen = true; try { - await this._discoverWithRootNodes(); + await this.#discoverWithRootNodes(); } catch (err) { - this._isOpen = false; + this.#isOpen = false; throw err; } } - private async _discoverWithRootNodes() { - let start = Math.floor(Math.random() * this._options.rootNodes.length); - for (let i = start; i < this._options.rootNodes.length; i++) { - if (!this._isOpen) throw new Error('Cluster closed'); - if (await this._discover(this._options.rootNodes[i])) return; + async #discoverWithRootNodes() { + let start = Math.floor(Math.random() * this.#options.rootNodes.length); + for (let i = start; i < this.#options.rootNodes.length; i++) { + if (!this.#isOpen) throw new Error('Cluster closed'); + if (await this.#discover(this.#options.rootNodes[i])) return; } for (let i = 0; i < start; i++) { - if (!this._isOpen) throw new Error('Cluster closed'); - if (await this._discover(this._options.rootNodes[i])) return; + if (!this.#isOpen) throw new Error('Cluster closed'); + if (await this.#discover(this.#options.rootNodes[i])) return; } throw new RootNodesUnavailableError(); } - private _resetSlots() { - this.slots = new Array(RedisClusterSlots._SLOTS); + #resetSlots() { + this.slots = new Array(RedisClusterSlots.#SLOTS); this.masters = []; this.replicas = []; this._randomNodeIterator = undefined; } - private async _discover(rootNode: RedisClusterClientOptions) { - this._resetSlots(); + async #discover(rootNode: RedisClusterClientOptions) { + this.#resetSlots(); try { const addressesInUse = new Set(), promises: Array> = [], - eagerConnect = this._options.minimizeConnections !== true; + eagerConnect = this.#options.minimizeConnections !== true; - for (const { from, to, master, replicas } of await this._getShards(rootNode)) { + for (const { from, to, master, replicas } of await this.#getShards(rootNode)) { const shard: Shard = { - master: this._initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) + master: this.#initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) }; - if (this._options.useReplicas) { + if (this.#options.useReplicas) { shard.replicas = replicas.map(replica => - this._initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises) + this.#initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises) ); } @@ -193,7 +193,7 @@ export default class RedisClusterSlots< if (channelsListeners.size || patternsListeners.size) { promises.push( - this._initiatePubSubClient({ + this.#initiatePubSubClient({ [PubSubType.CHANNELS]: channelsListeners, [PubSubType.PATTERNS]: patternsListeners }) @@ -220,21 +220,21 @@ export default class RedisClusterSlots< return true; } catch (err) { - this._emit('error', err); + this.#emit('error', err); return false; } } - private async _getShards(rootNode: RedisClusterClientOptions) { - const options = this._clientOptionsDefaults(rootNode)!; + async #getShards(rootNode: RedisClusterClientOptions) { + const options = this.#clientOptionsDefaults(rootNode)!; options.socket ??= {}; options.socket.reconnectStrategy = false; - options.RESP = this._options.RESP; + options.RESP = this.#options.RESP; options.commandOptions = undefined; // TODO: find a way to avoid type casting - const client = await this._clientFactory(options as RedisClientOptions) - .on('error', err => this._emit('error', err)) + const client = await this.#clientFactory(options as RedisClientOptions) + .on('error', err => this.#emit('error', err)) .connect(); try { @@ -245,37 +245,37 @@ export default class RedisClusterSlots< } } - private _getNodeAddress(address: string): NodeAddress | undefined { - switch (typeof this._options.nodeAddressMap) { + #getNodeAddress(address: string): NodeAddress | undefined { + switch (typeof this.#options.nodeAddressMap) { case 'object': - return this._options.nodeAddressMap[address]; + return this.#options.nodeAddressMap[address]; case 'function': - return this._options.nodeAddressMap(address); + return this.#options.nodeAddressMap(address); } } - private _clientOptionsDefaults(options?: RedisClientOptions) { - if (!this._options.defaults) return options; + #clientOptionsDefaults(options?: RedisClientOptions) { + if (!this.#options.defaults) return options; let socket; - if (this._options.defaults.socket) { + if (this.#options.defaults.socket) { socket = options?.socket ? { - ...this._options.defaults.socket, + ...this.#options.defaults.socket, ...options.socket - } : this._options.defaults.socket; + } : this.#options.defaults.socket; } else { socket = options?.socket; } return { - ...this._options.defaults, + ...this.#options.defaults, ...options, socket }; } - private _initiateSlotNode( + #initiateSlotNode( shard: NodeAddress & { id: string; }, readonly: boolean, eagerConnent: boolean, @@ -295,7 +295,7 @@ export default class RedisClusterSlots< }; if (eagerConnent) { - promises.push(this._createNodeClient(node)); + promises.push(this.#createNodeClient(node)); } this.nodeByAddress.set(address, node); @@ -309,21 +309,21 @@ export default class RedisClusterSlots< return node; } - private _createClient(node: ShardNode, readonly = node.readonly) { - return this._clientFactory( - this._clientOptionsDefaults({ - socket: this._getNodeAddress(node.address) ?? { + #createClient(node: ShardNode, readonly = node.readonly) { + return this.#clientFactory( + this.#clientOptionsDefaults({ + socket: this.#getNodeAddress(node.address) ?? { host: node.host, port: node.port }, readonly, - RESP: this._options.RESP + RESP: this.#options.RESP }) ).on('error', err => console.error(err)); } - private _createNodeClient(node: ShardNode, readonly?: boolean) { - const client = node.client = this._createClient(node, readonly); + #createNodeClient(node: ShardNode, readonly?: boolean) { + const client = node.client = this.#createClient(node, readonly); return node.connectPromise = client.connect() .finally(() => node.connectPromise = undefined); } @@ -332,46 +332,46 @@ export default class RedisClusterSlots< return ( node.connectPromise ?? // if the node is connecting node.client ?? // if the node is connected - this._createNodeClient(node) // if the not is disconnected + this.#createNodeClient(node) // if the not is disconnected ); } - private _runningRediscoverPromise?: Promise; + #runningRediscoverPromise?: Promise; async rediscover(startWith: RedisClientType): Promise { - this._runningRediscoverPromise ??= this._rediscover(startWith) - .finally(() => this._runningRediscoverPromise = undefined); - return this._runningRediscoverPromise; + this.#runningRediscoverPromise ??= this.#rediscover(startWith) + .finally(() => this.#runningRediscoverPromise = undefined); + return this.#runningRediscoverPromise; } - private async _rediscover(startWith: RedisClientType): Promise { - if (await this._discover(startWith.options!)) return; + async #rediscover(startWith: RedisClientType): Promise { + if (await this.#discover(startWith.options!)) return; - return this._discoverWithRootNodes(); + return this.#discoverWithRootNodes(); } /** * @deprecated Use `close` instead. */ quit(): Promise { - return this._destroy(client => client.quit()); + return this.#destroy(client => client.quit()); } /** * @deprecated Use `destroy` instead. */ disconnect(): Promise { - return this._destroy(client => client.disconnect()); + return this.#destroy(client => client.disconnect()); } close() { - return this._destroy(client => client.close()); + return this.#destroy(client => client.close()); } destroy() { - this._isOpen = false; + this.#isOpen = false; - for (const client of this._clients()) { + for (const client of this.#clients()) { client.destroy(); } @@ -380,11 +380,11 @@ export default class RedisClusterSlots< this.pubSubNode = undefined; } - this._resetSlots(); + this.#resetSlots(); this.nodeByAddress.clear(); } - private *_clients() { + *#clients() { for (const master of this.masters) { if (master.client) { yield master.client; @@ -402,11 +402,11 @@ export default class RedisClusterSlots< } } - private async _destroy(fn: (client: RedisClientType) => Promise): Promise { - this._isOpen = false; + async #destroy(fn: (client: RedisClientType) => Promise): Promise { + this.#isOpen = false; const promises = []; - for (const client of this._clients()) { + for (const client of this.#clients()) { promises.push(fn(client)); } @@ -415,7 +415,7 @@ export default class RedisClusterSlots< this.pubSubNode = undefined; } - this._resetSlots(); + this.#resetSlots(); this.nodeByAddress.clear(); await Promise.allSettled(promises); @@ -437,7 +437,7 @@ export default class RedisClusterSlots< return this.nodeClient(this.getSlotRandomNode(slotNumber)); } - private *_iterateAllNodes() { + *#iterateAllNodes() { let i = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); if (i < this.masters.length) { do { @@ -468,11 +468,11 @@ export default class RedisClusterSlots< _randomNodeIterator?: IterableIterator>; getRandomNode() { - this._randomNodeIterator ??= this._iterateAllNodes(); + this._randomNodeIterator ??= this.#iterateAllNodes(); return this._randomNodeIterator.next().value as ShardNode; } - private *_slotNodesIterator(slot: ShardWithReplicas) { + *#slotNodesIterator(slot: ShardWithReplicas) { let i = Math.floor(Math.random() * (1 + slot.replicas.length)); if (i < slot.replicas.length) { do { @@ -495,7 +495,7 @@ export default class RedisClusterSlots< return slot.master; } - slot.nodesIterator ??= this._slotNodesIterator(slot as ShardWithReplicas); + slot.nodesIterator ??= this.#slotNodesIterator(slot as ShardWithReplicas); return slot.nodesIterator.next().value as ShardNode; } @@ -507,17 +507,17 @@ export default class RedisClusterSlots< } getPubSubClient() { - if (!this.pubSubNode) return this._initiatePubSubClient(); + if (!this.pubSubNode) return this.#initiatePubSubClient(); return this.pubSubNode.connectPromise ?? this.pubSubNode.client; } - private async _initiatePubSubClient(toResubscribe?: PubSubToResubscribe) { + async #initiatePubSubClient(toResubscribe?: PubSubToResubscribe) { const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), node = index < this.masters.length ? this.masters[index] : this.replicas[index - this.masters.length], - client = this._createClient(node, true); + client = this.#createClient(node, true); this.pubSubNode = { address: node.address, @@ -557,12 +557,12 @@ export default class RedisClusterSlots< getShardedPubSubClient(channel: string) { const { master } = this.slots[calculateSlot(channel)]; - if (!master.pubSub) return this._initiateShardedPubSubClient(master); + if (!master.pubSub) return this.#initiateShardedPubSubClient(master); return master.pubSub.connectPromise ?? master.pubSub.client; } - private async _initiateShardedPubSubClient(master: MasterNode) { - const client = this._createClient(master, true) + async #initiateShardedPubSubClient(master: MasterNode) { + const client = this.#createClient(master, true) .on('server-sunsubscribe', async (channel, listeners) => { try { await this.rediscover(client); @@ -573,7 +573,7 @@ export default class RedisClusterSlots< listeners ); } catch (err) { - this._emit('sharded-shannel-moved-error', err, channel, listeners); + this.#emit('sharded-shannel-moved-error', err, channel, listeners); } }); diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index a350eb37f59..c2987a69157 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -132,7 +132,7 @@ export interface ClusterCommandOptions< type ProxyCluster = RedisCluster; -type NamespaceProxyCluster = { self: ProxyCluster }; +type NamespaceProxyCluster = { _self: ProxyCluster }; export default class RedisCluster< M extends RedisModules, @@ -166,7 +166,7 @@ export default class RedisCluster< return key; } - private static _createCommand(command: Command, resp: RespVersions) { + static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyCluster, ...args: Array) { const redisArgs = command.transformArguments(...args), @@ -189,7 +189,7 @@ export default class RedisCluster< }; } - private static _createModuleCommand(command: Command, resp: RespVersions) { + static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyCluster, ...args: Array) { const redisArgs = command.transformArguments(...args), @@ -198,11 +198,11 @@ export default class RedisCluster< args, redisArgs ), - reply = await this.self.sendCommand( + reply = await this._self.sendCommand( firstKey, command.IS_READ_ONLY, redisArgs, - this.self._commandOptions, + this._self._commandOptions, // command.POLICIES ); @@ -212,7 +212,7 @@ export default class RedisCluster< }; } - private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyCluster, ...args: Array) { @@ -223,11 +223,11 @@ export default class RedisCluster< fnArgs ), redisArgs = prefix.concat(fnArgs), - reply = await this.self.sendCommand( + reply = await this._self.sendCommand( firstKey, fn.IS_READ_ONLY, redisArgs, - this.self._commandOptions, + this._self._commandOptions, // fn.POLICIES ); @@ -237,7 +237,7 @@ export default class RedisCluster< }; } - private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + static #createScriptCommand(script: RedisScript, resp: RespVersions) { const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyCluster, ...args: Array) { @@ -274,17 +274,17 @@ export default class RedisCluster< const Cluster = attachConfig({ BaseClass: RedisCluster, commands: COMMANDS, - createCommand: RedisCluster._createCommand, - createModuleCommand: RedisCluster._createModuleCommand, - createFunctionCommand: RedisCluster._createFunctionCommand, - createScriptCommand: RedisCluster._createScriptCommand, + createCommand: RedisCluster.#createCommand, + createModuleCommand: RedisCluster.#createModuleCommand, + createFunctionCommand: RedisCluster.#createFunctionCommand, + createScriptCommand: RedisCluster.#createScriptCommand, config }); Cluster.prototype.Multi = RedisClusterMultiCommand.extend(config); return (options?: Omit>) => { - // returning a "proxy" to prevent the namespaces.self to leak between "proxies" + // returning a "proxy" to prevent the namespaces._self to leak between "proxies" return Object.create(new Cluster(options)) as RedisClusterType; }; } @@ -300,10 +300,11 @@ export default class RedisCluster< return RedisCluster.factory(options)(options); } - private readonly _options: RedisClusterOptions; + readonly #options: RedisClusterOptions; - private readonly _slots: RedisClusterSlots; + readonly #slots: RedisClusterSlots; + private _self = this; private _commandOptions?: ClusterCommandOptions; /** @@ -311,7 +312,7 @@ export default class RedisCluster< * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). */ get slots() { - return this._slots.slots; + return this._self.#slots.slots; } /** @@ -319,7 +320,7 @@ export default class RedisCluster< * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific master node. */ get masters() { - return this._slots.masters; + return this._self.#slots.masters; } /** @@ -327,7 +328,7 @@ export default class RedisCluster< * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific replica node. */ get replicas() { - return this._slots.replicas; + return this._self.#slots.replicas; } /** @@ -335,25 +336,25 @@ export default class RedisCluster< * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). */ get nodeByAddress() { - return this._slots.nodeByAddress; + return this._self.#slots.nodeByAddress; } /** * The current pub/sub node. */ get pubSubNode() { - return this._slots.pubSubNode; + return this._self.#slots.pubSubNode; } get isOpen() { - return this._slots.isOpen; + return this._self.#slots.isOpen; } constructor(options: RedisClusterOptions) { super(); - this._options = options; - this._slots = new RedisClusterSlots(options, this.emit.bind(this)); + this.#options = options; + this.#slots = new RedisClusterSlots(options, this.emit.bind(this)); if (options?.commandOptions) { this._commandOptions = options.commandOptions; @@ -368,14 +369,14 @@ export default class RedisCluster< _TYPE_MAPPING extends TypeMapping = TYPE_MAPPING >(overrides?: Partial>) { return new (Object.getPrototypeOf(this).constructor)({ - ...this._options, + ...this._self.#options, commandOptions: this._commandOptions, ...overrides }) as RedisClusterType<_M, _F, _S, _RESP, _TYPE_MAPPING>; } connect() { - return this._slots.connect(); + return this._self.#slots.connect(); } withCommandOptions< @@ -430,13 +431,13 @@ export default class RedisCluster< // return this._commandOptionsProxy('policies', policies); // } - private async _execute( + async #execute( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, fn: (client: RedisClientType) => Promise ): Promise { - const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; - let client = await this._slots.getClient(firstKey, isReadonly), + const maxCommandRedirections = this.#options.maxCommandRedirections ?? 16; + let client = await this.#slots.getClient(firstKey, isReadonly), i = 0; while (true) { try { @@ -449,10 +450,10 @@ export default class RedisCluster< if (err.message.startsWith('ASK')) { const address = err.message.substring(err.message.lastIndexOf(' ') + 1); - let redirectTo = await this._slots.getMasterByAddress(address); + let redirectTo = await this.#slots.getMasterByAddress(address); if (!redirectTo) { - await this._slots.rediscover(client); - redirectTo = await this._slots.getMasterByAddress(address); + await this.#slots.rediscover(client); + redirectTo = await this.#slots.getMasterByAddress(address); } if (!redirectTo) { @@ -465,8 +466,8 @@ export default class RedisCluster< } if (err.message.startsWith('MOVED')) { - await this._slots.rediscover(client); - client = await this._slots.getClient(firstKey, isReadonly); + await this.#slots.rediscover(client); + client = await this.#slots.getClient(firstKey, isReadonly); continue; } @@ -482,7 +483,7 @@ export default class RedisCluster< options?: ClusterCommandOptions, // defaultPolicies?: CommandPolicies ): Promise { - return this._execute( + return this._self.#execute( firstKey, isReadonly, client => client.sendCommand(args, options) @@ -496,7 +497,7 @@ export default class RedisCluster< args: Array, options?: CommandOptions ) { - return this._execute( + return this._self.#execute( firstKey, isReadonly, client => client.executeScript(script, args, options) @@ -507,11 +508,11 @@ export default class RedisCluster< type Multi = new (...args: ConstructorParameters) => RedisClusterMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING>; return new ((this as any).Multi as Multi)( async (firstKey, isReadonly, commands) => { - const client = await this._slots.getClient(firstKey, isReadonly); + const client = await this._self.#slots.getClient(firstKey, isReadonly); return client._executeMulti(commands); }, async (firstKey, isReadonly, commands) => { - const client = await this._slots.getClient(firstKey, isReadonly); + const client = await this._self.#slots.getClient(firstKey, isReadonly); return client._executePipeline(commands); }, routing @@ -525,7 +526,7 @@ export default class RedisCluster< listener: PubSubListener, bufferMode?: T ) { - return (await this._slots.getPubSubClient()) + return (await this._self.#slots.getPubSubClient()) .SUBSCRIBE(channels, listener, bufferMode); } @@ -536,7 +537,7 @@ export default class RedisCluster< listener?: PubSubListener, bufferMode?: T ) { - return this._slots.executeUnsubscribeCommand(client => + return this._self.#slots.executeUnsubscribeCommand(client => client.UNSUBSCRIBE(channels, listener, bufferMode) ); } @@ -548,7 +549,7 @@ export default class RedisCluster< listener: PubSubListener, bufferMode?: T ) { - return (await this._slots.getPubSubClient()) + return (await this._self.#slots.getPubSubClient()) .PSUBSCRIBE(patterns, listener, bufferMode); } @@ -559,7 +560,7 @@ export default class RedisCluster< listener?: PubSubListener, bufferMode?: T ) { - return this._slots.executeUnsubscribeCommand(client => + return this._self.#slots.executeUnsubscribeCommand(client => client.PUNSUBSCRIBE(patterns, listener, bufferMode) ); } @@ -571,9 +572,9 @@ export default class RedisCluster< listener: PubSubListener, bufferMode?: T ) { - const maxCommandRedirections = this._options.maxCommandRedirections ?? 16, + const maxCommandRedirections = this._self.#options.maxCommandRedirections ?? 16, firstChannel = Array.isArray(channels) ? channels[0] : channels; - let client = await this._slots.getShardedPubSubClient(firstChannel); + let client = await this._self.#slots.getShardedPubSubClient(firstChannel); for (let i = 0; ; i++) { try { return await client.SSUBSCRIBE(channels, listener, bufferMode); @@ -583,8 +584,8 @@ export default class RedisCluster< } if (err.message.startsWith('MOVED')) { - await this._slots.rediscover(client); - client = await this._slots.getShardedPubSubClient(firstChannel); + await this._self.#slots.rediscover(client); + client = await this._self.#slots.getShardedPubSubClient(firstChannel); continue; } @@ -600,7 +601,7 @@ export default class RedisCluster< listener: PubSubListener, bufferMode?: T ) { - return this._slots.executeShardedUnsubscribeCommand( + return this._self.#slots.executeShardedUnsubscribeCommand( Array.isArray(channels) ? channels[0] : channels, client => client.SUNSUBSCRIBE(channels, listener, bufferMode) ); @@ -612,26 +613,26 @@ export default class RedisCluster< * @deprecated Use `close` instead. */ quit() { - return this._slots.quit(); + return this._self.#slots.quit(); } /** * @deprecated Use `destroy` instead. */ disconnect() { - return this._slots.disconnect(); + return this._self.#slots.disconnect(); } close() { - return this._slots.close(); + return this._self.#slots.close(); } destroy() { - return this._slots.destroy(); + return this._self.#slots.destroy(); } nodeClient(node: ShardNode) { - return this._slots.nodeClient(node); + return this._self.#slots.nodeClient(node); } /** @@ -639,7 +640,7 @@ export default class RedisCluster< * Userful for running "forward" commands (like PUBLISH) on a random node. */ getRandomNode() { - return this._slots.getRandomNode(); + return this._self.#slots.getRandomNode(); } /** @@ -647,7 +648,7 @@ export default class RedisCluster< * Useful for running readonly commands on a slot. */ getSlotRandomNode(slot: number) { - return this._slots.getSlotRandomNode(slot); + return this._self.#slots.getSlotRandomNode(slot); } /** diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index 531c00f1d5e..225d1624653 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -91,7 +91,7 @@ export type ClusterMultiExecute = ( ) => Promise>; export default class RedisClusterMultiCommand { - private static _createCommand(command: Command, resp: RespVersions) { + static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return function (this: RedisClusterMultiCommand, ...args: Array) { const redisArgs = command.transformArguments(...args), @@ -109,16 +109,16 @@ export default class RedisClusterMultiCommand { }; } - private static _createModuleCommand(command: Command, resp: RespVersions) { + static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); - return function (this: { self: RedisClusterMultiCommand }, ...args: Array) { + return function (this: { _self: RedisClusterMultiCommand }, ...args: Array) { const redisArgs = command.transformArguments(...args), firstKey = RedisCluster.extractFirstKey( command, args, redisArgs ); - return this.self.addCommand( + return this._self.addCommand( firstKey, command.IS_READ_ONLY, redisArgs, @@ -127,10 +127,10 @@ export default class RedisClusterMultiCommand { }; } - private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + static #createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); - return function (this: { self: RedisClusterMultiCommand }, ...args: Array) { + return function (this: { _self: RedisClusterMultiCommand }, ...args: Array) { const fnArgs = fn.transformArguments(...args), redisArgs: CommandArguments = prefix.concat(fnArgs), firstKey = RedisCluster.extractFirstKey( @@ -139,7 +139,7 @@ export default class RedisClusterMultiCommand { fnArgs ); redisArgs.preserve = fnArgs.preserve; - return this.self.addCommand( + return this._self.addCommand( firstKey, fn.IS_READ_ONLY, redisArgs, @@ -148,11 +148,11 @@ export default class RedisClusterMultiCommand { }; } - private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + static #createScriptCommand(script: RedisScript, resp: RespVersions) { const transformReply = getTransformReply(script, resp); return function (this: RedisClusterMultiCommand, ...args: Array) { const scriptArgs = script.transformArguments(...args); - this._setState( + this.#setState( RedisCluster.extractFirstKey( script, args, @@ -160,7 +160,7 @@ export default class RedisClusterMultiCommand { ), script.IS_READ_ONLY ); - this._multi.addScript( + this.#multi.addScript( script, scriptArgs, transformReply @@ -178,36 +178,36 @@ export default class RedisClusterMultiCommand { return attachConfig({ BaseClass: RedisClusterMultiCommand, commands: COMMANDS, - createCommand: RedisClusterMultiCommand._createCommand, - createModuleCommand: RedisClusterMultiCommand._createModuleCommand, - createFunctionCommand: RedisClusterMultiCommand._createFunctionCommand, - createScriptCommand: RedisClusterMultiCommand._createScriptCommand, + createCommand: RedisClusterMultiCommand.#createCommand, + createModuleCommand: RedisClusterMultiCommand.#createModuleCommand, + createFunctionCommand: RedisClusterMultiCommand.#createFunctionCommand, + createScriptCommand: RedisClusterMultiCommand.#createScriptCommand, config }); } - private readonly _multi = new RedisMultiCommand(); - private readonly _executeMulti: ClusterMultiExecute; - private readonly _executePipeline: ClusterMultiExecute; - private _firstKey: RedisArgument | undefined; - private _isReadonly: boolean | undefined = true; + readonly #multi = new RedisMultiCommand(); + readonly #executeMulti: ClusterMultiExecute; + readonly #executePipeline: ClusterMultiExecute; + #firstKey: RedisArgument | undefined; + #isReadonly: boolean | undefined = true; constructor( executeMulti: ClusterMultiExecute, executePipeline: ClusterMultiExecute, routing: RedisArgument | undefined ) { - this._executeMulti = executeMulti; - this._executePipeline = executePipeline; - this._firstKey = routing; + this.#executeMulti = executeMulti; + this.#executePipeline = executePipeline; + this.#firstKey = routing; } - private _setState( + #setState( firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, ) { - this._firstKey ??= firstKey; - this._isReadonly &&= isReadonly; + this.#firstKey ??= firstKey; + this.#isReadonly &&= isReadonly; } addCommand( @@ -216,19 +216,19 @@ export default class RedisClusterMultiCommand { args: CommandArguments, transformReply?: TransformReply ) { - this._setState(firstKey, isReadonly); - this._multi.addCommand(args, transformReply); + this.#setState(firstKey, isReadonly); + this.#multi.addCommand(args, transformReply); return this; } async exec(execAsPipeline = false) { if (execAsPipeline) return this.execAsPipeline(); - return this._multi.transformReplies( - await this._executeMulti( - this._firstKey, - this._isReadonly, - this._multi.queue + return this.#multi.transformReplies( + await this.#executeMulti( + this.#firstKey, + this.#isReadonly, + this.#multi.queue ) ) as MultiReplyType; } @@ -240,13 +240,13 @@ export default class RedisClusterMultiCommand { } async execAsPipeline() { - if (this._multi.queue.length === 0) return [] as MultiReplyType; + if (this.#multi.queue.length === 0) return [] as MultiReplyType; - return this._multi.transformReplies( - await this._executePipeline( - this._firstKey, - this._isReadonly, - this._multi.queue + return this.#multi.transformReplies( + await this.#executePipeline( + this.#firstKey, + this.#isReadonly, + this.#multi.queue ) ) as MultiReplyType; } diff --git a/packages/client/lib/commander.ts b/packages/client/lib/commander.ts index b1db7e701f4..d96aaa7128e 100644 --- a/packages/client/lib/commander.ts +++ b/packages/client/lib/commander.ts @@ -71,7 +71,7 @@ function attachNamespace(prototype: any, name: PropertyKey, fns: any) { Object.defineProperty(prototype, name, { get() { const value = Object.create(fns); - value.self = this; + value._self = this; Object.defineProperty(this, name, { value }); return value; } From c1fc0feed011b69a4d19a493ba5ff9ef0d0f4f06 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 3 Jan 2024 11:46:09 -0500 Subject: [PATCH 297/325] #2670 #2668 - add note about command modifiers that changes the reply type --- packages/redis/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/redis/README.md b/packages/redis/README.md index 4d20fd1cd78..82386d725de 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -85,6 +85,8 @@ await client.set('key', 'value', { }); ``` +> NOTE: command modifiers that change the reply type (e.g. `WITHSCORES` for `ZDIFF`) are exposed as separate commands (e.g. `ZDIFF_WITHSCORES`/`zDiffWithScores`). + Replies will be mapped to useful data structures: ```javascript From 0f188a4eec84c4987e51e7d97b3a393cb6c558c8 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Tue, 16 Jan 2024 15:16:51 -0500 Subject: [PATCH 298/325] make `cluster.connect()` return `this` --- packages/client/lib/cluster/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index c2987a69157..e26582942d2 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -375,8 +375,9 @@ export default class RedisCluster< }) as RedisClusterType<_M, _F, _S, _RESP, _TYPE_MAPPING>; } - connect() { - return this._self.#slots.connect(); + async connect() { + await this._self.#slots.connect(); + return this as unknown as RedisClusterType; } withCommandOptions< From 97463e9dcc06a97e6e0872d24b97d24334b74007 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 17 Jan 2024 15:30:01 -0500 Subject: [PATCH 299/325] chain pipeline commands --- docs/transactions.md | 24 ++++++++++++++++++++++++ docs/v4-to-v5.md | 13 +++++++++++++ packages/client/lib/client/index.ts | 12 +++++++----- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/docs/transactions.md b/docs/transactions.md index f71eb50b374..542061ebbc0 100644 --- a/docs/transactions.md +++ b/docs/transactions.md @@ -27,3 +27,27 @@ await multi.execTyped(); // [string] You can also [watch](https://redis.io/docs/interact/transactions/#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. The `WATCH` state is stored on the connection (by the server). In case you need to run multiple `WATCH` & `MULTI` in parallel you'll need to use a [pool](./pool.md). + +## `execAsPipeline` + +`execAsPipeline` will execute the commands without "wrapping" it with `MULTI` & `EXEC` (and lose the transactional semantics). + +```javascript +await client.multi() + .get('a') + .get('b') + .execAsPipeline(); +``` + +the diffrence between the above pipeline and `Promise.all`: + +```javascript +await Promise.all([ + client.get('a'), + client.get('b') +]); +``` + +is that if the socket disconnects during the pipeline, any unwritten commands will be discarded. i.e. if the socket disconnects after `GET a` is written to the socket, but before `GET b` is: +- using `Promise.all` - the client will try to execute `GET b` when the socket reconnects +- using `execAsPipeline` - `GET b` promise will be rejected as well diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 83dde28c7c7..0863c7478a9 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -125,6 +125,19 @@ await cluster.multi() .exec(); ``` +## `MULTI.execAsPipeline()` + +```javascript +await client.multi() + .set('a', 'a') + .set('b', 'b') + .execAsPipeline(); +``` + +In older versions, if the socket disconnects during the pipeline execution, i.e. after writing `SET a a` and before `SET b b`, the returned promise is rejected, but `SET b b` will still be executed on the server. + +In v5, any unwritten commands (in the same pipeline) will be discarded. + ## Commands ### Redis diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 51a4a478d5f..7d9cadde2eb 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -749,11 +749,13 @@ export default class RedisClient< return Promise.reject(new ClientClosedError()); } - const promise = Promise.all( - commands.map(({ args }) => this._self.#queue.addCommand(args, { - typeMapping: this._commandOptions?.typeMapping - })) - ); + const chainId = Symbol('Pipeline Chain'), + promise = Promise.all( + commands.map(({ args }) => this._self.#queue.addCommand(args, { + chainId, + typeMapping: this._commandOptions?.typeMapping + })) + ); this._self.#scheduleWrite(); const result = await promise; From 455939c775a12fe3adfa405ea709b8f11a7f417c Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 17 Jan 2024 18:33:46 -0500 Subject: [PATCH 300/325] fix pubsub listener type --- packages/client/lib/client/pub-sub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/pub-sub.ts b/packages/client/lib/client/pub-sub.ts index 91c771a57e7..7c29099d71b 100644 --- a/packages/client/lib/client/pub-sub.ts +++ b/packages/client/lib/client/pub-sub.ts @@ -26,7 +26,7 @@ const COMMANDS = { export type PubSubListener< RETURN_BUFFERS extends boolean = false -> = (message: T, channel: T) => unknown; +> = (message: T, channel: T) => unknown; export interface ChannelListeners { unsubscribing: boolean; From dded3de090ebed5c9a4e0666c38e00b402907bda Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 24 Jan 2024 12:28:30 -0500 Subject: [PATCH 301/325] fix monitor, add client.reset & client.resetState, some fixes --- packages/client/lib/client/commands-queue.ts | 279 +++++++++++-------- packages/client/lib/client/index.spec.ts | 6 +- packages/client/lib/client/index.ts | 164 ++++++----- packages/client/lib/client/pool.ts | 1 + packages/client/lib/client/pub-sub.ts | 27 +- packages/client/lib/client/socket.ts | 2 +- 6 files changed, 283 insertions(+), 196 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 6261b5dd191..03851b4bee9 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,10 +1,9 @@ import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list'; import encodeCommand from '../RESP/encoder'; import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder'; -import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP/types'; +import { CommandArguments, TypeMapping, ReplyUnion, RespVersions, SimpleStringReply, ReplyWithTypeMapping } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; -import { EventEmitter } from 'node:stream'; import { MonitorCallback } from '.'; export interface CommandOptions { @@ -19,24 +18,24 @@ export interface CommandOptions { export interface CommandToWrite extends CommandWaitingForReply { args: CommandArguments; - chainId?: symbol; - abort?: { + chainId: symbol | undefined; + abort: { signal: AbortSignal; listener: () => unknown; - }; - resolveOnWrite?: boolean; + } | undefined; } interface CommandWaitingForReply { resolve(reply?: unknown): void; reject(err: unknown): void; - channelsCounter?: number; - typeMapping?: TypeMapping; + channelsCounter: number | undefined; + typeMapping: TypeMapping | undefined; } export type OnShardedChannelMoved = (channel: string, listeners: ChannelListeners) => void; -const PONG = Buffer.from('pong'); +const PONG = Buffer.from('pong'), + RESET = Buffer.from('RESET'); const RESP2_PUSH_TYPE_MAPPING = { ...PUSH_TYPE_MAPPING, @@ -44,35 +43,28 @@ const RESP2_PUSH_TYPE_MAPPING = { }; export default class RedisCommandsQueue { - readonly #maxLength: number | null | undefined; + readonly #respVersion; + readonly #maxLength; readonly #toWrite = new DoublyLinkedList(); readonly #waitingForReply = new SinglyLinkedList(); - readonly #onShardedChannelMoved: OnShardedChannelMoved; - + readonly #onShardedChannelMoved; + #chainInExecution: symbol | undefined; + readonly decoder; readonly #pubSub = new PubSub(); get isPubSubActive() { return this.#pubSub.isActive; } - #chainInExecution: symbol | undefined; - - decoder: Decoder; - constructor( - respVersion: RespVersions | null | undefined, + respVersion: RespVersions, maxLength: number | null | undefined, - onShardedChannelMoved: EventEmitter['emit'] + onShardedChannelMoved: OnShardedChannelMoved ) { - this.decoder = this.#initiateDecoder(respVersion); + this.#respVersion = respVersion; this.#maxLength = maxLength; this.#onShardedChannelMoved = onShardedChannelMoved; - } - - #initiateDecoder(respVersion: RespVersions | null | undefined) { - return respVersion === 3 ? - this.#initiateResp3Decoder() : - this.#initiateResp2Decoder(); + this.decoder = this.#initiateDecoder(); } #onReply(reply: ReplyUnion) { @@ -111,7 +103,7 @@ export default class RedisCommandsQueue { return this.#waitingForReply.head!.value.typeMapping ?? {}; } - #initiateResp3Decoder() { + #initiateDecoder() { return new Decoder({ onReply: reply => this.#onReply(reply), onErrorReply: err => this.#onErrorReply(err), @@ -124,61 +116,9 @@ export default class RedisCommandsQueue { }); } - #initiateResp2Decoder() { - return new Decoder({ - onReply: reply => { - if (this.#pubSub.isActive && Array.isArray(reply)) { - if (this.#onPush(reply)) return; - - if (PONG.equals(reply[0] as Buffer)) { - const { resolve, typeMapping } = this.#waitingForReply.shift()!, - buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); - return; - } - } - - this.#onReply(reply); - }, - onErrorReply: err => this.#onErrorReply(err), - // PUSH type does not exist in RESP2 - // PubSub is handled in onReply - // @ts-expect-error - onPush: undefined, - getTypeMapping: () => { - // PubSub push is an Array in RESP2 - return this.#pubSub.isActive ? - RESP2_PUSH_TYPE_MAPPING : - this.#getTypeMapping(); - } - }); - } - - async monitor(callback: MonitorCallback, typeMapping: TypeMapping = {}, asap = false) { - await this.addCommand( - ['MONITOR'], - { asap }, - true - ); - - const { onReply, getTypeMapping } = this.decoder; - this.decoder.onReply = callback; - this.decoder.getTypeMapping = () => typeMapping; - return () => new Promise(async resolve => { - await this.addCommand(['RESET'], undefined, true); - this.decoder.onReply = (reply: string) => { - if (reply !== 'RESET') return callback(reply); - this.decoder.onReply = onReply; - this.decoder.getTypeMapping = getTypeMapping; - resolve(); - }; - }); - } - addCommand( args: CommandArguments, - options?: CommandOptions, - resolveOnWrite?: boolean + options?: CommandOptions ): Promise { if (this.#maxLength && this.#toWrite.length + this.#waitingForReply.length >= this.#maxLength) { return Promise.reject(new Error('The queue is full')); @@ -192,7 +132,6 @@ export default class RedisCommandsQueue { args, chainId: options?.chainId, abort: undefined, - resolveOnWrite, resolve, reject, channelsCounter: undefined, @@ -215,15 +154,68 @@ export default class RedisCommandsQueue { }); } + #addPubSubCommand(command: PubSubCommand, asap = false) { + return new Promise((resolve, reject) => { + this.#toWrite.add({ + args: command.args, + chainId: undefined, + abort: undefined, + resolve() { + command.resolve(); + resolve(); + }, + reject(err) { + command.reject?.(); + reject(err); + }, + channelsCounter: command.channelsCounter, + typeMapping: PUSH_TYPE_MAPPING + }, asap); + }); + } + + #setupPubSubHandler(command: Exclude) { + // RESP3 uses `onPush` to handle PubSub, so no need to modify `onReply` + if (this.#respVersion !== 2) return; + + // overriding `resolve` instead of using `.then` to make sure it'll be called before processing the next reply + const { resolve } = command; + command.resolve = () => { + this.decoder.onReply = (reply => { + if (Array.isArray(reply)) { + if (this.#onPush(reply)) return; + + if (PONG.equals(reply[0] as Buffer)) { + const { resolve, typeMapping } = this.#waitingForReply.shift()!, + buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; + resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + return; + } + } + + return this.#onReply(reply); + }) as Decoder['onReply']; + this.decoder.getTypeMapping = () => RESP2_PUSH_TYPE_MAPPING; + resolve(); + }; + } + subscribe( type: PubSubType, channels: string | Array, listener: PubSubListener, returnBuffers?: T ) { - return this.#addPubSubCommand( - this.#pubSub.subscribe(type, channels, listener, returnBuffers) - ); + const command = this.#pubSub.subscribe(type, channels, listener, returnBuffers); + if (!command) return; + + this.#setupPubSubHandler(command); + return this.#addPubSubCommand(command); + } + + #resetDecoderCallbacks() { + this.decoder.onReply = (reply => this.#onReply(reply)) as Decoder['onReply']; + this.decoder.getTypeMapping = () => this.#getTypeMapping(); } unsubscribe( @@ -232,15 +224,30 @@ export default class RedisCommandsQueue { listener?: PubSubListener, returnBuffers?: T ) { - return this.#addPubSubCommand( - this.#pubSub.unsubscribe(type, channels, listener, returnBuffers) - ); + const command = this.#pubSub.unsubscribe(type, channels, listener, returnBuffers); + if (!command) return; + + if (command && this.#respVersion === 2) { + // RESP2 modifies `onReply` to handle PubSub (see #setupPubSubHandler) + const { resolve } = command; + command.resolve = () => { + if (!this.#pubSub.isActive) { + this.#resetDecoderCallbacks(); + } + + resolve(); + }; + } + + return this.#addPubSubCommand(command); } - resubscribe(): Promise | undefined { + resubscribe() { const commands = this.#pubSub.resubscribe(); if (!commands.length) return; + // using last command becasue of asap + this.#setupPubSubHandler(commands[commands.length - 1]); return Promise.all( commands.map(command => this.#addPubSubCommand(command, true)) ); @@ -251,44 +258,87 @@ export default class RedisCommandsQueue { channel: string, listeners: ChannelListeners ) { - return this.#addPubSubCommand( - this.#pubSub.extendChannelListeners(type, channel, listeners) - ); + const command = this.#pubSub.extendChannelListeners(type, channel, listeners); + if (!command) return; + + this.#setupPubSubHandler(command); + return this.#addPubSubCommand(command); } extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners) { - return this.#addPubSubCommand( - this.#pubSub.extendTypeListeners(type, listeners) - ); + const command = this.#pubSub.extendTypeListeners(type, listeners); + if (!command) return; + + this.#setupPubSubHandler(command); + return this.#addPubSubCommand(command); } getPubSubListeners(type: PubSubType) { return this.#pubSub.getTypeListeners(type); } - #addPubSubCommand(command: PubSubCommand, asap = false) { - if (command === undefined) return; - + monitor(callback: MonitorCallback, typeMapping: TypeMapping = {}, asap = false) { return new Promise((resolve, reject) => { this.#toWrite.add({ - args: command.args, + args: ['MONITOR'], chainId: undefined, abort: undefined, - resolveOnWrite: false, - resolve() { - command.resolve(); + // using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply + resolve: () => { + // after running `MONITOR` only `MONITOR` and `RESET` replies are expected + // any other command should cause an error + + // if `RESET` already overrides `onReply`, set monitor as it's fallback + if (this.#resetFallbackOnReply) { + this.#resetFallbackOnReply = callback; + } else { + this.decoder.onReply = callback; + } + + this.decoder.getTypeMapping = () => typeMapping; resolve(); }, - reject(err) { - command.reject?.(); - reject(err); - }, - channelsCounter: command.channelsCounter, - typeMapping: PUSH_TYPE_MAPPING + reject, + channelsCounter: undefined, + typeMapping }, asap); }); } + #resetFallbackOnReply?: Decoder['onReply']; + + async reset(typeMapping?: T) { + return new Promise((resolve, reject) => { + // overriding onReply to handle `RESET` while in `MONITOR` or PubSub mode + this.#resetFallbackOnReply = this.decoder.onReply; + this.decoder.onReply = (reply => { + if ( + (typeof reply === 'string' && reply === 'RESET') || + (reply instanceof Buffer && RESET.equals(reply)) + ) { + this.#resetDecoderCallbacks(); + this.#resetFallbackOnReply = undefined; + this.#pubSub.reset(); + + this.#waitingForReply.shift()!.resolve(reply); + return; + } + + this.#resetFallbackOnReply!(reply); + }) as Decoder['onReply']; + + this.#toWrite.push({ + args: ['RESET'], + chainId: undefined, + abort: undefined, + resolve, + reject, + channelsCounter: undefined, + typeMapping + }); + }); + } + isWaitingToWrite() { return this.#toWrite.length > 0; } @@ -305,22 +355,15 @@ export default class RedisCommandsQueue { continue; } + // TODO reuse `toSend` or create new object? + (toSend as any).args = undefined; if (toSend.abort) { RedisCommandsQueue.#removeAbortListener(toSend); toSend.abort = undefined; } - - if (toSend.resolveOnWrite) { - toSend.resolve(); - } else { - // TODO reuse `toSend` or create new object? - (toSend as any).args = undefined; - - this.#chainInExecution = toSend.chainId; - toSend.chainId = undefined; - - this.#waitingForReply.push(toSend); - } + this.#chainInExecution = toSend.chainId; + toSend.chainId = undefined; + this.#waitingForReply.push(toSend); yield encoded; toSend = this.#toWrite.shift(); diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index d8ac7487cc6..a893191c4e1 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -742,8 +742,10 @@ describe('Client', () => { }, GLOBAL.SERVERS.OPEN); testUtils.testWithClient('should be able to go back to "normal mode"', async client => { - const off = await client.monitor(() => {}); - await off(); + await Promise.all([ + client.monitor(() => {}), + client.reset() + ]); await assert.doesNotReject(client.ping()); }, GLOBAL.SERVERS.OPEN); diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 7d9cadde2eb..5ff842049b5 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -326,90 +326,101 @@ export default class RedisClient< #initiateQueue(): RedisCommandsQueue { return new RedisCommandsQueue( - this.#options?.RESP, + this.#options?.RESP ?? 2, this.#options?.commandsQueueMaxLength, (channel, listeners) => this.emit('sharded-channel-moved', channel, listeners) ); } - #initiateSocket(): RedisSocket { - const socketInitiator = async (): Promise => { - const promises = [this.#queue.resubscribe()]; + #handshake(asap = false, promises: Array> = []) { + if (this.#selectedDB !== 0) { + promises.push( + this.#queue.addCommand( + ['SELECT', this.#selectedDB.toString()], + { asap } + ) + ); + } - if (this.#monitorCallback) { - promises.push( - this.#queue.monitor( - this.#monitorCallback, - this._commandOptions?.typeMapping, - true - ) - ); + if (this.#options?.readonly) { + promises.push( + this.#queue.addCommand( + COMMANDS.READONLY.transformArguments(), + { asap } + ) + ); + } + + if (this.#options?.RESP) { + const hello: HelloOptions = {}; + + if (this.#options.password) { + hello.AUTH = { + username: this.#options.username ?? 'default', + password: this.#options.password + }; } - if (this.#selectedDB !== 0) { + if (this.#options.name) { + hello.SETNAME = this.#options.name; + } + + promises.push( + this.#queue.addCommand( + HELLO.transformArguments(this.#options.RESP, hello), + { asap } + ) + ); + } else { + if (this.#options?.name) { promises.push( this.#queue.addCommand( - ['SELECT', this.#selectedDB.toString()], - { asap: true } + COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), + { asap } ) ); } - if (this.#options?.readonly) { + if (this.#options?.username || this.#options?.password) { promises.push( this.#queue.addCommand( - COMMANDS.READONLY.transformArguments(), - { asap: true } + COMMANDS.AUTH.transformArguments({ + username: this.#options.username, + password: this.#options.password ?? '' + }), + { asap } ) ); } + } - if (this.#options?.RESP) { - const hello: HelloOptions = {}; + return promises; + } - if (this.#options.password) { - hello.AUTH = { - username: this.#options.username ?? 'default', - password: this.#options.password - }; - } + #initiateSocket(): RedisSocket { + const socketInitiator = () => { + const promises: Array> = []; - if (this.#options.name) { - hello.SETNAME = this.#options.name; - } + const resubscribePromise = this.#queue.resubscribe(); + if (resubscribePromise) { + promises.push(resubscribePromise); + } + if (this.#monitorCallback) { promises.push( - this.#queue.addCommand( - HELLO.transformArguments(this.#options.RESP, hello), - { asap: true } + this.#queue.monitor( + this.#monitorCallback, + this._commandOptions?.typeMapping, + true ) ); - } else { - if (this.#options?.name) { - promises.push( - this.#queue.addCommand( - COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), - { asap: true } - ) - ); - } - - if (this.#options?.username || this.#options?.password) { - promises.push( - this.#queue.addCommand( - COMMANDS.AUTH.transformArguments({ - username: this.#options.username, - password: this.#options.password ?? '' - }), - { asap: true } - ) - ); - } } + this.#handshake(true, promises); + if (promises.length) { this.#write(); - await Promise.all(promises); + return Promise.all(promises); } }; @@ -876,19 +887,48 @@ export default class RedisClient< async MONITOR(callback: MonitorCallback) { const promise = this._self.#queue.monitor(callback, this._commandOptions?.typeMapping); this._self.#scheduleWrite(); - - const off = await promise; + await promise; this._self.#monitorCallback = callback; - return async () => { - const promise = off(); - this._self.#scheduleWrite(); - await promise; - this._self.#monitorCallback = undefined; - }; } monitor = this.MONITOR; + /** + * Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.) + */ + async reset() { + const promises = [this._self.#queue.reset()]; + this._self.#handshake(false, promises); + await Promise.all(promises); + } + + /** + * If the client has state, reset it. + * An internal function to be used by wrapper class such as `RedisClientPool`. + * @internal + */ + resetIfDirty() { + let shouldReset = false; + if (this._self.#selectedDB !== this._self.#options?.database ?? 0) { + console.warn('Returning a client with a different selected DB'); + shouldReset = true; + } + + if (this._self.#monitorCallback) { + console.warn('Returning a client with active MONITOR'); + shouldReset = true; + } + + if (this._self.#queue.isPubSubActive) { + console.warn('Returning a client with active PubSub'); + shouldReset = true; + } + + if (shouldReset) { + return this.reset(); + } + } + /** * @deprecated use .close instead */ diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index 12d8f5fee5c..fc996e07625 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -375,6 +375,7 @@ export class RedisClientPool< #returnClient(node: DoublyLinkedNode>) { const task = this.#tasksQueue.shift(); if (task) { + clearTimeout(task.timeout); this.#executeTask(node, task.resolve, task.reject, task.fn); return; } diff --git a/packages/client/lib/client/pub-sub.ts b/packages/client/lib/client/pub-sub.ts index 7c29099d71b..aedbaf68d65 100644 --- a/packages/client/lib/client/pub-sub.ts +++ b/packages/client/lib/client/pub-sub.ts @@ -1,4 +1,5 @@ import { RedisArgument } from '../RESP/types'; +import { CommandToWrite } from './commands-queue'; export enum PubSubType { CHANNELS = 'CHANNELS', @@ -26,7 +27,7 @@ const COMMANDS = { export type PubSubListener< RETURN_BUFFERS extends boolean = false -> = (message: T, channel: T) => unknown; +> = (message: T, channel: T) => unknown; export interface ChannelListeners { unsubscribing: boolean; @@ -38,11 +39,11 @@ export type PubSubTypeListeners = Map; type Listeners = Record; -export type PubSubCommand = ReturnType< - typeof PubSub.prototype.subscribe | - typeof PubSub.prototype.unsubscribe | - typeof PubSub.prototype.extendTypeListeners ->; +export type PubSubCommand = ( + Required> & { + reject: undefined | (() => unknown); + } +); export class PubSub { static isStatusReply(reply: Array): boolean { @@ -135,7 +136,7 @@ export class PubSub { this.#subscribing--; this.#updateIsActive(); } - }; + } satisfies PubSubCommand; } extendChannelListeners( @@ -158,7 +159,7 @@ export class PubSub { this.#subscribing--; this.#updateIsActive(); } - }; + } satisfies PubSubCommand; } #extendChannelListeners( @@ -203,7 +204,7 @@ export class PubSub { this.#subscribing--; this.#updateIsActive(); } - }; + } satisfies PubSubCommand; } unsubscribe( @@ -299,8 +300,8 @@ export class PubSub { removeListeners(); this.#updateIsActive(); }, - reject: undefined // use the same structure as `subscribe` - }; + reject: undefined + } satisfies PubSubCommand; } #updateIsActive() { @@ -317,7 +318,7 @@ export class PubSub { this.#subscribing = 0; } - resubscribe(): Array { + resubscribe() { const commands = []; for (const [type, listeners] of Object.entries(this.#listeners)) { if (!listeners.size) continue; @@ -333,7 +334,7 @@ export class PubSub { channelsCounter: listeners.size, resolve: callback, reject: callback - }); + } satisfies PubSubCommand); } return commands; diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 129ace90397..753ced6c5ed 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -43,7 +43,7 @@ interface CreateSocketReturn { socket: T; } -export type RedisSocketInitiator = () => Promise; +export type RedisSocketInitiator = () => void | Promise; export default class RedisSocket extends EventEmitter { static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { From f7f51b9c92408e026733afe0e029342122b874f7 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jan 2024 08:02:54 -0500 Subject: [PATCH 302/325] fix pubsub handler --- packages/client/lib/client/commands-queue.ts | 44 +++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 03851b4bee9..11ee791a79b 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -174,30 +174,25 @@ export default class RedisCommandsQueue { }); } - #setupPubSubHandler(command: Exclude) { + #setupPubSubHandler() { // RESP3 uses `onPush` to handle PubSub, so no need to modify `onReply` if (this.#respVersion !== 2) return; - // overriding `resolve` instead of using `.then` to make sure it'll be called before processing the next reply - const { resolve } = command; - command.resolve = () => { - this.decoder.onReply = (reply => { - if (Array.isArray(reply)) { - if (this.#onPush(reply)) return; - - if (PONG.equals(reply[0] as Buffer)) { - const { resolve, typeMapping } = this.#waitingForReply.shift()!, - buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); - return; - } + this.decoder.onReply = (reply => { + if (Array.isArray(reply)) { + if (this.#onPush(reply)) return; + + if (PONG.equals(reply[0] as Buffer)) { + const { resolve, typeMapping } = this.#waitingForReply.shift()!, + buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; + resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + return; } - - return this.#onReply(reply); - }) as Decoder['onReply']; - this.decoder.getTypeMapping = () => RESP2_PUSH_TYPE_MAPPING; - resolve(); - }; + } + + return this.#onReply(reply); + }) as Decoder['onReply']; + this.decoder.getTypeMapping = () => RESP2_PUSH_TYPE_MAPPING; } subscribe( @@ -209,7 +204,7 @@ export default class RedisCommandsQueue { const command = this.#pubSub.subscribe(type, channels, listener, returnBuffers); if (!command) return; - this.#setupPubSubHandler(command); + this.#setupPubSubHandler(); return this.#addPubSubCommand(command); } @@ -246,8 +241,7 @@ export default class RedisCommandsQueue { const commands = this.#pubSub.resubscribe(); if (!commands.length) return; - // using last command becasue of asap - this.#setupPubSubHandler(commands[commands.length - 1]); + this.#setupPubSubHandler(); return Promise.all( commands.map(command => this.#addPubSubCommand(command, true)) ); @@ -261,7 +255,7 @@ export default class RedisCommandsQueue { const command = this.#pubSub.extendChannelListeners(type, channel, listeners); if (!command) return; - this.#setupPubSubHandler(command); + this.#setupPubSubHandler(); return this.#addPubSubCommand(command); } @@ -269,7 +263,7 @@ export default class RedisCommandsQueue { const command = this.#pubSub.extendTypeListeners(type, listeners); if (!command) return; - this.#setupPubSubHandler(command); + this.#setupPubSubHandler(); return this.#addPubSubCommand(command); } From 1006e3b29f14753886391be99cec50823804c630 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jan 2024 08:29:55 -0500 Subject: [PATCH 303/325] fix dirty selected DB check --- packages/client/lib/client/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 5ff842049b5..8ec2477cd10 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -909,7 +909,7 @@ export default class RedisClient< */ resetIfDirty() { let shouldReset = false; - if (this._self.#selectedDB !== this._self.#options?.database ?? 0) { + if (this._self.#selectedDB !== (this._self.#options?.database ?? 0)) { console.warn('Returning a client with a different selected DB'); shouldReset = true; } From baef3486ad0e15d0364bc92cab94fbfa825efe85 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 31 Jan 2024 13:23:26 -0500 Subject: [PATCH 304/325] fix client.reset --- packages/client/lib/client/commands-queue.ts | 9 +++++++-- packages/client/lib/client/index.ts | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 11ee791a79b..0c81deb7849 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -299,6 +299,11 @@ export default class RedisCommandsQueue { }); } + resetDecoder() { + this.#resetDecoderCallbacks(); + this.decoder.reset(); + } + #resetFallbackOnReply?: Decoder['onReply']; async reset(typeMapping?: T) { @@ -384,7 +389,7 @@ export default class RedisCommandsQueue { } flushWaitingForReply(err: Error): void { - this.decoder.reset(); + this.resetDecoder(); this.#pubSub.reset(); this.#flushWaitingForReply(err); @@ -402,7 +407,7 @@ export default class RedisCommandsQueue { } flushAll(err: Error): void { - this.decoder.reset(); + this.resetDecoder(); this.#pubSub.reset(); this.#flushWaitingForReply(err); for (const node of this.#toWrite) { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 8ec2477cd10..29516ee5496 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -429,7 +429,7 @@ export default class RedisClient< try { this.#queue.decoder.write(chunk); } catch (err) { - this.#queue.decoder.reset(); + this.#queue.resetDecoder(); this.emit('error', err); } }) @@ -899,6 +899,7 @@ export default class RedisClient< async reset() { const promises = [this._self.#queue.reset()]; this._self.#handshake(false, promises); + this._self.#scheduleWrite(); await Promise.all(promises); } From 0cd69156985a24e1bc1dcaf7245d8cfa7c6dbf9d Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 31 Jan 2024 15:07:01 -0500 Subject: [PATCH 305/325] fix client.reset --- packages/client/lib/client/commands-queue.ts | 21 ++-- packages/client/lib/client/index.spec.ts | 3 + packages/client/lib/client/index.ts | 103 ++++++++++--------- 3 files changed, 70 insertions(+), 57 deletions(-) diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 0c81deb7849..034c1e46bd8 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -1,7 +1,7 @@ import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list'; import encodeCommand from '../RESP/encoder'; import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder'; -import { CommandArguments, TypeMapping, ReplyUnion, RespVersions, SimpleStringReply, ReplyWithTypeMapping } from '../RESP/types'; +import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP/types'; import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub'; import { AbortError, ErrorReply } from '../errors'; import { MonitorCallback } from '.'; @@ -154,11 +154,11 @@ export default class RedisCommandsQueue { }); } - #addPubSubCommand(command: PubSubCommand, asap = false) { + #addPubSubCommand(command: PubSubCommand, asap = false, chainId?: symbol) { return new Promise((resolve, reject) => { this.#toWrite.add({ args: command.args, - chainId: undefined, + chainId, abort: undefined, resolve() { command.resolve(); @@ -237,13 +237,13 @@ export default class RedisCommandsQueue { return this.#addPubSubCommand(command); } - resubscribe() { + resubscribe(chainId?: symbol) { const commands = this.#pubSub.resubscribe(); if (!commands.length) return; this.#setupPubSubHandler(); return Promise.all( - commands.map(command => this.#addPubSubCommand(command, true)) + commands.map(command => this.#addPubSubCommand(command, true, chainId)) ); } @@ -271,11 +271,12 @@ export default class RedisCommandsQueue { return this.#pubSub.getTypeListeners(type); } - monitor(callback: MonitorCallback, typeMapping: TypeMapping = {}, asap = false) { + monitor(callback: MonitorCallback, options?: CommandOptions) { return new Promise((resolve, reject) => { + const typeMapping = options?.typeMapping ?? {}; this.#toWrite.add({ args: ['MONITOR'], - chainId: undefined, + chainId: options?.chainId, abort: undefined, // using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply resolve: () => { @@ -295,7 +296,7 @@ export default class RedisCommandsQueue { reject, channelsCounter: undefined, typeMapping - }, asap); + }, options?.asap); }); } @@ -306,7 +307,7 @@ export default class RedisCommandsQueue { #resetFallbackOnReply?: Decoder['onReply']; - async reset(typeMapping?: T) { + async reset(chainId: symbol, typeMapping?: T) { return new Promise((resolve, reject) => { // overriding onReply to handle `RESET` while in `MONITOR` or PubSub mode this.#resetFallbackOnReply = this.decoder.onReply; @@ -328,7 +329,7 @@ export default class RedisCommandsQueue { this.#toWrite.push({ args: ['RESET'], - chainId: undefined, + chainId, abort: undefined, resolve, reject, diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index a893191c4e1..2fd689b9d7b 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -732,6 +732,9 @@ describe('Client', () => { skipMe: true }) ]); + + await once(duplicate, 'ready'); + await Promise.all([ waitTillBeenCalled(listener), client.ping() diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 29516ee5496..d6b9e3714d4 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -332,24 +332,8 @@ export default class RedisClient< ); } - #handshake(asap = false, promises: Array> = []) { - if (this.#selectedDB !== 0) { - promises.push( - this.#queue.addCommand( - ['SELECT', this.#selectedDB.toString()], - { asap } - ) - ); - } - - if (this.#options?.readonly) { - promises.push( - this.#queue.addCommand( - COMMANDS.READONLY.transformArguments(), - { asap } - ) - ); - } + #handshake(selectedDB: number) { + const commands = []; if (this.#options?.RESP) { const hello: HelloOptions = {}; @@ -365,43 +349,45 @@ export default class RedisClient< hello.SETNAME = this.#options.name; } - promises.push( - this.#queue.addCommand( - HELLO.transformArguments(this.#options.RESP, hello), - { asap } - ) + commands.push( + HELLO.transformArguments(this.#options.RESP, hello) ); } else { - if (this.#options?.name) { - promises.push( - this.#queue.addCommand( - COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name), - { asap } - ) + if (this.#options?.username || this.#options?.password) { + commands.push( + COMMANDS.AUTH.transformArguments({ + username: this.#options.username, + password: this.#options.password ?? '' + }) ); } - if (this.#options?.username || this.#options?.password) { - promises.push( - this.#queue.addCommand( - COMMANDS.AUTH.transformArguments({ - username: this.#options.username, - password: this.#options.password ?? '' - }), - { asap } - ) + if (this.#options?.name) { + commands.push( + COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name) ); } } - return promises; + if (selectedDB !== 0) { + commands.push(['SELECT', this.#selectedDB.toString()]); + } + + if (this.#options?.readonly) { + commands.push( + COMMANDS.READONLY.transformArguments() + ); + } + + return commands; } #initiateSocket(): RedisSocket { const socketInitiator = () => { - const promises: Array> = []; + const promises = [], + chainId = Symbol('Socket Initiator'); - const resubscribePromise = this.#queue.resubscribe(); + const resubscribePromise = this.#queue.resubscribe(chainId); if (resubscribePromise) { promises.push(resubscribePromise); } @@ -410,13 +396,24 @@ export default class RedisClient< promises.push( this.#queue.monitor( this.#monitorCallback, - this._commandOptions?.typeMapping, - true + { + typeMapping: this._commandOptions?.typeMapping, + chainId, + asap: true + } ) ); } - this.#handshake(true, promises); + const commands = this.#handshake(this.#selectedDB); + for (let i = commands.length - 1; i >= 0; --i) { + promises.push( + this.#queue.addCommand(commands[i], { + chainId, + asap: true + }) + ); + } if (promises.length) { this.#write(); @@ -885,7 +882,9 @@ export default class RedisClient< } async MONITOR(callback: MonitorCallback) { - const promise = this._self.#queue.monitor(callback, this._commandOptions?.typeMapping); + const promise = this._self.#queue.monitor(callback, { + typeMapping: this._commandOptions?.typeMapping + }); this._self.#scheduleWrite(); await promise; this._self.#monitorCallback = callback; @@ -897,10 +896,20 @@ export default class RedisClient< * Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.) */ async reset() { - const promises = [this._self.#queue.reset()]; - this._self.#handshake(false, promises); + const chainId = Symbol('Reset Chain'), + promises = [this._self.#queue.reset(chainId)], + selectedDB = this._self.#options?.database ?? 0; + for (const command of this._self.#handshake(selectedDB)) { + promises.push( + this._self.#queue.addCommand(command, { + chainId + }) + ); + } this._self.#scheduleWrite(); await Promise.all(promises); + this._self.#selectedDB = selectedDB; + this._self.#monitorCallback = undefined; } /** From 8f3a2765099b2508a3e3e550bb8424ea8128cfee Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Mon, 5 Feb 2024 16:48:33 +0200 Subject: [PATCH 306/325] Sentinel Support (#2664) * redis client socket changes needed for sentinel * Sentinel Implementation [EXPERIMENTAL] * add pooling * improve typing with SENTINEL_ client members * cleanup - remove unused comments / commented code * small sendCommand change + revert change to tsconfig * add more sentinel commands needed for testing. * lots of fixups and a reasonable first pass test suite * add a timer option to update topology in background + don't need both sentinel client and pubsubclient + nits * format all the things * more progress * small cleanup * try to group promises together to minimize the internal await points * redo events, to keep a single topology event to listen on * nits + readme * add RedisSentinelFactory to provide lower level access to sentinel * nit * update * add RedisSentinelClient/Type for leased clients returned by aquire() used by function passed to use() * add self for private access + improve emitting * nit * nits * improve testing - improve steady state waiting between tests - get masternode from client, not from sentinels themselves (not consistent and then client isn't changing as we expect - provide extensive logging/tracing on test errors - provide a very low impact tracing mechanism withinthe code that only really impacts code when tracing is in use. * ismall nit for typing * bunch of changes - harden testing - don't use sentinel[0] for debug error dump as could be downed by a test - increase time for sentinel down test to 30s (caused a long taking failover) - add client-error even / don't pass throuh client errors as errors option for pubsub proxy - when passing through cient errors as error events, dont pass the event, but the Error object, as only Error objects are supposed to be on 'error' - * improve pub sub proxy. save the refference to all channel/pattern listeners up front on creation, dont hve to fetch the object each time, as it doesn't change. removes race condition between setting up the listener and the pub sub node going down and being recreated. * wrap the passed through RedisClient error to make clear where its coming from. * refactor sentinel object / factory tests apart * harden tests a little bit more * add pipeline test * add scripts/function tests + fixups / cleanups to get them to work * change to use redis-stack-server for redis nodes to enable module testing * fix test, forgot to return in use function with module * rename test * improve tests to test with redis/sentinel nodes with and withput passwords this tests that we are handling the nodeClientOptions and sentinelClientOptions correctly * cleanup for RedisSentinel type generic typing in tests * remove debugLog, just rely on traace mechanism * added multi tests for script/function/modules * don't emit errors on lease object, only on main object * improve testing * extract out common code to reduce duplication * nit * nits * nit * remove SENTINEL_... commands from main client, load them via module interface * missed adding RedisSentinelModule to correct places in RedisSentinelFactory * nits * fix test logging on error 1) it takes a lot of time now, so needs larger timeout 2) docker logs can be large, so need to increase maxBuffer size so doesn't error (and break test clean up) * invalidate watches when client reconnects + provide API for other wrapper clients to also create invalid watch states programatically. Reasoning: if a user does a WATCH and then the client reconnects, the watch is no longer active, but if a user does a MULTI/EXEC after that, they wont know, and since the WATCH is no longer active, the request has no protection. The API is needed for when a wrapper client (say sentinel, cluster) might close the underlying client and reopen a new one transparently to the user. Just like in the reconnection case, this should result in an error, but its up to the wrapping client to provide the appropriate error * remove WATCH and UNWATCH command files, fix WATCH and UNWATCH return type, some more cleanups * missing file in last commit :P * support for custom message in `WatchError` * setDirtyWatch * update watch docs * fixes needed * wip * get functions/modules to work again self -> _self change * reuse leased client on pipelined commands. though I realize this implementation, really only works after the first write command. unsure this is worth it. * test tweaks * nit * change how "sentinel" object client works, allow it to be reserved no more semaphore type counting * review * fixes to get more tests to pass * handle dirtyWatch and watchEpoch in reset and resetIfDirty * "fix", but not correct, needs more work * fix pubsub proxy * remove timeout from steadyState function in test, caused problems * improve restarting nodes * fix pubsub proxy and test --------- Co-authored-by: Leibale Eidelman --- docs/clustering.md | 1 + docs/sentinel.md | 100 + docs/transactions.md | 2 +- package-lock.json | 3489 +++++++++++------ packages/client/index.ts | 5 + packages/client/lib/client/commands-queue.ts | 2 +- packages/client/lib/client/index.ts | 70 +- packages/client/lib/client/pub-sub.spec.ts | 266 +- packages/client/lib/client/pub-sub.ts | 86 +- packages/client/lib/client/socket.ts | 8 +- packages/client/lib/cluster/cluster-slots.ts | 18 +- packages/client/lib/commands/UNWATCH.spec.ts | 19 - packages/client/lib/commands/UNWATCH.ts | 10 - packages/client/lib/commands/WATCH.spec.ts | 20 - packages/client/lib/commands/WATCH.ts | 11 - packages/client/lib/commands/index.ts | 6 - packages/client/lib/errors.ts | 4 +- .../lib/sentinel/commands/SENTINEL_MASTER.ts | 12 + .../lib/sentinel/commands/SENTINEL_MONITOR.ts | 8 + .../sentinel/commands/SENTINEL_REPLICAS.ts | 15 + .../sentinel/commands/SENTINEL_SENTINELS.ts | 15 + .../lib/sentinel/commands/SENTINEL_SET.ts | 19 + .../client/lib/sentinel/commands/index.ts | 19 + packages/client/lib/sentinel/index.spec.ts | 1274 ++++++ packages/client/lib/sentinel/index.ts | 1492 +++++++ packages/client/lib/sentinel/module.ts | 6 + .../client/lib/sentinel/multi-commands.ts | 215 + packages/client/lib/sentinel/pub-sub-proxy.ts | 213 + packages/client/lib/sentinel/test-util.ts | 605 +++ packages/client/lib/sentinel/types.ts | 174 + packages/client/lib/sentinel/utils.ts | 103 + packages/client/lib/sentinel/wait-queue.ts | 24 + packages/gears/lib/commands/TFUNCTION_LIST.ts | 51 + packages/redis/README.md | 1 + 34 files changed, 6806 insertions(+), 1557 deletions(-) create mode 100644 docs/sentinel.md delete mode 100644 packages/client/lib/commands/UNWATCH.spec.ts delete mode 100644 packages/client/lib/commands/UNWATCH.ts delete mode 100644 packages/client/lib/commands/WATCH.spec.ts delete mode 100644 packages/client/lib/commands/WATCH.ts create mode 100644 packages/client/lib/sentinel/commands/SENTINEL_MASTER.ts create mode 100644 packages/client/lib/sentinel/commands/SENTINEL_MONITOR.ts create mode 100644 packages/client/lib/sentinel/commands/SENTINEL_REPLICAS.ts create mode 100644 packages/client/lib/sentinel/commands/SENTINEL_SENTINELS.ts create mode 100644 packages/client/lib/sentinel/commands/SENTINEL_SET.ts create mode 100644 packages/client/lib/sentinel/commands/index.ts create mode 100644 packages/client/lib/sentinel/index.spec.ts create mode 100644 packages/client/lib/sentinel/index.ts create mode 100644 packages/client/lib/sentinel/module.ts create mode 100644 packages/client/lib/sentinel/multi-commands.ts create mode 100644 packages/client/lib/sentinel/pub-sub-proxy.ts create mode 100644 packages/client/lib/sentinel/test-util.ts create mode 100644 packages/client/lib/sentinel/types.ts create mode 100644 packages/client/lib/sentinel/utils.ts create mode 100644 packages/client/lib/sentinel/wait-queue.ts create mode 100644 packages/gears/lib/commands/TFUNCTION_LIST.ts diff --git a/docs/clustering.md b/docs/clustering.md index 43cea373a02..f335c259c24 100644 --- a/docs/clustering.md +++ b/docs/clustering.md @@ -37,6 +37,7 @@ await cluster.close(); | modules | | Included [Redis Modules](../README.md#packages) | | scripts | | Script definitions (see [Lua Scripts](../README.md#lua-scripts)) | | functions | | Function definitions (see [Functions](../README.md#functions)) | + ## Auth with password and username Specifying the password in the URL or a root node will only affect the connection to that specific node. In case you want to set the password for all the connections being created from a cluster instance, use the `defaults` option. diff --git a/docs/sentinel.md b/docs/sentinel.md new file mode 100644 index 00000000000..80e79c3f88c --- /dev/null +++ b/docs/sentinel.md @@ -0,0 +1,100 @@ +# Redis Sentinel + +The [Redis Sentinel](https://redis.io/docs/management/sentinel/) object of node-redis provides a high level object that provides access to a high availability redis installation managed by Redis Sentinel to provide enumeration of master and replica nodes belonging to an installation as well as reconfigure itself on demand for failover and topology changes. + +## Basic Example + +```javascript +import { createSentinel } from 'redis'; + +const sentinel = await createSentinel({ + name: 'sentinel-db', + sentinelRootNodes: [{ + host: 'example', + port: 1234 + }] + }) + .on('error', err => console.error('Redis Sentinel Error', err)); + .connect(); + +await sentinel.set('key', 'value'); +const value = await sentinel.get('key'); +await sentinel.close(); +``` + +In the above example, we configure the sentinel object to fetch the configuration for the database Redis Sentinel is monitoring as "sentinel-db" with one of the sentinels being located at `example:1234`, then using it like a regular Redis client. + +## `createSentinel` configuration + +| Property | Default | Description | +|-----------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| name | | The sentinel identifier for a particular database cluster | +| sentinelRootNodes | | An array of root nodes that are part of the sentinel cluster, which will be used to get the 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 sentinel configuration from the server | +| maxCommandRediscovers | `16` | The maximum number of times a command will retry due to topology changes. | +| nodeClientOptions | | The configuration values for every node in the cluster. Use this for example when specifying an ACL user to connect with | +| sentinelClientOptions | | The configuration values for every sentinel in the cluster. Use this for example when specifying an ACL user to connect with | +| masterPoolSize | `1` | The number of clients connected to the master node | +| replicaPoolSize | `0` | The number of clients connected to each replica node. When greater than 0, the client will distribute the load by executing read-only commands (such as `GET`, `GEOSEARCH`, etc.) across all the cluster nodes. | +| reserveClient | `false` | When `true`, one client will be reserved for the sentinel object. When `false`, the sentinel object will wait for the first available client from the pool. | +## PubSub + +It supports PubSub via the normal mechanisms, including migrating the listeners if the node they are connected to goes down. + +```javascript +await sentinel.subscribe('channel', message => { + // ... +}); +await sentinel.unsubscribe('channel'); +``` + +see [the PubSub guide](./pub-sub.md) for more details. + +## Sentinel as a pool + +The sentinel object provides the ability to manage a pool of clients for the master node: + +```javascript +createSentinel({ + // ... + masterPoolSize: 10 +}); +``` + +In addition, it also provides the ability have a pool of clients connected to the replica nodes, and to direct all read-only commands to them: + +```javascript +createSentinel({ + // ... + replicaPoolSize: 10 +}); +``` + +## Master client lease + +Sometimes multiple commands needs to run on an exclusive client (for example, using `WATCH/MULTI/EXEC`). + +There are 2 ways to get a client lease: + +`.use()` +```javascript +const result = await sentinel.use(async client => { + await client.watch('key'); + return client.multi() + .get('key') + .exec(); +}); +``` + +`.getMasterClientLease()` +```javascript +const clientLease = await sentinel.getMasterClientLease(); + +try { + await clientLease.watch('key'); + const resp = await clientLease.multi() + .get('key') + .exec(); +} finally { + clientLease.release(); +} +``` diff --git a/docs/transactions.md b/docs/transactions.md index 542061ebbc0..6331fef4be5 100644 --- a/docs/transactions.md +++ b/docs/transactions.md @@ -24,7 +24,7 @@ await multi.execTyped(); // [string] ## [`WATCH`](https://redis.io/commands/watch/) -You can also [watch](https://redis.io/docs/interact/transactions/#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. +You can also [watch](https://redis.io/docs/interact/transactions/#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change or if the client reconnected between the `watch` and `exec` calls. The `WATCH` state is stored on the connection (by the server). In case you need to run multiple `WATCH` & `MULTI` in parallel you'll need to use a [pool](./pool.md). diff --git a/package-lock.json b/package-lock.json index a5b9f626b4d..aff547130b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,8 +25,9 @@ }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -34,8 +35,9 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -46,8 +48,9 @@ }, "node_modules/@babel/code-frame": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -58,8 +61,9 @@ }, "node_modules/@babel/code-frame/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -69,8 +73,9 @@ }, "node_modules/@babel/code-frame/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -82,37 +87,42 @@ }, "node_modules/@babel/code-frame/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/code-frame/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/code-frame/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/code-frame/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -122,27 +132,29 @@ }, "node_modules/@babel/compat-data": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.5", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dev": true, - "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.5", - "@babel/parser": "^7.23.5", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -159,23 +171,26 @@ }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.23.5", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.23.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -185,13 +200,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -201,24 +217,27 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/template": "^7.22.15", "@babel/types": "^7.23.0" @@ -229,8 +248,9 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -240,8 +260,9 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.15" }, @@ -251,8 +272,9 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-module-imports": "^7.22.15", @@ -269,8 +291,9 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -280,8 +303,9 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -291,36 +315,40 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.5", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" @@ -328,8 +356,9 @@ }, "node_modules/@babel/highlight": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -341,8 +370,9 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -352,8 +382,9 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -365,37 +396,42 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -404,9 +440,10 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -415,32 +452,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.5", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -449,16 +488,18 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.23.5", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -468,13 +509,270 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -483,10 +781,107 @@ "node": ">=12" } }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -499,16 +894,18 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "ajv": "^6.12.4", @@ -528,33 +925,84 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.55.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "peer": true, "engines": { "node": ">=12.22" @@ -565,20 +1013,23 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true, - "license": "BSD-3-Clause", "peer": true }, "node_modules/@iarna/toml": { "version": "2.2.5", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -592,16 +1043,18 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -612,8 +1065,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/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, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -624,8 +1078,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -635,8 +1090,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -649,8 +1105,9 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -660,16 +1117,18 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", + "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2" }, @@ -682,16 +1141,18 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -703,40 +1164,45 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@ljharb/through": { - "version": "2.3.11", + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", + "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.5" }, "engines": { "node": ">= 0.4" @@ -744,8 +1210,9 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -756,16 +1223,18 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -776,16 +1245,18 @@ }, "node_modules/@octokit/auth-token": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "5.0.2", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz", + "integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.0.0", @@ -801,8 +1272,9 @@ }, "node_modules/@octokit/endpoint": { "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", + "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^12.0.0", "universal-user-agent": "^6.0.0" @@ -813,8 +1285,9 @@ }, "node_modules/@octokit/graphql": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", + "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/request": "^8.0.1", "@octokit/types": "^12.0.0", @@ -826,13 +1299,15 @@ }, "node_modules/@octokit/openapi-types": { "version": "19.1.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.1.0.tgz", + "integrity": "sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw==", + "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { "version": "9.1.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.5.tgz", + "integrity": "sha512-WKTQXxK+bu49qzwv4qKbMMRXej1DU2gq017euWyKVudA6MldaSSQuxtz+vGbhxV4CjxpUxjZu6rM2wfc1FiWVg==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^12.4.0" }, @@ -845,8 +1320,9 @@ }, "node_modules/@octokit/plugin-request-log": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", + "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 18" }, @@ -856,8 +1332,9 @@ }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.2.0.tgz", + "integrity": "sha512-ePbgBMYtGoRNXDyKGvr9cyHjQ163PbwD0y1MkDJCpkO2YH4OeXX40c4wYHKikHGZcpGPbcRLuy0unPUuafco8Q==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^12.3.0" }, @@ -870,8 +1347,9 @@ }, "node_modules/@octokit/request": { "version": "8.1.6", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz", + "integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/endpoint": "^9.0.0", "@octokit/request-error": "^5.0.0", @@ -884,8 +1362,9 @@ }, "node_modules/@octokit/request-error": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", + "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^12.0.0", "deprecation": "^2.0.0", @@ -897,8 +1376,9 @@ }, "node_modules/@octokit/rest": { "version": "20.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", + "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/core": "^5.0.0", "@octokit/plugin-paginate-rest": "^9.0.0", @@ -911,24 +1391,27 @@ }, "node_modules/@octokit/types": { "version": "12.4.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz", + "integrity": "sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/openapi-types": "^19.1.0" } }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", "dev": true, - "license": "MIT", "engines": { "node": ">=12.22.0" } }, "node_modules/@pnpm/network.ca-file": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" }, @@ -938,13 +1421,15 @@ }, "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { "version": "4.2.10", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true }, "node_modules/@pnpm/npm-conf": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", "dev": true, - "license": "MIT", "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", @@ -984,8 +1469,9 @@ }, "node_modules/@sindresorhus/is": { "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -995,8 +1481,9 @@ }, "node_modules/@sindresorhus/merge-streams": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", + "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -1005,25 +1492,28 @@ } }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "lodash.get": "^4.4.2", @@ -1032,21 +1522,24 @@ }, "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dev": true, - "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -1056,73 +1549,84 @@ }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.15", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "node_modules/@types/mocha": { "version": "10.0.6", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true }, "node_modules/@types/node": { - "version": "20.10.3", + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { "version": "7.5.6", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true }, "node_modules/@types/sinon": { - "version": "17.0.2", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", "dev": true, - "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true }, "node_modules/@types/yargs": { "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, - "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", + "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/type-utils": "6.19.1", + "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1148,14 +1652,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", + "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4" }, "engines": { @@ -1175,12 +1680,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1191,12 +1697,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", + "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/utils": "6.19.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1217,9 +1724,10 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, - "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -1229,15 +1737,17 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -1255,16 +1765,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" }, "engines": { @@ -1279,11 +1790,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1296,14 +1808,16 @@ }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true, - "license": "ISC", "peer": true }, "node_modules/acorn": { - "version": "8.11.2", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "license": "MIT", "peer": true, "bin": { "acorn": "bin/acorn" @@ -1314,8 +1828,9 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -1323,8 +1838,9 @@ }, "node_modules/agent-base": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -1334,8 +1850,9 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, - "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1346,8 +1863,9 @@ }, "node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -1362,24 +1880,27 @@ }, "node_modules/ansi-align": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.1.0" } }, "node_modules/ansi-colors": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "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==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -1392,8 +1913,9 @@ }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -1403,21 +1925,24 @@ }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-sequence-parser": { "version": "1.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1430,8 +1955,9 @@ }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1442,8 +1968,9 @@ }, "node_modules/append-transform": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, - "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" }, @@ -1453,18 +1980,21 @@ }, "node_modules/archy": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true }, "node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-buffer-byte-length": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "is-array-buffer": "^3.0.1" @@ -1475,24 +2005,27 @@ }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/array-uniq": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/array.prototype.map": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.6.tgz", + "integrity": "sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -1509,8 +2042,9 @@ }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", @@ -1529,8 +2063,9 @@ }, "node_modules/ast-types": { "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, - "license": "MIT", "dependencies": { "tslib": "^2.0.1" }, @@ -1540,21 +2075,24 @@ }, "node_modules/async": { "version": "3.2.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true }, "node_modules/async-retry": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "dev": true, - "license": "MIT", "dependencies": { "retry": "0.13.1" } }, "node_modules/available-typed-arrays": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1564,11 +2102,14 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -1583,52 +2124,48 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/basic-ftp": { - "version": "5.0.3", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.4.tgz", + "integrity": "sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/before-after-hook": { "version": "2.2.3", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "dev": true, - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true }, "node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/bl": { - "version": "5.1.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, - "license": "MIT", "dependencies": { - "buffer": "^6.0.3", + "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "node_modules/boxen": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", "dev": true, - "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^7.0.1", @@ -1648,8 +2185,9 @@ }, "node_modules/boxen/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -1659,8 +2197,9 @@ }, "node_modules/boxen/node_modules/ansi-styles": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -1670,8 +2209,9 @@ }, "node_modules/boxen/node_modules/camelcase": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -1681,8 +2221,9 @@ }, "node_modules/boxen/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1692,13 +2233,15 @@ }, "node_modules/boxen/node_modules/emoji-regex": { "version": "9.2.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/boxen/node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, - "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -1713,8 +2256,9 @@ }, "node_modules/boxen/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1727,8 +2271,9 @@ }, "node_modules/boxen/node_modules/type-fest": { "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -1738,8 +2283,9 @@ }, "node_modules/boxen/node_modules/wrap-ansi": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1752,30 +2298,20 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { - "version": "1.1.11", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1785,11 +2321,14 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, "node_modules/browserslist": { - "version": "4.22.2", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "dev": true, "funding": [ { @@ -1805,10 +2344,9 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -1820,7 +2358,9 @@ } }, "node_modules/buffer": { - "version": "6.0.3", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -1836,21 +2376,21 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "ieee754": "^1.1.13" } }, "node_modules/bundle-name": { - "version": "3.0.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, - "license": "MIT", "dependencies": { - "run-applescript": "^5.0.0" + "run-applescript": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1858,16 +2398,18 @@ }, "node_modules/cacheable-lookup": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" } }, "node_modules/cacheable-request": { "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", @@ -1883,8 +2425,9 @@ }, "node_modules/cacheable-request/node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -1894,8 +2437,9 @@ }, "node_modules/caching-transform": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, - "license": "MIT", "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1908,8 +2452,9 @@ }, "node_modules/call-bind": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, - "license": "MIT", "dependencies": { "function-bind": "^1.1.2", "get-intrinsic": "^1.2.1", @@ -1921,22 +2466,26 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001566", + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", "dev": true, "funding": [ { @@ -1951,13 +2500,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1971,11 +2520,14 @@ }, "node_modules/chardet": { "version": "0.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true }, "node_modules/chokidar": { "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -1983,7 +2535,6 @@ "url": "https://paulmillr.com/funding/" } ], - "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2002,8 +2553,9 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2013,6 +2565,8 @@ }, "node_modules/ci-info": { "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -2020,23 +2574,24 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-boxes": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2046,8 +2601,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -2057,8 +2613,9 @@ }, "node_modules/cli-spinners": { "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" }, @@ -2068,16 +2625,18 @@ }, "node_modules/cli-width": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, - "license": "ISC", "engines": { "node": ">= 12" } }, "node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -2086,8 +2645,9 @@ }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2102,23 +2662,26 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/cluster-key-slot": { "version": "1.1.2", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2128,31 +2691,36 @@ }, "node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/commander": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" } }, "node_modules/commondir": { "version": "1.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/config-chain": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, - "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -2160,13 +2728,15 @@ }, "node_modules/config-chain/node_modules/ini": { "version": "1.3.8", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/configstore": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "dot-prop": "^6.0.1", "graceful-fs": "^4.2.6", @@ -2183,18 +2753,20 @@ }, "node_modules/convert-source-map": { "version": "1.9.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/cosmiconfig": { - "version": "8.3.6", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, - "license": "MIT", "dependencies": { + "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "parse-json": "^5.2.0" }, "engines": { "node": ">=14" @@ -2213,8 +2785,9 @@ }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2226,8 +2799,9 @@ }, "node_modules/crypto-random-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^1.0.1" }, @@ -2240,8 +2814,9 @@ }, "node_modules/crypto-random-string/node_modules/type-fest": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2251,16 +2826,18 @@ }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 12" } }, "node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -2275,16 +2852,18 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/decompress-response": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, - "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -2297,8 +2876,9 @@ }, "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2308,97 +2888,43 @@ }, "node_modules/deep-extend": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/default-browser": { - "version": "4.0.0", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, - "license": "MIT", "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/default-browser-id": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/execa": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-browser/node_modules/get-stream": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/human-signals": { - "version": "4.3.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/default-browser/node_modules/is-stream": { - "version": "3.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, - "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2406,8 +2932,9 @@ }, "node_modules/default-require-extensions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, - "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" }, @@ -2420,8 +2947,9 @@ }, "node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, - "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -2431,16 +2959,18 @@ }, "node_modules/defer-to-connect": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/define-data-property": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.1", "gopd": "^1.0.1", @@ -2452,8 +2982,9 @@ }, "node_modules/define-lazy-prop": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -2463,8 +2994,9 @@ }, "node_modules/define-properties": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -2479,8 +3011,9 @@ }, "node_modules/degenerator": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "dev": true, - "license": "MIT", "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -2492,21 +3025,24 @@ }, "node_modules/deprecation": { "version": "2.3.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true }, "node_modules/diff": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/dir-glob": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -2516,8 +3052,9 @@ }, "node_modules/doctrine": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { "esutils": "^2.0.2" @@ -2528,8 +3065,9 @@ }, "node_modules/dot-prop": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", "dev": true, - "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -2542,36 +3080,51 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.603", - "dev": true, - "license": "ISC" + "version": "1.4.648", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", + "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", + "dev": true }, "node_modules/email-addresses": { "version": "5.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true }, "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==", + "dev": true + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=6" + } }, "node_modules/error-ex": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.2", @@ -2622,13 +3175,15 @@ }, "node_modules/es-array-method-boxes-properly": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true }, "node_modules/es-get-iterator": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -2646,8 +3201,9 @@ }, "node_modules/es-set-tostringtag": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.2", "has-tostringtag": "^1.0.0", @@ -2659,8 +3215,9 @@ }, "node_modules/es-to-primitive": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -2675,14 +3232,16 @@ }, "node_modules/es6-error": { "version": "4.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true }, "node_modules/esbuild": { - "version": "0.18.20", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", "dev": true, "hasInstallScript": true, - "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -2690,42 +3249,45 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" } }, "node_modules/escalade": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-goat": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -2735,8 +3297,9 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -2746,8 +3309,9 @@ }, "node_modules/escodegen": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -2765,15 +3329,16 @@ } }, "node_modules/eslint": { - "version": "8.55.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2821,8 +3386,9 @@ }, "node_modules/eslint-scope": { "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2837,8 +3403,9 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2846,10 +3413,35 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "acorn": "^8.9.0", @@ -2865,8 +3457,9 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2877,8 +3470,9 @@ }, "node_modules/esquery": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "license": "BSD-3-Clause", "peer": true, "dependencies": { "estraverse": "^5.1.0" @@ -2889,8 +3483,9 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "estraverse": "^5.2.0" @@ -2901,24 +3496,27 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/execa": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, - "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -2939,8 +3537,9 @@ }, "node_modules/execa/node_modules/is-stream": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2950,8 +3549,9 @@ }, "node_modules/execa/node_modules/signal-exit": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "ISC", "engines": { "node": ">=14" }, @@ -2961,8 +3561,9 @@ }, "node_modules/external-editor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, - "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -2974,14 +3575,16 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fast-glob": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2995,8 +3598,9 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3006,26 +3610,31 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/fastq": { - "version": "1.15.0", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", "dev": true, - "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fetch-blob": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "dev": true, "funding": [ { @@ -3037,7 +3646,6 @@ "url": "https://paypal.me/jimmywarting" } ], - "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -3048,8 +3656,9 @@ }, "node_modules/figures": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^5.0.0", "is-unicode-supported": "^1.2.0" @@ -3063,8 +3672,9 @@ }, "node_modules/figures/node_modules/escape-string-regexp": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -3074,8 +3684,9 @@ }, "node_modules/figures/node_modules/is-unicode-supported": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -3085,8 +3696,9 @@ }, "node_modules/file-entry-cache": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "flat-cache": "^3.0.4" @@ -3097,16 +3709,18 @@ }, "node_modules/filename-reserved-regex": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/filenamify": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, - "license": "MIT", "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", @@ -3121,8 +3735,9 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3132,8 +3747,9 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, - "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -3148,8 +3764,9 @@ }, "node_modules/find-up": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3163,16 +3780,18 @@ }, "node_modules/flat": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "flatted": "^3.2.9", @@ -3185,22 +3804,25 @@ }, "node_modules/flatted": { "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true, - "license": "ISC", "peer": true }, "node_modules/for-each": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } }, "node_modules/foreground-child": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, - "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" @@ -3211,16 +3833,18 @@ }, "node_modules/form-data-encoder": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 14.17" } }, "node_modules/formdata-polyfill": { "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dev": true, - "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -3230,6 +3854,8 @@ }, "node_modules/fromentries": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { @@ -3244,13 +3870,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/fs-extra": { "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -3262,21 +3888,38 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "license": "ISC" + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -3292,32 +3935,48 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, - "license": "MIT", "dependencies": { "function-bind": "^1.1.2", "has-proto": "^1.0.1", @@ -3330,16 +3989,18 @@ }, "node_modules/get-package-type": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" }, @@ -3349,8 +4010,9 @@ }, "node_modules/get-symbol-description": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -3364,8 +4026,9 @@ }, "node_modules/get-tsconfig": { "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", "dev": true, - "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -3375,8 +4038,9 @@ }, "node_modules/get-uri": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", + "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", "dev": true, - "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.0", @@ -3389,16 +4053,18 @@ }, "node_modules/get-uri/node_modules/data-uri-to-buffer": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", + "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/get-uri/node_modules/fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -3410,24 +4076,27 @@ }, "node_modules/get-uri/node_modules/jsonfile": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/get-uri/node_modules/universalify": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/gh-pages": { - "version": "6.1.0", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz", + "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==", "dev": true, - "license": "MIT", "dependencies": { "async": "^3.2.4", "commander": "^11.0.0", @@ -3447,8 +4116,9 @@ }, "node_modules/gh-pages/node_modules/array-union": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, - "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -3458,8 +4128,9 @@ }, "node_modules/gh-pages/node_modules/globby": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, - "license": "MIT", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -3473,25 +4144,28 @@ }, "node_modules/git-up": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "dev": true, - "license": "MIT", "dependencies": { "is-ssh": "^1.4.0", "parse-url": "^8.1.0" } }, "node_modules/git-url-parse": { - "version": "13.1.1", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-14.0.0.tgz", + "integrity": "sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==", "dev": true, - "license": "MIT", "dependencies": { "git-up": "^7.0.0" } }, "node_modules/glob": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, - "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3509,8 +4183,9 @@ }, "node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -3519,10 +4194,33 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global-dirs": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, - "license": "MIT", "dependencies": { "ini": "2.0.0" }, @@ -3534,9 +4232,10 @@ } }, "node_modules/globals": { - "version": "13.23.0", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "type-fest": "^0.20.2" @@ -3550,8 +4249,9 @@ }, "node_modules/globalthis": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, - "license": "MIT", "dependencies": { "define-properties": "^1.1.3" }, @@ -3564,8 +4264,9 @@ }, "node_modules/globby": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3583,8 +4284,9 @@ }, "node_modules/gopd": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -3594,8 +4296,9 @@ }, "node_modules/got": { "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", "dev": true, - "license": "MIT", "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", @@ -3618,8 +4321,9 @@ }, "node_modules/got/node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -3629,34 +4333,39 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "node_modules/has-bigints": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.2" }, @@ -3666,8 +4375,9 @@ }, "node_modules/has-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3677,8 +4387,9 @@ }, "node_modules/has-symbols": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3688,8 +4399,9 @@ }, "node_modules/has-tostringtag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, - "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -3702,8 +4414,9 @@ }, "node_modules/hasha": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, - "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" @@ -3717,16 +4430,18 @@ }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/hasown": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "dev": true, - "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3736,26 +4451,30 @@ }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/html-escaper": { "version": "2.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "node_modules/http-cache-semantics": { "version": "4.1.1", - "dev": true, - "license": "BSD-2-Clause" + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true }, "node_modules/http-proxy-agent": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -3766,8 +4485,9 @@ }, "node_modules/http2-wrapper": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, - "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -3778,8 +4498,9 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -3790,16 +4511,18 @@ }, "node_modules/human-signals": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } }, "node_modules/iconv-lite": { "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -3809,6 +4532,8 @@ }, "node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -3823,21 +4548,22 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "BSD-3-Clause" + ] }, "node_modules/ignore": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3851,32 +4577,36 @@ }, "node_modules/import-lazy": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, - "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3884,21 +4614,24 @@ }, "node_modules/inherits": { "version": "2.0.4", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/ini": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/inquirer": { "version": "9.2.12", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", + "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", "dev": true, - "license": "MIT", "dependencies": { "@ljharb/through": "^2.3.11", "ansi-escapes": "^4.3.2", @@ -3920,43 +4653,11 @@ "node": ">=14.18.0" } }, - "node_modules/inquirer/node_modules/bl": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/inquirer/node_modules/buffer": { - "version": "5.7.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/inquirer/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -3966,16 +4667,18 @@ }, "node_modules/inquirer/node_modules/is-interactive": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inquirer/node_modules/ora": { "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, - "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -3996,8 +4699,9 @@ }, "node_modules/inquirer/node_modules/ora/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4011,8 +4715,9 @@ }, "node_modules/internal-slot": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, - "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.2", "hasown": "^2.0.0", @@ -4024,21 +4729,24 @@ }, "node_modules/interpret": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/ip": { "version": "1.1.8", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true }, "node_modules/is-arguments": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -4052,8 +4760,9 @@ }, "node_modules/is-array-buffer": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.0", @@ -4065,13 +4774,15 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true }, "node_modules/is-bigint": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -4081,8 +4792,9 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4092,8 +4804,9 @@ }, "node_modules/is-boolean-object": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -4107,8 +4820,9 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4118,8 +4832,9 @@ }, "node_modules/is-ci": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, - "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -4129,8 +4844,9 @@ }, "node_modules/is-core-module": { "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, - "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -4140,8 +4856,9 @@ }, "node_modules/is-date-object": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4154,8 +4871,9 @@ }, "node_modules/is-docker": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, - "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -4168,24 +4886,27 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "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==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -4195,8 +4916,9 @@ }, "node_modules/is-in-ci": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-0.1.0.tgz", + "integrity": "sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==", "dev": true, - "license": "MIT", "bin": { "is-in-ci": "cli.js" }, @@ -4209,8 +4931,9 @@ }, "node_modules/is-inside-container": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, - "license": "MIT", "dependencies": { "is-docker": "^3.0.0" }, @@ -4226,8 +4949,9 @@ }, "node_modules/is-installed-globally": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, - "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" @@ -4241,8 +4965,9 @@ }, "node_modules/is-interactive": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -4252,16 +4977,18 @@ }, "node_modules/is-map": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-negative-zero": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4271,8 +4998,9 @@ }, "node_modules/is-npm": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4282,16 +5010,18 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-number-object": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4304,32 +5034,36 @@ }, "node_modules/is-obj": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-regex": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -4343,16 +5077,18 @@ }, "node_modules/is-set": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -4362,16 +5098,18 @@ }, "node_modules/is-ssh": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", + "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", "dev": true, - "license": "MIT", "dependencies": { "protocols": "^2.0.1" } }, "node_modules/is-stream": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -4381,8 +5119,9 @@ }, "node_modules/is-string": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, - "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -4395,8 +5134,9 @@ }, "node_modules/is-symbol": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, - "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -4409,8 +5149,9 @@ }, "node_modules/is-typed-array": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dev": true, - "license": "MIT", "dependencies": { "which-typed-array": "^1.1.11" }, @@ -4423,13 +5164,15 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -4439,8 +5182,9 @@ }, "node_modules/is-weakref": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -4450,32 +5194,23 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-wsl": { - "version": "2.2.0", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, - "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4483,18 +5218,21 @@ }, "node_modules/isarray": { "version": "2.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/issue-parser": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", "dev": true, - "license": "MIT", "dependencies": { "lodash.capitalize": "^4.2.1", "lodash.escaperegexp": "^4.1.2", @@ -4508,16 +5246,18 @@ }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" }, @@ -4527,8 +5267,9 @@ }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -4541,16 +5282,18 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, - "license": "ISC", "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", @@ -4565,8 +5308,9 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -4578,8 +5322,9 @@ }, "node_modules/istanbul-lib-report/node_modules/make-dir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -4592,8 +5337,9 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -4605,8 +5351,9 @@ }, "node_modules/istanbul-reports": { "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -4617,16 +5364,18 @@ }, "node_modules/iterate-iterator": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/iterate-value": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", "dev": true, - "license": "MIT", "dependencies": { "es-get-iterator": "^1.0.2", "iterate-iterator": "^1.0.1" @@ -4637,13 +5386,15 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4653,8 +5404,9 @@ }, "node_modules/jsesc": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -4664,30 +5416,35 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -4696,14 +5453,16 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.0", - "dev": true, - "license": "MIT" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true }, "node_modules/jsonfile": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, - "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -4712,22 +5471,25 @@ } }, "node_modules/just-extend": { - "version": "4.2.1", - "dev": true, - "license": "MIT" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true }, "node_modules/keyv": { "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/latest-version": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", "dev": true, - "license": "MIT", "dependencies": { "package-json": "^8.1.0" }, @@ -4740,8 +5502,9 @@ }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -4753,13 +5516,15 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true }, "node_modules/locate-path": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -4772,54 +5537,64 @@ }, "node_modules/lodash": { "version": "4.17.21", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash.capitalize": { "version": "4.2.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true }, "node_modules/lodash.escaperegexp": { "version": "4.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true }, "node_modules/lodash.flattendeep": { "version": "4.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true }, "node_modules/lodash.isstring": { "version": "4.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/lodash.uniqby": { "version": "4.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -4833,8 +5608,9 @@ }, "node_modules/lowercase-keys": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4844,21 +5620,24 @@ }, "node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/lunr": { "version": "2.3.9", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true }, "node_modules/macos-release": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.2.0.tgz", + "integrity": "sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4868,8 +5647,9 @@ }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -4882,16 +5662,18 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/marked": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, - "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -4901,21 +5683,24 @@ }, "node_modules/merge-stream": { "version": "2.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -4926,16 +5711,18 @@ }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -4945,8 +5732,9 @@ }, "node_modules/mimic-fn": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -4956,8 +5744,9 @@ }, "node_modules/mimic-response": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4966,28 +5755,34 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/mocha": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -5023,18 +5818,11 @@ "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5044,13 +5832,15 @@ }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -5063,21 +5853,24 @@ }, "node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/mute-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, - "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/nanoid": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5087,21 +5880,24 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "node_modules/netmask": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/new-github-release-url": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", + "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^2.5.1" }, @@ -5114,8 +5910,9 @@ }, "node_modules/new-github-release-url/node_modules/type-fest": { "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -5124,43 +5921,22 @@ } }, "node_modules/nise": { - "version": "5.1.5", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "3.0.0", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", + "integrity": "sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, "node_modules/node-domexception": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "dev": true, "funding": [ { @@ -5172,15 +5948,15 @@ "url": "https://paypal.me/jimmywarting" } ], - "license": "MIT", "engines": { "node": ">=10.5.0" } }, "node_modules/node-fetch": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, - "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -5196,8 +5972,9 @@ }, "node_modules/node-preload": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, - "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" }, @@ -5207,21 +5984,24 @@ }, "node_modules/node-releases": { "version": "2.0.14", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/normalize-url": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", + "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -5230,9 +6010,10 @@ } }, "node_modules/npm-run-path": { - "version": "5.1.0", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -5245,8 +6026,9 @@ }, "node_modules/npm-run-path/node_modules/path-key": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5256,8 +6038,9 @@ }, "node_modules/nyc": { "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -5296,8 +6079,9 @@ }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -5306,8 +6090,9 @@ }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5318,8 +6103,9 @@ }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -5329,8 +6115,9 @@ }, "node_modules/nyc/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -5343,8 +6130,9 @@ }, "node_modules/nyc/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -5354,21 +6142,24 @@ }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -5388,8 +6179,9 @@ }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, - "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -5400,32 +6192,36 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -5441,16 +6237,18 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, - "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -5462,17 +6260,18 @@ } }, "node_modules/open": { - "version": "9.1.0", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.3.tgz", + "integrity": "sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A==", "dev": true, - "license": "MIT", "dependencies": { - "default-browser": "^4.0.0", + "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5480,8 +6279,9 @@ }, "node_modules/optionator": { "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", @@ -5496,22 +6296,23 @@ } }, "node_modules/ora": { - "version": "7.0.1", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^4.0.0", - "cli-spinners": "^2.9.0", + "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.3.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "string-width": "^6.1.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5519,8 +6320,9 @@ }, "node_modules/ora/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -5530,8 +6332,9 @@ }, "node_modules/ora/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -5541,8 +6344,9 @@ }, "node_modules/ora/node_modules/cli-cursor": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, - "license": "MIT", "dependencies": { "restore-cursor": "^4.0.0" }, @@ -5555,28 +6359,43 @@ }, "node_modules/ora/node_modules/emoji-regex": { "version": "10.3.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, "node_modules/ora/node_modules/is-unicode-supported": { - "version": "1.3.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", "dev": true, - "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ora/node_modules/log-symbols": { - "version": "5.1.0", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, - "license": "MIT", "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, "engines": { "node": ">=12" }, @@ -5586,16 +6405,18 @@ }, "node_modules/ora/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==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ora/node_modules/onetime": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -5608,8 +6429,9 @@ }, "node_modules/ora/node_modules/restore-cursor": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, - "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -5622,16 +6444,17 @@ } }, "node_modules/ora/node_modules/string-width": { - "version": "6.1.0", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, - "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^10.2.1", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5639,8 +6462,9 @@ }, "node_modules/ora/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5653,8 +6477,9 @@ }, "node_modules/os-name": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", + "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", "dev": true, - "license": "MIT", "dependencies": { "macos-release": "^3.1.0", "windows-release": "^5.0.1" @@ -5668,24 +6493,27 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/p-cancelable": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, - "license": "MIT", "engines": { "node": ">=12.20" } }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5698,8 +6526,9 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -5712,8 +6541,9 @@ }, "node_modules/p-map": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, - "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -5723,16 +6553,18 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pac-proxy-agent": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -5749,8 +6581,9 @@ }, "node_modules/pac-resolver": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", "dev": true, - "license": "MIT", "dependencies": { "degenerator": "^5.0.0", "ip": "^1.1.8", @@ -5762,8 +6595,9 @@ }, "node_modules/package-hash": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, - "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -5776,8 +6610,9 @@ }, "node_modules/package-json": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", "dev": true, - "license": "MIT", "dependencies": { "got": "^12.1.0", "registry-auth-token": "^5.0.1", @@ -5793,8 +6628,9 @@ }, "node_modules/package-json/node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -5804,8 +6640,9 @@ }, "node_modules/package-json/node_modules/got": { "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", "dev": true, - "license": "MIT", "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", @@ -5828,8 +6665,9 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -5839,8 +6677,9 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -5856,79 +6695,81 @@ }, "node_modules/parse-path": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", "dev": true, - "license": "MIT", "dependencies": { "protocols": "^2.0.0" } }, "node_modules/parse-url": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "dev": true, - "license": "MIT", "dependencies": { "parse-path": "^7.0.0" } }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -5938,24 +6779,27 @@ }, "node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, - "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -5965,8 +6809,9 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -5976,8 +6821,9 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5988,8 +6834,9 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -5999,8 +6846,9 @@ }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -6013,8 +6861,9 @@ }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -6024,8 +6873,9 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">= 0.8.0" @@ -6033,8 +6883,9 @@ }, "node_modules/process-on-spawn": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, - "license": "MIT", "dependencies": { "fromentries": "^1.2.0" }, @@ -6044,8 +6895,9 @@ }, "node_modules/promise.allsettled": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.7.tgz", + "integrity": "sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA==", "dev": true, - "license": "MIT", "dependencies": { "array.prototype.map": "^1.0.5", "call-bind": "^1.0.2", @@ -6063,18 +6915,21 @@ }, "node_modules/proto-list": { "version": "1.2.4", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true }, "node_modules/protocols": { "version": "2.0.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true }, "node_modules/proxy-agent": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -6091,21 +6946,24 @@ }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/proxy-from-env": { "version": "1.1.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -6113,8 +6971,9 @@ }, "node_modules/pupa": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", "dev": true, - "license": "MIT", "dependencies": { "escape-goat": "^4.0.0" }, @@ -6127,6 +6986,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -6141,13 +7002,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/quick-lru": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -6157,16 +7018,18 @@ }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/rc": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -6179,21 +7042,24 @@ }, "node_modules/rc/node_modules/ini": { "version": "1.3.8", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6205,8 +7071,9 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -6216,6 +7083,8 @@ }, "node_modules/rechoir": { "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "dependencies": { "resolve": "^1.1.6" @@ -6230,8 +7099,9 @@ }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -6246,8 +7116,9 @@ }, "node_modules/registry-auth-token": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "dev": true, - "license": "MIT", "dependencies": { "@pnpm/npm-conf": "^2.1.0" }, @@ -6257,8 +7128,9 @@ }, "node_modules/registry-url": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", "dev": true, - "license": "MIT", "dependencies": { "rc": "1.2.8" }, @@ -6270,17 +7142,28 @@ } }, "node_modules/release-it": { - "version": "17.0.0", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-17.0.3.tgz", + "integrity": "sha512-QjTCmvQm91pwLEbvavEs9jofHNe8thsb9Uimin+8DNSwFRdUd73p0Owy2PP/Dzh/EegRkKq/o+4Pn1xp8pC1og==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/webpro" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/webpro" + } + ], "dependencies": { "@iarna/toml": "2.2.5", "@octokit/rest": "20.0.2", "async-retry": "1.3.3", "chalk": "5.3.0", - "cosmiconfig": "8.3.6", + "cosmiconfig": "9.0.0", "execa": "8.0.1", - "git-url-parse": "13.1.1", + "git-url-parse": "14.0.0", "globby": "14.0.0", "got": "13.0.0", "inquirer": "9.2.12", @@ -6290,8 +7173,8 @@ "mime-types": "2.1.35", "new-github-release-url": "2.0.0", "node-fetch": "3.3.2", - "open": "9.1.0", - "ora": "7.0.1", + "open": "10.0.3", + "ora": "8.0.1", "os-name": "5.1.0", "promise.allsettled": "1.0.7", "proxy-agent": "6.3.1", @@ -6311,8 +7194,9 @@ }, "node_modules/release-it/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -6322,8 +7206,9 @@ }, "node_modules/release-it/node_modules/globby": { "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", "dev": true, - "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^1.0.0", "fast-glob": "^3.3.2", @@ -6341,8 +7226,9 @@ }, "node_modules/release-it/node_modules/path-type": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -6352,8 +7238,9 @@ }, "node_modules/release-it/node_modules/slash": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -6363,16 +7250,18 @@ }, "node_modules/release-it/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/release-zalgo": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, - "license": "ISC", "dependencies": { "es6-error": "^4.0.1" }, @@ -6382,21 +7271,24 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "node_modules/resolve": { "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, - "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -6411,210 +7303,139 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, "node_modules/responselike": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, - "license": "MIT", "dependencies": { "lowercase-keys": "^3.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", + "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==", "dev": true, - "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=8" } }, - "node_modules/run-applescript/node_modules/get-stream": { - "version": "6.0.1", + "node_modules/restore-cursor/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==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "license": "Apache-2.0", + "dependencies": { + "mimic-fn": "^2.1.0" + }, "engines": { - "node": ">=10.17.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, "engines": { - "node": ">=8" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, - "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=6" + "bin": { + "rimraf": "bin.js" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/run-async": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -6630,26 +7451,27 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/rxjs": { "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, - "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-array-concat": { - "version": "1.0.1", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -6662,6 +7484,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -6676,31 +7500,36 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/safer-buffer": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/semver": { "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6713,8 +7542,9 @@ }, "node_modules/semver-diff": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", "dev": true, - "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -6727,8 +7557,9 @@ }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -6738,31 +7569,36 @@ }, "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/serialize-javascript": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/set-blocking": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/set-function-length": { - "version": "1.1.1", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6770,8 +7606,9 @@ }, "node_modules/set-function-name": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "functions-have-names": "^1.2.3", @@ -6783,8 +7620,9 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6794,16 +7632,18 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shelljs": { "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -6817,9 +7657,10 @@ } }, "node_modules/shiki": { - "version": "0.14.5", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -6829,8 +7670,9 @@ }, "node_modules/side-channel": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -6842,13 +7684,15 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/sinon": { "version": "17.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", + "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -6864,24 +7708,27 @@ }, "node_modules/sinon/node_modules/diff": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -6889,8 +7736,9 @@ }, "node_modules/socks": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, - "license": "MIT", "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -6902,8 +7750,9 @@ }, "node_modules/socks-proxy-agent": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -6915,21 +7764,24 @@ }, "node_modules/socks/node_modules/ip": { "version": "2.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/spawn-wrap": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, - "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -6944,18 +7796,17 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "node_modules/stdin-discarder": { - "version": "0.1.0", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6963,8 +7814,9 @@ }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", "dev": true, - "license": "MIT", "dependencies": { "internal-slot": "^1.0.4" }, @@ -6974,16 +7826,18 @@ }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, - "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "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==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6995,8 +7849,9 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7011,8 +7866,9 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7024,8 +7880,9 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7037,8 +7894,9 @@ }, "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==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -7048,16 +7906,18 @@ }, "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-final-newline": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7067,8 +7927,9 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -7078,8 +7939,9 @@ }, "node_modules/strip-outer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7089,16 +7951,18 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7108,8 +7972,9 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7119,8 +7984,9 @@ }, "node_modules/test-exclude": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -7130,27 +7996,40 @@ "node": ">=8" } }, - "node_modules/text-table": { - "version": "0.2.0", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", - "peer": true + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/titleize": { - "version": "3.0.0", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "*" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true + }, "node_modules/tmp": { "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, - "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -7160,16 +8039,18 @@ }, "node_modules/to-fast-properties": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -7179,8 +8060,9 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.2" }, @@ -7190,16 +8072,18 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/ts-api-utils": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, - "license": "MIT", "engines": { "node": ">=16.13.0" }, @@ -7209,15 +8093,17 @@ }, "node_modules/tslib": { "version": "2.6.2", - "dev": true, - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, "node_modules/tsx": { - "version": "4.6.2", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz", + "integrity": "sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==", "dev": true, - "license": "MIT", "dependencies": { - "esbuild": "~0.18.20", + "esbuild": "~0.19.10", "get-tsconfig": "^4.7.2" }, "bin": { @@ -7232,8 +8118,9 @@ }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -7244,16 +8131,18 @@ }, "node_modules/type-detect": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", "peer": true, "engines": { "node": ">=10" @@ -7264,8 +8153,9 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1", @@ -7277,8 +8167,9 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -7294,8 +8185,9 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", "dev": true, - "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -7312,8 +8204,9 @@ }, "node_modules/typed-array-length": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -7325,21 +8218,23 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, - "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { - "version": "0.25.4", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.7.tgz", + "integrity": "sha512-m6A6JjQRg39p2ZVRIN3NKXgrN8vzlHhOS+r9ymUYtcUP/TIQPvWSq7YgE5ZjASfv5Vd5BW5xrir6Gm2XNNcOow==", "dev": true, - "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", "minimatch": "^9.0.3", - "shiki": "^0.14.1" + "shiki": "^0.14.7" }, "bin": { "typedoc": "bin/typedoc" @@ -7351,32 +8246,11 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { - "version": "5.3.2", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7387,8 +8261,9 @@ }, "node_modules/unbox-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -7401,13 +8276,15 @@ }, "node_modules/undici-types": { "version": "5.26.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/unicorn-magic": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -7417,8 +8294,9 @@ }, "node_modules/unique-string": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", "dev": true, - "license": "MIT", "dependencies": { "crypto-random-string": "^4.0.0" }, @@ -7431,27 +8309,23 @@ }, "node_modules/universal-user-agent": { "version": "6.0.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true }, "node_modules/universalify": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -7467,7 +8341,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -7481,8 +8354,9 @@ }, "node_modules/update-notifier": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.0.0.tgz", + "integrity": "sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boxen": "^7.1.1", "chalk": "^5.3.0", @@ -7506,8 +8380,9 @@ }, "node_modules/update-notifier/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -7517,8 +8392,9 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-2-Clause", "peer": true, "dependencies": { "punycode": "^2.1.0" @@ -7526,55 +8402,63 @@ }, "node_modules/url-join": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/util-deprecate": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/vscode-oniguruma": { "version": "1.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true }, "node_modules/vscode-textmate": { "version": "8.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true }, "node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, - "license": "MIT", "dependencies": { "defaults": "^1.0.3" } }, "node_modules/web-streams-polyfill": { - "version": "3.2.1", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", + "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -7587,8 +8471,9 @@ }, "node_modules/which-boxed-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, - "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -7602,13 +8487,15 @@ }, "node_modules/which-module": { "version": "2.0.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true }, "node_modules/which-typed-array": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, - "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.4", @@ -7625,8 +8512,9 @@ }, "node_modules/widest-line": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dev": true, - "license": "MIT", "dependencies": { "string-width": "^5.0.1" }, @@ -7639,8 +8527,9 @@ }, "node_modules/widest-line/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7650,13 +8539,15 @@ }, "node_modules/widest-line/node_modules/emoji-regex": { "version": "9.2.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/widest-line/node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, - "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -7671,8 +8562,9 @@ }, "node_modules/widest-line/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -7685,13 +8577,15 @@ }, "node_modules/wildcard-match": { "version": "5.1.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.2.tgz", + "integrity": "sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==", + "dev": true }, "node_modules/windows-release": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.1.1.tgz", + "integrity": "sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==", "dev": true, - "license": "MIT", "dependencies": { "execa": "^5.1.1" }, @@ -7704,8 +8598,9 @@ }, "node_modules/windows-release/node_modules/execa": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -7726,8 +8621,9 @@ }, "node_modules/windows-release/node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7737,24 +8633,27 @@ }, "node_modules/windows-release/node_modules/human-signals": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/windows-release/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==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/windows-release/node_modules/npm-run-path": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -7764,8 +8663,9 @@ }, "node_modules/windows-release/node_modules/onetime": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -7778,21 +8678,24 @@ }, "node_modules/windows-release/node_modules/strip-final-newline": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/workerpool": { "version": "6.2.1", - "dev": true, - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": 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==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7804,13 +8707,15 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -7820,8 +8725,9 @@ }, "node_modules/xdg-basedir": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7831,21 +8737,24 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -7861,16 +8770,18 @@ }, "node_modules/yargs-parser": { "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -7883,8 +8794,9 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7894,8 +8806,9 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7905,8 +8818,9 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -7915,7 +8829,6 @@ } }, "packages/bloom": { - "name": "@redis/bloom", "version": "2.0.0-next.3", "license": "MIT", "devDependencies": { @@ -7926,7 +8839,6 @@ } }, "packages/client": { - "name": "@redis/client", "version": "2.0.0-next.4", "license": "MIT", "dependencies": { @@ -7942,7 +8854,6 @@ } }, "packages/graph": { - "name": "@redis/graph", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -7953,7 +8864,6 @@ } }, "packages/json": { - "name": "@redis/json", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -7976,7 +8886,6 @@ } }, "packages/search": { - "name": "@redis/search", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { @@ -7987,7 +8896,6 @@ } }, "packages/test-utils": { - "name": "@redis/test-utils", "devDependencies": { "@types/yargs": "^17.0.32", "yargs": "^17.7.2" @@ -7998,8 +8906,9 @@ }, "packages/test-utils/node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -8011,8 +8920,9 @@ }, "packages/test-utils/node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8027,8 +8937,9 @@ }, "packages/test-utils/node_modules/yargs": { "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -8044,14 +8955,14 @@ }, "packages/test-utils/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC", "engines": { "node": ">=12" } }, "packages/time-series": { - "name": "@redis/time-series", "version": "2.0.0-next.2", "license": "MIT", "devDependencies": { diff --git a/packages/client/index.ts b/packages/client/index.ts index 6d6efd07725..c6f8814a6c5 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -16,6 +16,11 @@ import RedisCluster, { RedisClusterOptions, RedisClusterType } from './lib/clust export { RedisClusterType, RedisClusterOptions }; export const createCluster = RedisCluster.create; +import RedisSentinel from './lib/sentinel'; +import { RedisSentinelOptions, RedisSentinelType } from './lib/sentinel/types'; +export { RedisSentinelType, RedisSentinelOptions }; +export const createSentinel = RedisSentinel.create; + // export { GeoReplyWith } from './lib/commands/generic-transformers'; // export { SetOptions } from './lib/commands/SET'; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index 034c1e46bd8..a4029779fc8 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -268,7 +268,7 @@ export default class RedisCommandsQueue { } getPubSubListeners(type: PubSubType) { - return this.#pubSub.getTypeListeners(type); + return this.#pubSub.listeners[type]; } monitor(callback: MonitorCallback, options?: CommandOptions) { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index d6b9e3714d4..a24770e6f99 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -6,7 +6,7 @@ import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumen import { ClientClosedError, ClientOfflineError, DisconnectsClientError, WatchError } from '../errors'; import { URL } from 'node:url'; import { TcpSocketConnectOpts } from 'node:net'; -import { PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; +import { PUBSUB_TYPE, PubSubType, PubSubListener, PubSubTypeListeners, ChannelListeners } from './pub-sub'; import { Command, CommandSignature, TypeMapping, CommanderConfig, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, RedisArgument, ReplyWithTypeMapping, SimpleStringReply } from '../RESP/types'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; import { RedisMultiQueuedCommand } from '../multi-command'; @@ -14,6 +14,7 @@ import HELLO, { HelloOptions } from '../commands/HELLO'; import { ScanOptions, ScanCommonOptions } from '../commands/SCAN'; import { RedisLegacyClient, RedisLegacyClientType } from './legacy-mode'; import { RedisPoolOptions, RedisClientPool } from './pool'; +import { RedisVariadicArgument, pushVariadicArguments } from '../commands/generic-transformers'; export interface RedisClientOptions< M extends RedisModules = RedisModules, @@ -279,6 +280,9 @@ export default class RedisClient< #monitorCallback?: MonitorCallback; private _self = this; private _commandOptions?: CommandOptions; + #dirtyWatch?: string; + #epoch: number; + #watchEpoch?: number; get options(): RedisClientOptions | undefined { return this._self.#options; @@ -296,11 +300,20 @@ export default class RedisClient< return this._self.#queue.isPubSubActive; } + get isWatching() { + return this._self.#watchEpoch !== undefined; + } + + setDirtyWatch(msg: string) { + this._self.#dirtyWatch = msg; + } + constructor(options?: RedisClientOptions) { super(); this.#options = this.#initiateOptions(options); this.#queue = this.#initiateQueue(); this.#socket = this.#initiateSocket(); + this.#epoch = 0; } #initiateOptions(options?: RedisClientOptions): RedisClientOptions | undefined { @@ -440,6 +453,7 @@ export default class RedisClient< }) .on('connect', () => this.emit('connect')) .on('ready', () => { + this.#epoch++; this.emit('ready'); this.#setPingTimer(); this.#maybeScheduleWrite(); @@ -596,7 +610,7 @@ export default class RedisClient< select = this.SELECT; - #pubSubCommand(promise: Promise | undefined) { + #pubSubCommand(promise: Promise | undefined) { if (promise === undefined) return Promise.resolve(); this.#scheduleWrite(); @@ -610,7 +624,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.subscribe( - PubSubType.CHANNELS, + PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode @@ -627,7 +641,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.unsubscribe( - PubSubType.CHANNELS, + PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode @@ -635,7 +649,7 @@ export default class RedisClient< ); } - unsubscribe = this.UNSUBSCRIBE + unsubscribe = this.UNSUBSCRIBE; PSUBSCRIBE( patterns: string | Array, @@ -644,7 +658,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.subscribe( - PubSubType.PATTERNS, + PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode @@ -661,7 +675,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.unsubscribe( - PubSubType.PATTERNS, + PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode @@ -678,7 +692,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.subscribe( - PubSubType.SHARDED, + PUBSUB_TYPE.SHARDED, channels, listener, bufferMode @@ -695,7 +709,7 @@ export default class RedisClient< ): Promise { return this._self.#pubSubCommand( this._self.#queue.unsubscribe( - PubSubType.SHARDED, + PUBSUB_TYPE.SHARDED, channels, listener, bufferMode @@ -705,6 +719,24 @@ export default class RedisClient< sUnsubscribe = this.SUNSUBSCRIBE; + async WATCH(key: RedisVariadicArgument) { + const reply = await this._self.sendCommand( + pushVariadicArguments(['WATCH'], key) + ); + this._self.#watchEpoch ??= this._self.#epoch; + return reply as unknown as ReplyWithTypeMapping, TYPE_MAPPING>; + } + + watch = this.WATCH; + + async UNWATCH() { + const reply = await this._self.sendCommand(['UNWATCH']); + this._self.#watchEpoch = undefined; + return reply as unknown as ReplyWithTypeMapping, TYPE_MAPPING>; + } + + unwatch = this.UNWATCH; + getPubSubListeners(type: PubSubType) { return this._self.#queue.getPubSubListeners(type); } @@ -781,10 +813,23 @@ export default class RedisClient< commands: Array, selectedDB?: number ) { + const dirtyWatch = this._self.#dirtyWatch; + this._self.#dirtyWatch = undefined; + const watchEpoch = this._self.#watchEpoch; + this._self.#watchEpoch = undefined; + if (!this._self.#socket.isOpen) { throw new ClientClosedError(); } + if (dirtyWatch) { + throw new WatchError(dirtyWatch); + } + + if (watchEpoch && watchEpoch !== this._self.#epoch) { + throw new WatchError('Client reconnected after WATCH'); + } + const typeMapping = this._commandOptions?.typeMapping, chainId = Symbol('MULTI Chain'), promises = [ @@ -910,6 +955,8 @@ export default class RedisClient< await Promise.all(promises); this._self.#selectedDB = selectedDB; this._self.#monitorCallback = undefined; + this._self.#dirtyWatch = undefined; + this._self.#watchEpoch = undefined; } /** @@ -934,6 +981,11 @@ export default class RedisClient< shouldReset = true; } + if (this._self.#dirtyWatch || this._self.#watchEpoch) { + console.warn('Returning a client with active WATCH'); + shouldReset = true; + } + if (shouldReset) { return this.reset(); } diff --git a/packages/client/lib/client/pub-sub.spec.ts b/packages/client/lib/client/pub-sub.spec.ts index 65152909325..74bd85c1831 100644 --- a/packages/client/lib/client/pub-sub.spec.ts +++ b/packages/client/lib/client/pub-sub.spec.ts @@ -1,151 +1,151 @@ import { strict as assert } from 'node:assert'; -import { PubSub, PubSubType } from './pub-sub'; +import { PubSub, PUBSUB_TYPE } from './pub-sub'; describe('PubSub', () => { - const TYPE = PubSubType.CHANNELS, - CHANNEL = 'channel', - LISTENER = () => {}; - - describe('subscribe to new channel', () => { - function createAndSubscribe() { - const pubSub = new PubSub(), - command = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - - assert.equal(pubSub.isActive, true); - assert.ok(command); - assert.equal(command.channelsCounter, 1); - - return { - pubSub, - command - }; - } - - it('resolve', () => { - const { pubSub, command } = createAndSubscribe(); - - command.resolve(); - - assert.equal(pubSub.isActive, true); - }); - - it('reject', () => { - const { pubSub, command } = createAndSubscribe(); - - assert.ok(command.reject); - command.reject(); - - assert.equal(pubSub.isActive, false); - }); + const TYPE = PUBSUB_TYPE.CHANNELS, + CHANNEL = 'channel', + LISTENER = () => {}; + + describe('subscribe to new channel', () => { + function createAndSubscribe() { + const pubSub = new PubSub(), + command = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + + assert.equal(pubSub.isActive, true); + assert.ok(command); + assert.equal(command.channelsCounter, 1); + + return { + pubSub, + command + }; + } + + it('resolve', () => { + const { pubSub, command } = createAndSubscribe(); + + command.resolve(); + + assert.equal(pubSub.isActive, true); }); - it('subscribe to already subscribed channel', () => { - const pubSub = new PubSub(), - firstSubscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(firstSubscribe); + it('reject', () => { + const { pubSub, command } = createAndSubscribe(); - const secondSubscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(secondSubscribe); + assert.ok(command.reject); + command.reject(); - firstSubscribe.resolve(); + assert.equal(pubSub.isActive, false); + }); + }); + + it('subscribe to already subscribed channel', () => { + const pubSub = new PubSub(), + firstSubscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(firstSubscribe); + + const secondSubscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(secondSubscribe); + + firstSubscribe.resolve(); + + assert.equal( + pubSub.subscribe(TYPE, CHANNEL, LISTENER), + undefined + ); + }); + + it('unsubscribe all', () => { + const pubSub = new PubSub(); + + const subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(subscribe); + subscribe.resolve(); + assert.equal(pubSub.isActive, true); + + const unsubscribe = pubSub.unsubscribe(TYPE); + assert.equal(pubSub.isActive, true); + assert.ok(unsubscribe); + unsubscribe.resolve(); + assert.equal(pubSub.isActive, false); + }); + + describe('unsubscribe from channel', () => { + it('when not subscribed', () => { + const pubSub = new PubSub(), + unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL); + assert.ok(unsubscribe); + unsubscribe.resolve(); + assert.equal(pubSub.isActive, false); + }); - assert.equal( - pubSub.subscribe(TYPE, CHANNEL, LISTENER), - undefined - ); + it('when already subscribed', () => { + const pubSub = new PubSub(), + subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(subscribe); + subscribe.resolve(); + assert.equal(pubSub.isActive, true); + + const unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL); + assert.equal(pubSub.isActive, true); + assert.ok(unsubscribe); + unsubscribe.resolve(); + assert.equal(pubSub.isActive, false); + }); + }); + + describe('unsubscribe from listener', () => { + it('when it\'s the only listener', () => { + const pubSub = new PubSub(), + subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(subscribe); + subscribe.resolve(); + assert.equal(pubSub.isActive, true); + + const unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL, LISTENER); + assert.ok(unsubscribe); + unsubscribe.resolve(); + assert.equal(pubSub.isActive, false); }); - it('unsubscribe all', () => { - const pubSub = new PubSub(); - - const subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + it('when there are more listeners', () => { + const pubSub = new PubSub(), + subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); + assert.ok(subscribe); + subscribe.resolve(); + assert.equal(pubSub.isActive, true); + + assert.equal( + pubSub.subscribe(TYPE, CHANNEL, () => { }), + undefined + ); + + assert.equal( + pubSub.unsubscribe(TYPE, CHANNEL, LISTENER), + undefined + ); + }); + + describe('non-existing listener', () => { + it('on subscribed channel', () => { + const pubSub = new PubSub(), + subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); assert.ok(subscribe); subscribe.resolve(); assert.equal(pubSub.isActive, true); - const unsubscribe = pubSub.unsubscribe(TYPE); + assert.equal( + pubSub.unsubscribe(TYPE, CHANNEL, () => { }), + undefined + ); assert.equal(pubSub.isActive, true); - assert.ok(unsubscribe); - unsubscribe.resolve(); - assert.equal(pubSub.isActive, false); - }); - - describe('unsubscribe from channel', () => { - it('when not subscribed', () => { - const pubSub = new PubSub(), - unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL); - assert.ok(unsubscribe); - unsubscribe.resolve(); - assert.equal(pubSub.isActive, false); - }); - - it('when already subscribed', () => { - const pubSub = new PubSub(), - subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(subscribe); - subscribe.resolve(); - assert.equal(pubSub.isActive, true); - - const unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL); - assert.equal(pubSub.isActive, true); - assert.ok(unsubscribe); - unsubscribe.resolve(); - assert.equal(pubSub.isActive, false); - }); - }); + }); - describe('unsubscribe from listener', () => { - it('when it\'s the only listener', () => { - const pubSub = new PubSub(), - subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(subscribe); - subscribe.resolve(); - assert.equal(pubSub.isActive, true); - - const unsubscribe = pubSub.unsubscribe(TYPE, CHANNEL, LISTENER); - assert.ok(unsubscribe); - unsubscribe.resolve(); - assert.equal(pubSub.isActive, false); - }); - - it('when there are more listeners', () => { - const pubSub = new PubSub(), - subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(subscribe); - subscribe.resolve(); - assert.equal(pubSub.isActive, true); - - assert.equal( - pubSub.subscribe(TYPE, CHANNEL, () => {}), - undefined - ); - - assert.equal( - pubSub.unsubscribe(TYPE, CHANNEL, LISTENER), - undefined - ); - }); - - describe('non-existing listener', () => { - it('on subscribed channel', () => { - const pubSub = new PubSub(), - subscribe = pubSub.subscribe(TYPE, CHANNEL, LISTENER); - assert.ok(subscribe); - subscribe.resolve(); - assert.equal(pubSub.isActive, true); - - assert.equal( - pubSub.unsubscribe(TYPE, CHANNEL, () => {}), - undefined - ); - assert.equal(pubSub.isActive, true); - }); - - it('on unsubscribed channel', () => { - const pubSub = new PubSub(); - assert.ok(pubSub.unsubscribe(TYPE, CHANNEL, () => {})); - assert.equal(pubSub.isActive, false); - }); - }); + it('on unsubscribed channel', () => { + const pubSub = new PubSub(); + assert.ok(pubSub.unsubscribe(TYPE, CHANNEL, () => { })); + assert.equal(pubSub.isActive, false); + }); }); + }); }); diff --git a/packages/client/lib/client/pub-sub.ts b/packages/client/lib/client/pub-sub.ts index aedbaf68d65..1387aea8417 100644 --- a/packages/client/lib/client/pub-sub.ts +++ b/packages/client/lib/client/pub-sub.ts @@ -1,24 +1,28 @@ import { RedisArgument } from '../RESP/types'; import { CommandToWrite } from './commands-queue'; -export enum PubSubType { - CHANNELS = 'CHANNELS', - PATTERNS = 'PATTERNS', - SHARDED = 'SHARDED' -} +export const PUBSUB_TYPE = { + CHANNELS: 'CHANNELS', + PATTERNS: 'PATTERNS', + SHARDED: 'SHARDED' +} as const; + +export type PUBSUB_TYPE = typeof PUBSUB_TYPE; + +export type PubSubType = PUBSUB_TYPE[keyof PUBSUB_TYPE]; const COMMANDS = { - [PubSubType.CHANNELS]: { + [PUBSUB_TYPE.CHANNELS]: { subscribe: Buffer.from('subscribe'), unsubscribe: Buffer.from('unsubscribe'), message: Buffer.from('message') }, - [PubSubType.PATTERNS]: { + [PUBSUB_TYPE.PATTERNS]: { subscribe: Buffer.from('psubscribe'), unsubscribe: Buffer.from('punsubscribe'), message: Buffer.from('pmessage') }, - [PubSubType.SHARDED]: { + [PUBSUB_TYPE.SHARDED]: { subscribe: Buffer.from('ssubscribe'), unsubscribe: Buffer.from('sunsubscribe'), message: Buffer.from('smessage') @@ -37,7 +41,7 @@ export interface ChannelListeners { export type PubSubTypeListeners = Map; -type Listeners = Record; +export type PubSubListeners = Record; export type PubSubCommand = ( Required> & { @@ -48,16 +52,16 @@ export type PubSubCommand = ( export class PubSub { static isStatusReply(reply: Array): boolean { return ( - COMMANDS[PubSubType.CHANNELS].subscribe.equals(reply[0]) || - COMMANDS[PubSubType.CHANNELS].unsubscribe.equals(reply[0]) || - COMMANDS[PubSubType.PATTERNS].subscribe.equals(reply[0]) || - COMMANDS[PubSubType.PATTERNS].unsubscribe.equals(reply[0]) || - COMMANDS[PubSubType.SHARDED].subscribe.equals(reply[0]) + COMMANDS[PUBSUB_TYPE.CHANNELS].subscribe.equals(reply[0]) || + COMMANDS[PUBSUB_TYPE.CHANNELS].unsubscribe.equals(reply[0]) || + COMMANDS[PUBSUB_TYPE.PATTERNS].subscribe.equals(reply[0]) || + COMMANDS[PUBSUB_TYPE.PATTERNS].unsubscribe.equals(reply[0]) || + COMMANDS[PUBSUB_TYPE.SHARDED].subscribe.equals(reply[0]) ); } static isShardedUnsubscribe(reply: Array): boolean { - return COMMANDS[PubSubType.SHARDED].unsubscribe.equals(reply[0]); + return COMMANDS[PUBSUB_TYPE.SHARDED].unsubscribe.equals(reply[0]); } static #channelsArray(channels: string | Array) { @@ -79,10 +83,10 @@ export class PubSub { return this.#isActive; } - #listeners: Listeners = { - [PubSubType.CHANNELS]: new Map(), - [PubSubType.PATTERNS]: new Map(), - [PubSubType.SHARDED]: new Map() + readonly listeners: PubSubListeners = { + [PUBSUB_TYPE.CHANNELS]: new Map(), + [PUBSUB_TYPE.PATTERNS]: new Map(), + [PUBSUB_TYPE.SHARDED]: new Map() }; subscribe( @@ -94,7 +98,7 @@ export class PubSub { const args: Array = [COMMANDS[type].subscribe], channelsArray = PubSub.#channelsArray(channels); for (const channel of channelsArray) { - let channelListeners = this.#listeners[type].get(channel); + let channelListeners = this.listeners[type].get(channel); if (!channelListeners || channelListeners.unsubscribing) { args.push(channel); } @@ -104,7 +108,7 @@ export class PubSub { // all channels are already subscribed, add listeners without issuing a command for (const channel of channelsArray) { PubSub.#listenersSet( - this.#listeners[type].get(channel)!, + this.listeners[type].get(channel)!, returnBuffers ).add(listener); } @@ -119,14 +123,14 @@ export class PubSub { resolve: () => { this.#subscribing--; for (const channel of channelsArray) { - let listeners = this.#listeners[type].get(channel); + let listeners = this.listeners[type].get(channel); if (!listeners) { listeners = { unsubscribing: false, buffers: new Set(), strings: new Set() }; - this.#listeners[type].set(channel, listeners); + this.listeners[type].set(channel, listeners); } PubSub.#listenersSet(listeners, returnBuffers).add(listener); @@ -167,9 +171,9 @@ export class PubSub { channel: string, listeners: ChannelListeners ) { - const existingListeners = this.#listeners[type].get(channel); + const existingListeners = this.listeners[type].get(channel); if (!existingListeners) { - this.#listeners[type].set(channel, listeners); + this.listeners[type].set(channel, listeners); return true; } @@ -213,7 +217,7 @@ export class PubSub { listener?: PubSubListener, returnBuffers?: T ) { - const listeners = this.#listeners[type]; + const listeners = this.listeners[type]; if (!channels) { return this.#unsubscribeCommand( [COMMANDS[type].unsubscribe], @@ -306,9 +310,9 @@ export class PubSub { #updateIsActive() { this.#isActive = ( - this.#listeners[PubSubType.CHANNELS].size !== 0 || - this.#listeners[PubSubType.PATTERNS].size !== 0 || - this.#listeners[PubSubType.SHARDED].size !== 0 || + this.listeners[PUBSUB_TYPE.CHANNELS].size !== 0 || + this.listeners[PUBSUB_TYPE.PATTERNS].size !== 0 || + this.listeners[PUBSUB_TYPE.SHARDED].size !== 0 || this.#subscribing !== 0 ); } @@ -320,7 +324,7 @@ export class PubSub { resubscribe() { const commands = []; - for (const [type, listeners] of Object.entries(this.#listeners)) { + for (const [type, listeners] of Object.entries(this.listeners)) { if (!listeners.size) continue; this.#isActive = true; @@ -341,24 +345,24 @@ export class PubSub { } handleMessageReply(reply: Array): boolean { - if (COMMANDS[PubSubType.CHANNELS].message.equals(reply[0])) { + if (COMMANDS[PUBSUB_TYPE.CHANNELS].message.equals(reply[0])) { this.#emitPubSubMessage( - PubSubType.CHANNELS, + PUBSUB_TYPE.CHANNELS, reply[2], reply[1] ); return true; - } else if (COMMANDS[PubSubType.PATTERNS].message.equals(reply[0])) { + } else if (COMMANDS[PUBSUB_TYPE.PATTERNS].message.equals(reply[0])) { this.#emitPubSubMessage( - PubSubType.PATTERNS, + PUBSUB_TYPE.PATTERNS, reply[3], reply[2], reply[1] ); return true; - } else if (COMMANDS[PubSubType.SHARDED].message.equals(reply[0])) { + } else if (COMMANDS[PUBSUB_TYPE.SHARDED].message.equals(reply[0])) { this.#emitPubSubMessage( - PubSubType.SHARDED, + PUBSUB_TYPE.SHARDED, reply[2], reply[1] ); @@ -369,8 +373,8 @@ export class PubSub { } removeShardedListeners(channel: string): ChannelListeners { - const listeners = this.#listeners[PubSubType.SHARDED].get(channel)!; - this.#listeners[PubSubType.SHARDED].delete(channel); + const listeners = this.listeners[PUBSUB_TYPE.SHARDED].get(channel)!; + this.listeners[PUBSUB_TYPE.SHARDED].delete(channel); this.#updateIsActive(); return listeners; } @@ -382,7 +386,7 @@ export class PubSub { pattern?: Buffer ): void { const keyString = (pattern ?? channel).toString(), - listeners = this.#listeners[type].get(keyString); + listeners = this.listeners[type].get(keyString); if (!listeners) return; @@ -402,8 +406,4 @@ export class PubSub { listener(messageString, channelString); } } - - getTypeListeners(type: PubSubType): PubSubTypeListeners { - return this.#listeners[type]; - } } diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 753ced6c5ed..ca75016d987 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -28,15 +28,15 @@ export interface RedisSocketCommonOptions { reconnectStrategy?: false | number | ((retries: number, cause: Error) => false | Error | number); } -type RedisNetSocketOptions = Partial & { +export interface RedisNetConnectOpts extends Omit, 'keepAlive'>, Partial, RedisSocketCommonOptions { tls?: false; }; -export interface RedisTlsSocketOptions extends tls.ConnectionOptions { +export interface RedisTlsSocketOptions extends Partial, RedisSocketCommonOptions { tls: true; -} +}; -export type RedisSocketOptions = RedisSocketCommonOptions & (RedisNetSocketOptions | RedisTlsSocketOptions); +export type RedisSocketOptions = RedisNetConnectOpts | RedisTlsSocketOptions interface CreateSocketReturn { connectEvent: string; diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index dee133176a9..f78dad984ce 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -2,7 +2,7 @@ import { RedisClusterClientOptions, RedisClusterOptions } from '.'; import { RootNodesUnavailableError } from '../errors'; import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; import { EventEmitter } from 'node:stream'; -import { ChannelListeners, PubSubType, PubSubTypeListeners } from '../client/pub-sub'; +import { ChannelListeners, PUBSUB_TYPE, PubSubTypeListeners } from '../client/pub-sub'; import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; import calculateSlot from 'cluster-key-slot'; @@ -83,7 +83,7 @@ type PubSubNode< ); type PubSubToResubscribe = Record< - PubSubType.CHANNELS | PubSubType.PATTERNS, + PUBSUB_TYPE['CHANNELS'] | PUBSUB_TYPE['PATTERNS'], PubSubTypeListeners >; @@ -186,16 +186,16 @@ export default class RedisClusterSlots< } if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { - const channelsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.CHANNELS), - patternsListeners = this.pubSubNode.client.getPubSubListeners(PubSubType.PATTERNS); + const channelsListeners = this.pubSubNode.client.getPubSubListeners(PUBSUB_TYPE.CHANNELS), + patternsListeners = this.pubSubNode.client.getPubSubListeners(PUBSUB_TYPE.PATTERNS); this.pubSubNode.client.destroy(); if (channelsListeners.size || patternsListeners.size) { promises.push( this.#initiatePubSubClient({ - [PubSubType.CHANNELS]: channelsListeners, - [PubSubType.PATTERNS]: patternsListeners + [PUBSUB_TYPE.CHANNELS]: channelsListeners, + [PUBSUB_TYPE.PATTERNS]: patternsListeners }) ); } @@ -526,8 +526,8 @@ export default class RedisClusterSlots< .then(async client => { if (toResubscribe) { await Promise.all([ - client.extendPubSubListeners(PubSubType.CHANNELS, toResubscribe[PubSubType.CHANNELS]), - client.extendPubSubListeners(PubSubType.PATTERNS, toResubscribe[PubSubType.PATTERNS]) + client.extendPubSubListeners(PUBSUB_TYPE.CHANNELS, toResubscribe[PUBSUB_TYPE.CHANNELS]), + client.extendPubSubListeners(PUBSUB_TYPE.PATTERNS, toResubscribe[PUBSUB_TYPE.PATTERNS]) ]); } @@ -568,7 +568,7 @@ export default class RedisClusterSlots< await this.rediscover(client); const redirectTo = await this.getShardedPubSubClient(channel); await redirectTo.extendPubSubChannelListeners( - PubSubType.SHARDED, + PUBSUB_TYPE.SHARDED, channel, listeners ); diff --git a/packages/client/lib/commands/UNWATCH.spec.ts b/packages/client/lib/commands/UNWATCH.spec.ts deleted file mode 100644 index 2aeb0297e99..00000000000 --- a/packages/client/lib/commands/UNWATCH.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { strict as assert } from 'node:assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import UNWATCH from './UNWATCH'; - -describe('UNWATCH', () => { - it('transformArguments', () => { - assert.deepEqual( - UNWATCH.transformArguments(), - ['UNWATCH'] - ); - }); - - testUtils.testWithClient('client.unwatch', async client => { - assert.equal( - await client.unwatch(), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); -}); diff --git a/packages/client/lib/commands/UNWATCH.ts b/packages/client/lib/commands/UNWATCH.ts deleted file mode 100644 index d12e9c2b949..00000000000 --- a/packages/client/lib/commands/UNWATCH.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { SimpleStringReply, Command } from '../RESP/types'; - -export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, - transformArguments() { - return ['UNWATCH']; - }, - transformReply: undefined as unknown as () => SimpleStringReply -} as const satisfies Command; diff --git a/packages/client/lib/commands/WATCH.spec.ts b/packages/client/lib/commands/WATCH.spec.ts deleted file mode 100644 index c3069fd6200..00000000000 --- a/packages/client/lib/commands/WATCH.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { strict as assert } from 'node:assert'; -import WATCH from './WATCH'; - -describe('WATCH', () => { - describe('transformArguments', () => { - it('string', () => { - assert.deepEqual( - WATCH.transformArguments('key'), - ['WATCH', 'key'] - ); - }); - - it('array', () => { - assert.deepEqual( - WATCH.transformArguments(['1', '2']), - ['WATCH', '1', '2'] - ); - }); - }); -}); diff --git a/packages/client/lib/commands/WATCH.ts b/packages/client/lib/commands/WATCH.ts deleted file mode 100644 index 339642bf991..00000000000 --- a/packages/client/lib/commands/WATCH.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { SimpleStringReply, Command } from '../RESP/types'; -import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers'; - -export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, - transformArguments(key: RedisVariadicArgument) { - return pushVariadicArguments(['WATCH'], key); - }, - transformReply: undefined as unknown as () => SimpleStringReply -} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index 804277b4ae3..b2898988386 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -265,9 +265,7 @@ import TOUCH from './TOUCH'; import TTL from './TTL'; import TYPE from './TYPE'; import UNLINK from './UNLINK'; -import UNWATCH from './UNWATCH'; import WAIT from './WAIT'; -import WATCH from './WATCH'; import XACK from './XACK'; import XADD_NOMKSTREAM from './XADD_NOMKSTREAM'; import XADD from './XADD'; @@ -869,12 +867,8 @@ export default { type: TYPE, UNLINK, unlink: UNLINK, - UNWATCH, - unwatch: UNWATCH, WAIT, wait: WAIT, - WATCH, - watch: WATCH, XACK, xAck: XACK, XADD_NOMKSTREAM, diff --git a/packages/client/lib/errors.ts b/packages/client/lib/errors.ts index b7345ac76e9..8af4c5e5bed 100644 --- a/packages/client/lib/errors.ts +++ b/packages/client/lib/errors.ts @@ -5,8 +5,8 @@ export class AbortError extends Error { } export class WatchError extends Error { - constructor() { - super('One (or more) of the watched keys has been changed'); + constructor(message = 'One (or more) of the watched keys has been changed') { + super(message); } } diff --git a/packages/client/lib/sentinel/commands/SENTINEL_MASTER.ts b/packages/client/lib/sentinel/commands/SENTINEL_MASTER.ts new file mode 100644 index 00000000000..25217c85d40 --- /dev/null +++ b/packages/client/lib/sentinel/commands/SENTINEL_MASTER.ts @@ -0,0 +1,12 @@ +import { RedisArgument, MapReply, BlobStringReply, Command } from '../../RESP/types'; +import { transformTuplesReply } from '../../commands/generic-transformers'; + +export default { + transformArguments(dbname: RedisArgument) { + return ['SENTINEL', 'MASTER', dbname]; + }, + transformReply: { + 2: transformTuplesReply, + 3: undefined as unknown as () => MapReply + } +} as const satisfies Command; diff --git a/packages/client/lib/sentinel/commands/SENTINEL_MONITOR.ts b/packages/client/lib/sentinel/commands/SENTINEL_MONITOR.ts new file mode 100644 index 00000000000..14caecd924a --- /dev/null +++ b/packages/client/lib/sentinel/commands/SENTINEL_MONITOR.ts @@ -0,0 +1,8 @@ +import { RedisArgument, SimpleStringReply, Command } from '../../RESP/types'; + +export default { + transformArguments(dbname: RedisArgument, host: RedisArgument, port: RedisArgument, quorum: RedisArgument) { + return ['SENTINEL', 'MONITOR', dbname, host, port, quorum]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/sentinel/commands/SENTINEL_REPLICAS.ts b/packages/client/lib/sentinel/commands/SENTINEL_REPLICAS.ts new file mode 100644 index 00000000000..cba2cdf724e --- /dev/null +++ b/packages/client/lib/sentinel/commands/SENTINEL_REPLICAS.ts @@ -0,0 +1,15 @@ +import { RedisArgument, ArrayReply, BlobStringReply, MapReply, Command } from '../../RESP/types'; +import { transformTuplesReply } from '../../commands/generic-transformers'; + +export default { + transformArguments(dbname: RedisArgument) { + return ['SENTINEL', 'REPLICAS', dbname]; + }, + transformReply: { + 2: (reply: any) => { + const initial: Array> = []; + return reply.reduce((sentinels: Array>, x: any) => { sentinels.push(transformTuplesReply(x)); return sentinels }, initial); + }, + 3: undefined as unknown as () => ArrayReply> + } +} as const satisfies Command; diff --git a/packages/client/lib/sentinel/commands/SENTINEL_SENTINELS.ts b/packages/client/lib/sentinel/commands/SENTINEL_SENTINELS.ts new file mode 100644 index 00000000000..4e97218a300 --- /dev/null +++ b/packages/client/lib/sentinel/commands/SENTINEL_SENTINELS.ts @@ -0,0 +1,15 @@ +import { RedisArgument, ArrayReply, MapReply, BlobStringReply, Command } from '../../RESP/types'; +import { transformTuplesReply } from '../../commands/generic-transformers'; + +export default { + transformArguments(dbname: RedisArgument) { + return ['SENTINEL', 'SENTINELS', dbname]; + }, + transformReply: { + 2: (reply: any) => { + const initial: Array> = []; + return reply.reduce((sentinels: Array>, x: any) => { sentinels.push(transformTuplesReply(x)); return sentinels }, initial); + }, + 3: undefined as unknown as () => ArrayReply> + } +} as const satisfies Command; diff --git a/packages/client/lib/sentinel/commands/SENTINEL_SET.ts b/packages/client/lib/sentinel/commands/SENTINEL_SET.ts new file mode 100644 index 00000000000..41037819869 --- /dev/null +++ b/packages/client/lib/sentinel/commands/SENTINEL_SET.ts @@ -0,0 +1,19 @@ +import { RedisArgument, SimpleStringReply, Command } from '../../RESP/types'; + +export type SentinelSetOptions = Array<{ + option: RedisArgument; + value: RedisArgument; +}>; + +export default { + transformArguments(dbname: RedisArgument, options: SentinelSetOptions) { + const args = ['SENTINEL', 'SET', dbname]; + + for (const option of options) { + args.push(option.option, option.value); + } + + return args; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/client/lib/sentinel/commands/index.ts b/packages/client/lib/sentinel/commands/index.ts new file mode 100644 index 00000000000..1fc16f872f6 --- /dev/null +++ b/packages/client/lib/sentinel/commands/index.ts @@ -0,0 +1,19 @@ +import { RedisCommands } from '../../RESP/types'; +import SENTINEL_MASTER from './SENTINEL_MASTER'; +import SENTINEL_MONITOR from './SENTINEL_MONITOR'; +import SENTINEL_REPLICAS from './SENTINEL_REPLICAS'; +import SENTINEL_SENTINELS from './SENTINEL_SENTINELS'; +import SENTINEL_SET from './SENTINEL_SET'; + +export default { + SENTINEL_SENTINELS, + sentinelSentinels: SENTINEL_SENTINELS, + SENTINEL_MASTER, + sentinelMaster: SENTINEL_MASTER, + SENTINEL_REPLICAS, + sentinelReplicas: SENTINEL_REPLICAS, + SENTINEL_MONITOR, + sentinelMonitor: SENTINEL_MONITOR, + SENTINEL_SET, + sentinelSet: SENTINEL_SET +} as const satisfies RedisCommands; diff --git a/packages/client/lib/sentinel/index.spec.ts b/packages/client/lib/sentinel/index.spec.ts new file mode 100644 index 00000000000..a7238a5fdfd --- /dev/null +++ b/packages/client/lib/sentinel/index.spec.ts @@ -0,0 +1,1274 @@ +import { strict as assert } from 'node:assert'; +import { setTimeout } from 'node:timers/promises'; +import { WatchError } from "../errors"; +import { RedisSentinelConfig, SentinelFramework } from "./test-util"; +import { RedisNode, RedisSentinelClientType, RedisSentinelEvent, RedisSentinelType } from "./types"; +import { RedisSentinelFactory } from '.'; +import { RedisClientType } from '../client'; +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping, NumberReply } from '../RESP/types'; + +import { promisify } from 'node:util'; +import { exec } from 'node:child_process'; +import { RESP_TYPES } from '../RESP/decoder'; +import { defineScript } from '../lua-script'; +import { MATH_FUNCTION } from '../commands/FUNCTION_LOAD.spec'; +import RedisBloomModules from '@redis/bloom'; + +const execAsync = promisify(exec); + +const SQUARE_SCRIPT = defineScript({ + SCRIPT: + `local number = redis.call('GET', KEYS[1]) + return number * number`, + NUMBER_OF_KEYS: 1, + FIRST_KEY_INDEX: 0, + transformArguments(key: string) { + return [key]; + }, + transformReply: undefined as unknown as () => NumberReply +}); + +/* used to ensure test environment resets to normal state + i.e. + - all redis nodes are active and are part of the topology + before allowing things to continue. +*/ + +async function steadyState(frame: SentinelFramework) { + let checkedMaster = false; + let checkedReplicas = false; + while (!checkedMaster || !checkedReplicas) { + if (!checkedMaster) { + const master = await frame.sentinelMaster(); + if (master?.flags === 'master') { + checkedMaster = true; + } + } + + if (!checkedReplicas) { + const replicas = (await frame.sentinelReplicas()) as Array; + checkedReplicas = true; + for (const replica of replicas) { + checkedReplicas &&= (replica.flags === 'slave'); + } + } + } + + let nodeResolve, nodeReject; + const nodePromise = new Promise((res, rej) => { + nodeResolve = res; + nodeReject = rej; + }) + + const seenNodes = new Set(); + let sentinel: RedisSentinelType | undefined; + const tracer = []; + + try { + sentinel = frame.getSentinelClient({ replicaPoolSize: 1, scanInterval: 2000 }, false) + .on('topology-change', (event: RedisSentinelEvent) => { + if (event.type == "MASTER_CHANGE" || event.type == "REPLICA_ADD") { + seenNodes.add(event.node.port); + if (seenNodes.size == frame.getAllNodesPort().length) { + nodeResolve(); + } + } + }).on('error', err => { }); + sentinel.setTracer(tracer); + await sentinel.connect(); + + await nodePromise; + + await sentinel.flushAll(); + } finally { + if (sentinel !== undefined) { + sentinel.destroy(); + } + } +} + +["redis-sentinel-test-password", undefined].forEach(function (password) { + describe.only(`Sentinel - password = ${password}`, () => { + const config: RedisSentinelConfig = { sentinelName: "test", numberOfNodes: 3, password: password }; + const frame = new SentinelFramework(config); + let tracer = new Array(); + let stopMeasuringBlocking = false; + let longestDelta = 0; + let longestTestDelta = 0; + let last: number; + + before(async function () { + this.timeout(15000); + + last = Date.now(); + + function deltaMeasurer() { + const delta = Date.now() - last; + if (delta > longestDelta) { + longestDelta = delta; + } + if (delta > longestTestDelta) { + longestTestDelta = delta; + } + if (!stopMeasuringBlocking) { + last = Date.now(); + setImmediate(deltaMeasurer); + } + } + + setImmediate(deltaMeasurer); + + await frame.spawnRedisSentinel(); + }); + + after(async function () { + this.timeout(15000); + + stopMeasuringBlocking = true; + + await frame.cleanup(); + }) + + describe('Sentinel Client', function () { + let sentinel: RedisSentinelType< RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping> | undefined; + + beforeEach(async function () { + this.timeout(0); + + await frame.getAllRunning(); + + await steadyState(frame); + longestTestDelta = 0; + }) + + afterEach(async function () { + this.timeout(30000); + + // avoid errors in afterEach that end testing + if (sentinel !== undefined) { + sentinel.on('error', () => { }); + } + + if (this!.currentTest!.state === 'failed') { + console.log(`longest event loop blocked delta: ${longestDelta}`); + console.log(`longest event loop blocked in failing test: ${longestTestDelta}`); + console.log("trace:"); + for (const line of tracer) { + console.log(line); + } + console.log(`sentinel object state:`) + console.log(`master: ${JSON.stringify(sentinel?.getMasterNode())}`) + console.log(`replicas: ${JSON.stringify(sentinel?.getReplicaNodes().entries)}`) + const results = await Promise.all([ + frame.sentinelSentinels(), + frame.sentinelMaster(), + frame.sentinelReplicas() + ]) + console.log(`sentinel sentinels:\n${JSON.stringify(results[0], undefined, '\t')}`); + console.log(`sentinel master:\n${JSON.stringify(results[1], undefined, '\t')}`); + console.log(`sentinel replicas:\n${JSON.stringify(results[2], undefined, '\t')}`); + const { stdout, stderr } = await execAsync("docker ps -a"); + console.log(`docker stdout:\n${stdout}`); + + const ids = frame.getAllDockerIds(); + console.log("docker logs"); + + for (const [id, port] of ids) { + console.log(`${id}/${port}\n`); + const { stdout, stderr } = await execAsync(`docker logs ${id}`, {maxBuffer: 8192 * 8192 * 4}); + console.log(stdout); + } + } + tracer.length = 0; + + if (sentinel !== undefined) { + await sentinel.destroy(); + sentinel = undefined; + } + }) + + it('basic bootstrap', async function () { + sentinel = frame.getSentinelClient(); + await sentinel.connect(); + + await assert.doesNotReject(sentinel.set('x', 1)); + + }); + + it('basic teardown worked', async function () { + const nodePorts = frame.getAllNodesPort(); + const sentinelPorts = frame.getAllSentinelsPort(); + + assert.notEqual(nodePorts.length, 0); + assert.notEqual(sentinelPorts.length, 0); + + sentinel = frame.getSentinelClient(); + await sentinel.connect(); + + await assert.doesNotReject(sentinel.get('x')); + }); + + it('try to connect multiple times', async function () { + sentinel = frame.getSentinelClient(); + const connectPromise = sentinel.connect(); + await assert.rejects(sentinel.connect()); + await connectPromise; + }); + + it('with type mapping', async function () { + const commandOptions = { + typeMapping: { + [RESP_TYPES.SIMPLE_STRING]: Buffer + } + } + sentinel = frame.getSentinelClient({ commandOptions: commandOptions }); + await sentinel.connect(); + + const resp = await sentinel.ping(); + assert.deepEqual(resp, Buffer.from('PONG')) + }) + + it('with a script', async function () { + const options = { + scripts: { + square: SQUARE_SCRIPT + } + } + + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const [, reply] = await Promise.all([ + sentinel.set('key', '2'), + sentinel.square('key') + ]); + + assert.equal(reply, 4); + }) + + it('multi with a script', async function () { + const options = { + scripts: { + square: SQUARE_SCRIPT + } + } + + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const reply = await sentinel.multi().set('key', 2).square('key').exec(); + + assert.deepEqual(reply, ['OK', 4]); + }) + + it('with a function', async function () { + const options = { + functions: { + math: MATH_FUNCTION.library + } + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + await sentinel.functionLoad( + MATH_FUNCTION.code, + { REPLACE: true } + ); + + await sentinel.set('key', '2'); + const resp = await sentinel.math.square('key'); + + assert.equal(resp, 4); + }) + + it('multi with a function', async function () { + const options = { + functions: { + math: MATH_FUNCTION.library + } + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + await sentinel.functionLoad( + MATH_FUNCTION.code, + { REPLACE: true } + ); + + const reply = await sentinel.multi().set('key', 2).math.square('key').exec(); + assert.deepEqual(reply, ['OK', 4]); + }) + + it('with a module', async function () { + const options = { + modules: RedisBloomModules + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const resp = await sentinel.bf.add('key', 'item') + assert.equal(resp, true); + }) + + it('multi with a module', async function () { + const options = { + modules: RedisBloomModules + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const resp = await sentinel.multi().bf.add('key', 'item').exec(); + assert.deepEqual(resp, [true]); + }) + + it('many readers', async function () { + this.timeout(10000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 8 }); + await sentinel.connect(); + + await sentinel.set("x", 1); + for (let i = 0; i < 10; i++) { + if (await sentinel.get("x") == "1") { + break; + } + await setTimeout(1000); + } + + const promises: Array> = []; + for (let i = 0; i < 500; i++) { + promises.push(sentinel.get("x")); + } + + const resp = await Promise.all(promises); + assert.equal(resp.length, 500); + for (let i = 0; i < 500; i++) { + assert.equal(resp[i], "1", `failed on match at ${i}`); + } + }); + + it('use', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 1 }); + sentinel.on("error", () => { }); + await sentinel.connect(); + + await sentinel.use( + async (client: RedisSentinelClientType, ) => { + const masterNode = sentinel!.getMasterNode(); + await frame.stopNode(masterNode!.port.toString()); + await assert.doesNotReject(client.get('x')); + } + ); + }); + + it('use with script', async function () { + this.timeout(10000); + + const options = { + scripts: { + square: SQUARE_SCRIPT + } + } + + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const reply = await sentinel.use( + async (client: RedisSentinelClientType) => { + assert.equal(await client.set('key', '2'), 'OK'); + assert.equal(await client.get('key'), '2'); + return client.square('key') + } + ); + + assert.equal(reply, 4); + }) + + it('use with a function', async function () { + this.timeout(10000); + + const options = { + functions: { + math: MATH_FUNCTION.library + } + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + await sentinel.functionLoad( + MATH_FUNCTION.code, + { REPLACE: true } + ); + + const reply = await sentinel.use( + async (client: RedisSentinelClientType) => { + await client.set('key', '2'); + return client.math.square('key'); + } + ); + + assert.equal(reply, 4); + }) + + it('use with a module', async function () { + const options = { + modules: RedisBloomModules + } + sentinel = frame.getSentinelClient(options); + await sentinel.connect(); + + const reply = await sentinel.use( + async (client: RedisSentinelClientType) => { + return client.bf.add('key', 'item'); + } + ); + + assert.equal(reply, true); + }) + + it('block on pool', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 1 }); + sentinel.on("error", () => { }); + await sentinel.connect(); + + const promise = sentinel.use( + async client => { + await setTimeout(1000); + return await client.get("x"); + } + ) + + await sentinel.set("x", 1); + assert.equal(await promise, null); + }); + + it('reserve client, takes a client out of pool', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2, reserveClient: true }); + await sentinel.connect(); + + const promise1 = sentinel.use( + async client => { + const val = await client.get("x"); + await client.set("x", 2); + return val; + } + ) + + const promise2 = sentinel.use( + async client => { + return client.get("x"); + } + ) + + await sentinel.set("x", 1); + assert.equal(await promise1, "1"); + assert.equal(await promise2, "2"); + }) + + it('multiple clients', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + sentinel.on("error", () => { }); + await sentinel.connect(); + + let set = false; + + const promise = sentinel.use( + async client => { + await sentinel!.set("x", 1); + await client.get("x"); + } + ) + + await assert.doesNotReject(promise); + }); + + // by taking a lease, we know we will block on master as no clients are available, but as read occuring, means replica read occurs + it('replica reads', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 1 }); + sentinel.on("error", () => { }); + await sentinel.connect(); + + const clientLease = await sentinel.aquire(); + clientLease.set('x', 456); + + let matched = false; + /* waits for replication */ + for (let i = 0; i < 15; i++) { + try { + assert.equal(await sentinel.get("x"), '456'); + matched = true; + break; + } catch (err) { + await setTimeout(1000); + } + } + + clientLease.release(); + + assert.equal(matched, true); + }); + + it('pipeline', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 1 }); + await sentinel.connect(); + + const resp = await sentinel.multi().set('x', 1).get('x').execAsPipeline(); + + assert.deepEqual(resp, ['OK', '1']); + }) + + it('use - watch - clean', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + await sentinel.connect(); + + let promise = sentinel.use(async (client) => { + await client.set("x", 1); + await client.watch("x"); + return client.multi().get("x").exec(); + }); + + assert.deepEqual(await promise, ['1']); + }); + + it('use - watch - dirty', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + await sentinel.connect(); + + let promise = sentinel.use(async (client) => { + await client.set('x', 1); + await client.watch('x'); + await sentinel!.set('x', 2); + return client.multi().get('x').exec(); + }); + + await assert.rejects(promise, new WatchError()); + }); + + it('lease - watch - clean', async function () { + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + await sentinel.connect(); + + const leasedClient = await sentinel.aquire(); + await leasedClient.set('x', 1); + await leasedClient.watch('x'); + assert.deepEqual(await leasedClient.multi().get('x').exec(), ['1']) + }); + + it('lease - watch - dirty', async function () { + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + await sentinel.connect(); + + const leasedClient = await sentinel.aquire(); + await leasedClient.set('x', 1); + await leasedClient.watch('x'); + await leasedClient.set('x', 2); + + await assert.rejects(leasedClient.multi().get('x').exec(), new WatchError()); + }); + + + it('watch does not carry through leases', async function () { + this.timeout(10000); + sentinel = frame.getSentinelClient(); + await sentinel.connect(); + + // each of these commands is an independent lease + assert.equal(await sentinel.use(client => client.watch("x")), 'OK') + assert.equal(await sentinel.use(client => client.set('x', 1)), 'OK'); + assert.deepEqual(await sentinel.use(client => client.multi().get('x').exec()), ['1']); + }); + + // stops master to force sentinel to update + it('stop master', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + + tracer.push(`connected`); + + let masterChangeResolve; + const masterChangePromise = new Promise((res) => { + masterChangeResolve = res; + }) + + const masterNode = await sentinel.getMasterNode(); + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + tracer.push(`got expected master change event`); + masterChangeResolve(event.node); + } + }); + + tracer.push(`stopping master node`); + await frame.stopNode(masterNode!.port.toString()); + tracer.push(`stopped master node`); + + tracer.push(`waiting on master change promise`); + const newMaster = await masterChangePromise as RedisNode; + tracer.push(`got new master node of ${newMaster.port}`); + assert.notEqual(masterNode!.port, newMaster.port); + }); + + // if master changes, client should make sure user knows watches are invalid + it('watch across master change', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + + tracer.push("connected"); + + const client = await sentinel.aquire(); + tracer.push("aquired lease"); + + await client.set("x", 1); + await client.watch("x"); + + tracer.push("did a watch on lease"); + + let resolve; + const promise = new Promise((res) => { + resolve = res; + }) + + const masterNode = sentinel.getMasterNode(); + tracer.push(`got masterPort as ${masterNode!.port}`); + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + tracer.push("resolving promise"); + resolve(event.node); + } + }); + + tracer.push("stopping master node"); + await frame.stopNode(masterNode!.port.toString()); + tracer.push("stopped master node and waiting on promise"); + + const newMaster = await promise as RedisNode; + tracer.push(`promise returned, newMaster = ${JSON.stringify(newMaster)}`); + assert.notEqual(masterNode!.port, newMaster.port); + tracer.push(`newMaster does not equal old master`); + + tracer.push(`waiting to assert that a multi/exec now fails`); + await assert.rejects(async () => { await client.multi().get("x").exec() }, new Error("sentinel config changed in middle of a WATCH Transaction")); + tracer.push(`asserted that a multi/exec now fails`); + }); + + // same as above, but set a watch before and after master change, shouldn't change the fact that watches are invalid + it('watch before and after master change', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ masterPoolSize: 2 }); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + tracer.push("connected"); + + const client = await sentinel.aquire(); + tracer.push("got leased client"); + await client.set("x", 1); + await client.watch("x"); + + tracer.push("set and watched x"); + + let resolve; + const promise = new Promise((res) => { + resolve = res; + }) + + const masterNode = sentinel.getMasterNode(); + tracer.push(`initial masterPort = ${masterNode!.port} `); + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + tracer.push("got a master change event that is not the same as before"); + resolve(event.node); + } + }); + + tracer.push("stopping master"); + await frame.stopNode(masterNode!.port.toString()); + tracer.push("stopped master"); + + tracer.push("waiting on master change promise"); + const newMaster = await promise as RedisNode; + tracer.push(`got master change port as ${newMaster.port}`); + assert.notEqual(masterNode!.port, newMaster.port); + + tracer.push("watching again, shouldn't matter"); + await client.watch("y"); + + tracer.push("expecting multi to be rejected"); + await assert.rejects(async () => { await client.multi().get("x").exec() }, new Error("sentinel config changed in middle of a WATCH Transaction")); + tracer.push("multi was rejected"); + }); + + it('plain pubsub - channel', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + await sentinel.connect(); + tracer.push(`connected`); + + let pubSubResolve; + const pubSubPromise = new Promise((res) => { + pubSubResolve = res; + }); + + let tester = false; + await sentinel.subscribe('test', () => { + tracer.push(`got pubsub message`); + tester = true; + pubSubResolve(1); + }) + + tracer.push(`publishing pubsub message`); + await sentinel.publish('test', 'hello world'); + tracer.push(`waiting on pubsub promise`); + await pubSubPromise; + tracer.push(`got pubsub promise`); + assert.equal(tester, true); + + // now unsubscribe + tester = false + tracer.push(`unsubscribing pubsub listener`); + await sentinel.unsubscribe('test') + tracer.push(`pubishing pubsub message`); + await sentinel.publish('test', 'hello world'); + await setTimeout(1000); + + tracer.push(`ensuring pubsub was unsubscribed via an assert`); + assert.equal(tester, false); + }); + + it('plain pubsub - pattern', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + await sentinel.connect(); + tracer.push(`connected`); + + let pubSubResolve; + const pubSubPromise = new Promise((res) => { + pubSubResolve = res; + }); + + let tester = false; + await sentinel.pSubscribe('test*', () => { + tracer.push(`got pubsub message`); + tester = true; + pubSubResolve(1); + }) + + tracer.push(`publishing pubsub message`); + await sentinel.publish('testy', 'hello world'); + tracer.push(`waiting on pubsub promise`); + await pubSubPromise; + tracer.push(`got pubsub promise`); + assert.equal(tester, true); + + // now unsubscribe + tester = false + tracer.push(`unsubscribing pubsub listener`); + await sentinel.pUnsubscribe('test*'); + tracer.push(`pubishing pubsub message`); + await sentinel.publish('testy', 'hello world'); + await setTimeout(1000); + + tracer.push(`ensuring pubsub was unsubscribed via an assert`); + assert.equal(tester, false); + }); + + // pubsub continues to work, even with a master change + it('pubsub - channel - with master change', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + tracer.push(`connected`); + + let pubSubResolve; + const pubSubPromise = new Promise((res) => { + pubSubResolve = res; + }) + + let tester = false; + await sentinel.subscribe('test', () => { + tracer.push(`got pubsub message`); + tester = true; + pubSubResolve(1); + }) + + let masterChangeResolve; + const masterChangePromise = new Promise((res) => { + masterChangeResolve = res; + }) + + const masterNode = sentinel.getMasterNode(); + tracer.push(`got masterPort as ${masterNode!.port}`); + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + tracer.push("got a master change event that is not the same as before"); + masterChangeResolve(event.node); + } + }); + + tracer.push("stopping master"); + await frame.stopNode(masterNode!.port.toString()); + tracer.push("stopped master and waiting on change promise"); + + const newMaster = await masterChangePromise as RedisNode; + tracer.push(`got master change port as ${newMaster.port}`); + assert.notEqual(masterNode!.port, newMaster.port); + + tracer.push(`publishing pubsub message`); + await sentinel.publish('test', 'hello world'); + tracer.push(`published pubsub message and waiting pn pubsub promise`); + await pubSubPromise; + tracer.push(`got pubsub promise`); + + assert.equal(tester, true); + + // now unsubscribe + tester = false + await sentinel.unsubscribe('test') + await sentinel.publish('test', 'hello world'); + await setTimeout(1000); + + assert.equal(tester, false); + }); + + it('pubsub - pattern - with master change', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + tracer.push(`connected`); + + let pubSubResolve; + const pubSubPromise = new Promise((res) => { + pubSubResolve = res; + }) + + let tester = false; + await sentinel.pSubscribe('test*', () => { + tracer.push(`got pubsub message`); + tester = true; + pubSubResolve(1); + }) + + let masterChangeResolve; + const masterChangePromise = new Promise((res) => { + masterChangeResolve = res; + }) + + const masterNode = sentinel.getMasterNode(); + tracer.push(`got masterPort as ${masterNode!.port}`); + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + tracer.push("got a master change event that is not the same as before"); + masterChangeResolve(event.node); + } + }); + + tracer.push("stopping master"); + await frame.stopNode(masterNode!.port.toString()); + tracer.push("stopped master and waiting on master change promise"); + + const newMaster = await masterChangePromise as RedisNode; + tracer.push(`got master change port as ${newMaster.port}`); + assert.notEqual(masterNode!.port, newMaster.port); + + tracer.push(`publishing pubsub message`); + await sentinel.publish('testy', 'hello world'); + tracer.push(`published pubsub message and waiting on pubsub promise`); + await pubSubPromise; + tracer.push(`got pubsub promise`); + assert.equal(tester, true); + + // now unsubscribe + tester = false + await sentinel.pUnsubscribe('test*'); + await sentinel.publish('testy', 'hello world'); + await setTimeout(1000); + + assert.equal(tester, false); + }); + + // if we stop a node, the comand should "retry" until we reconfigure topology and execute on new topology + it('command immeaditely after stopping master', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + + tracer.push("connected"); + + let masterChangeResolve; + const masterChangePromise = new Promise((res) => { + masterChangeResolve = res; + }) + + const masterNode = sentinel.getMasterNode(); + tracer.push(`original master port = ${masterNode!.port}`); + + let changeCount = 0; + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "MASTER_CHANGE" && event.node.port != masterNode!.port) { + changeCount++; + tracer.push(`got topology-change event we expected`); + masterChangeResolve(event.node); + } + }); + + tracer.push(`stopping masterNode`); + await frame.stopNode(masterNode!.port.toString()); + tracer.push(`stopped masterNode`); + assert.equal(await sentinel.set('x', 123), 'OK'); + tracer.push(`did the set operation`); + const presumamblyNewMaster = sentinel.getMasterNode(); + tracer.push(`new master node seems to be ${presumamblyNewMaster?.port} and waiting on master change promise`); + + const newMaster = await masterChangePromise as RedisNode; + tracer.push(`got new masternode event saying master is at ${newMaster.port}`); + assert.notEqual(masterNode!.port, newMaster.port); + + tracer.push(`doing the get`); + const val = await sentinel.get('x'); + tracer.push(`did the get and got ${val}`); + const newestMaster = sentinel.getMasterNode() + tracer.push(`after get, we see master as ${newestMaster?.port}`); + + switch (changeCount) { + case 1: + // if we only changed masters once, we should have the proper value + assert.equal(val, '123'); + break; + case 2: + // we changed masters twice quickly, so probably didn't replicate + // therefore, this is soewhat flakey, but the above is the common case + assert(val == '123' || val == null); + break; + default: + assert(false, "unexpected case"); + } + }); + + it('shutdown sentinel node', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient(); + sentinel.setTracer(tracer); + sentinel.on("error", () => { }); + await sentinel.connect(); + tracer.push("connected"); + + let sentinelChangeResolve; + const sentinelChangePromise = new Promise((res) => { + sentinelChangeResolve = res; + }) + + const sentinelNode = sentinel.getSentinelNode(); + tracer.push(`sentinelNode = ${sentinelNode?.port}`) + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "SENTINEL_CHANGE") { + tracer.push("got sentinel change event"); + sentinelChangeResolve(event.node); + } + }); + + tracer.push("Stopping sentinel node"); + await frame.stopSentinel(sentinelNode!.port.toString()); + tracer.push("Stopped sentinel node and waiting on sentinel change promise"); + const newSentinel = await sentinelChangePromise as RedisNode; + tracer.push("got sentinel change promise"); + assert.notEqual(sentinelNode!.port, newSentinel.port); + }); + + it('timer works, and updates sentinel list', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ scanInterval: 1000 }); + sentinel.setTracer(tracer); + await sentinel.connect(); + tracer.push("connected"); + + let sentinelChangeResolve; + const sentinelChangePromise = new Promise((res) => { + sentinelChangeResolve = res; + }) + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "SENTINE_LIST_CHANGE" && event.size == 4) { + tracer.push(`got sentinel list change event with right size`); + sentinelChangeResolve(event.size); + } + }); + + tracer.push(`adding sentinel`); + await frame.addSentinel(); + tracer.push(`added sentinel and waiting on sentinel change promise`); + const newSentinelSize = await sentinelChangePromise as number; + + assert.equal(newSentinelSize, 4); + }); + + it('stop replica, bring back replica', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ replicaPoolSize: 1 }); + sentinel.setTracer(tracer); + sentinel.on('error', err => { }); + await sentinel.connect(); + tracer.push("connected"); + + let sentinelRemoveResolve; + const sentinelRemovePromise = new Promise((res) => { + sentinelRemoveResolve = res; + }) + + const replicaPort = await frame.getRandonNonMasterNode(); + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "REPLICA_REMOVE") { + if (event.node.port.toString() == replicaPort) { + tracer.push("got expected replica removed event"); + sentinelRemoveResolve(event.node); + } else { + tracer.push(`got replica removed event for a different node: ${event.node.port}`); + } + } + }); + + tracer.push(`replicaPort = ${replicaPort} and stopping it`); + await frame.stopNode(replicaPort); + tracer.push("stopped replica and waiting on sentinel removed promise"); + const stoppedNode = await sentinelRemovePromise as RedisNode; + tracer.push("got removed promise"); + assert.equal(stoppedNode.port, Number(replicaPort)); + + let sentinelRestartedResolve; + const sentinelRestartedPromise = new Promise((res) => { + sentinelRestartedResolve = res; + }) + + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "REPLICA_ADD") { + tracer.push("got replica added event"); + sentinelRestartedResolve(event.node); + } + }); + + tracer.push("restarting replica"); + await frame.restartNode(replicaPort); + tracer.push("restarted replica and waiting on restart promise"); + const restartedNode = await sentinelRestartedPromise as RedisNode; + tracer.push("got restarted promise"); + assert.equal(restartedNode.port, Number(replicaPort)); + }) + + it('add a node / new replica', async function () { + this.timeout(30000); + + sentinel = frame.getSentinelClient({ scanInterval: 2000, replicaPoolSize: 1 }); + sentinel.setTracer(tracer); + // need to handle errors, as the spawning a new docker node can cause existing connections to time out + sentinel.on('error', err => { }); + await sentinel.connect(); + tracer.push("connected"); + + let nodeAddedResolve: (value: RedisNode) => void; + const nodeAddedPromise = new Promise((res) => { + nodeAddedResolve = res as (value: RedisNode) => void; + }); + + const portSet = new Set(); + for (const port of frame.getAllNodesPort()) { + portSet.add(port); + } + + // "on" and not "once" as due to connection timeouts, can happen multiple times, and want right one + sentinel.on('topology-change', (event: RedisSentinelEvent) => { + tracer.push(`got topology-change event: ${JSON.stringify(event)}`); + if (event.type === "REPLICA_ADD") { + if (!portSet.has(event.node.port)) { + tracer.push("got expected replica added event"); + nodeAddedResolve(event.node); + } + } + }); + + tracer.push("adding node"); + await frame.addNode(); + tracer.push("added node and waiting on added promise"); + await nodeAddedPromise; + }) + }) + + describe('Sentinel Factory', function () { + let master: RedisClientType | undefined; + let replica: RedisClientType | undefined; + + beforeEach(async function () { + this.timeout(0); + + await frame.getAllRunning(); + + await steadyState(frame); + longestTestDelta = 0; + }) + + afterEach(async function () { + if (this!.currentTest.state === 'failed') { + console.log(`longest event loop blocked delta: ${longestDelta}`); + console.log(`longest event loop blocked in failing test: ${longestTestDelta}`); + console.log("trace:"); + for (const line of tracer) { + console.log(line); + } + const results = await Promise.all([ + frame.sentinelSentinels(), + frame.sentinelMaster(), + frame.sentinelReplicas() + ]) + console.log(`sentinel sentinels:\n${JSON.stringify(results[0], undefined, '\t')}`); + console.log(`sentinel master:\n${JSON.stringify(results[1], undefined, '\t')}`); + console.log(`sentinel replicas:\n${JSON.stringify(results[2], undefined, '\t')}`); + const { stdout, stderr } = await execAsync("docker ps -a"); + console.log(`docker stdout:\n${stdout}`); + console.log(`docker stderr:\n${stderr}`); + } + tracer.length = 0; + + if (master !== undefined) { + if (master.isOpen) { + master.destroy(); + } + master = undefined; + } + + if (replica !== undefined) { + if (replica.isOpen) { + replica.destroy(); + } + replica = undefined; + } + }) + + it('sentinel factory - master', async function () { + const sentinelPorts = frame.getAllSentinelsPort(); + const sentinels: Array = []; + for (const port of sentinelPorts) { + sentinels.push({ host: "localhost", port: port }); + } + + const factory = new RedisSentinelFactory({ name: frame.config.sentinelName, sentinelRootNodes: sentinels, sentinelClientOptions: {password: password}, nodeClientOptions: {password: password} }) + await factory.updateSentinelRootNodes(); + + master = await factory.getMasterClient(); + await master.connect(); + + assert.equal(await master.set("x", 1), 'OK'); + }) + + it('sentinel factory - replica', async function () { + const sentinelPorts = frame.getAllSentinelsPort(); + const sentinels: Array = []; + + for (const port of sentinelPorts) { + sentinels.push({ host: "localhost", port: port }); + } + + const factory = new RedisSentinelFactory({ name: frame.config.sentinelName, sentinelRootNodes: sentinels, sentinelClientOptions: {password: password}, nodeClientOptions: {password: password} }) + await factory.updateSentinelRootNodes(); + + const masterNode = await factory.getMasterNode(); + replica = await factory.getReplicaClient(); + assert.notEqual(masterNode.port, replica.options?.socket?.port) + }) + + it('sentinel factory - bad node', async function () { + const factory = new RedisSentinelFactory({ name: frame.config.sentinelName, sentinelRootNodes: [{ host: "locahost", port: 1 }] }); + await assert.rejects(factory.updateSentinelRootNodes(), new Error("Couldn't connect to any sentinel node")); + }) + + it('sentinel factory - invalid db name', async function () { + this.timeout(15000); + + const sentinelPorts = frame.getAllSentinelsPort(); + const sentinels: Array = []; + + for (const port of sentinelPorts) { + sentinels.push({ host: "localhost", port: port }); + } + + const factory = new RedisSentinelFactory({ name: "invalid-name", sentinelRootNodes: sentinels, sentinelClientOptions: {password: password}, nodeClientOptions: {password: password} }) + await assert.rejects(factory.updateSentinelRootNodes(), new Error("ERR No such master with that name")); + }) + + it('sentinel factory - no available nodes', async function () { + this.timeout(15000); + + const sentinelPorts = frame.getAllSentinelsPort(); + const sentinels: Array = []; + + for (const port of sentinelPorts) { + sentinels.push({ host: "localhost", port: port }); + } + + const factory = new RedisSentinelFactory({ name: frame.config.sentinelName, sentinelRootNodes: sentinels, sentinelClientOptions: {password: password}, nodeClientOptions: {password: password} }) + + for (const node of frame.getAllNodesPort()) { + await frame.stopNode(node.toString()); + } + + await setTimeout(1000); + + await assert.rejects(factory.getMasterNode(), new Error("Master Node Not Enumerated")); + }) + }) + }) +}); diff --git a/packages/client/lib/sentinel/index.ts b/packages/client/lib/sentinel/index.ts new file mode 100644 index 00000000000..36253044756 --- /dev/null +++ b/packages/client/lib/sentinel/index.ts @@ -0,0 +1,1492 @@ +import { EventEmitter } from 'node:events'; +import { CommandArguments, RedisArgument, RedisFunctions, RedisModules, RedisScript, RedisScripts, ReplyUnion, RespVersions, TypeMapping } from '../RESP/types'; +import RedisClient, { RedisClientOptions, RedisClientType } from '../client'; +import { CommandOptions } from '../client/commands-queue'; +import { attachConfig } from '../commander'; +import COMMANDS from '../commands'; +import { ClientErrorEvent, NamespaceProxySentinel, NamespaceProxySentinelClient, ProxySentinel, ProxySentinelClient, RedisNode, RedisSentinelClientType, RedisSentinelEvent, RedisSentinelOptions, RedisSentinelType, SentinelCommander } from './types'; +import { clientSocketToNode, createCommand, createFunctionCommand, createModuleCommand, createNodeList, createScriptCommand, parseNode } from './utils'; +import { RedisMultiQueuedCommand } from '../multi-command'; +import RedisSentinelMultiCommand, { RedisSentinelMultiCommandType } from './multi-commands'; +import { PubSubListener } from '../client/pub-sub'; +import { PubSubProxy } from './pub-sub-proxy'; +import { setTimeout } from 'node:timers/promises'; +import RedisSentinelModule from './module' +import { RedisVariadicArgument } from '../commands/generic-transformers'; +import { WaitQueue } from './wait-queue'; + +interface ClientInfo { + id: number; +} + +export class RedisSentinelClient< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> { + #clientInfo: ClientInfo | undefined; + #internal: RedisSentinelInternal; + readonly _self: RedisSentinelClient; + + get isOpen() { + return this._self.#internal.isOpen; + } + + get isReady() { + return this._self.#internal.isReady; + } + + get commandOptions() { + return this._self.#commandOptions; + } + + #commandOptions?: CommandOptions; + + constructor( + internal: RedisSentinelInternal, + clientInfo: ClientInfo, + commandOptions?: CommandOptions + ) { + this._self = this; + this.#internal = internal; + this.#clientInfo = clientInfo; + this.#commandOptions = commandOptions; + } + + static factory< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >(config?: SentinelCommander) { + const SentinelClient = attachConfig({ + BaseClass: RedisSentinelClient, + commands: COMMANDS, + createCommand: createCommand, + createModuleCommand: createModuleCommand, + createFunctionCommand: createFunctionCommand, + createScriptCommand: createScriptCommand, + config + }); + + SentinelClient.prototype.Multi = RedisSentinelMultiCommand.extend(config); + + return ( + internal: RedisSentinelInternal, + clientInfo: ClientInfo, + commandOptions?: CommandOptions + ) => { + // returning a "proxy" to prevent the namespaces._self to leak between "proxies" + return Object.create(new SentinelClient(internal, clientInfo, commandOptions)) as RedisSentinelClientType; + }; + } + + static create< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >( + internal: RedisSentinelInternal, + clientInfo: ClientInfo, + commandOptions?: CommandOptions, + options?: RedisSentinelOptions + ) { + return RedisSentinelClient.factory(options)(internal, clientInfo, commandOptions); + } + + withCommandOptions< + OPTIONS extends CommandOptions, + TYPE_MAPPING extends TypeMapping + >(options: OPTIONS) { + const proxy = Object.create(this); + proxy._commandOptions = options; + return proxy as RedisSentinelClientType< + M, + F, + S, + RESP, + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {} + >; + } + + private _commandOptionsProxy< + K extends keyof CommandOptions, + V extends CommandOptions[K] + >( + key: K, + value: V + ) { + const proxy = Object.create(this); + proxy._commandOptions = Object.create(this._self.#commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy as RedisSentinelClientType< + M, + F, + S, + RESP, + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING + >; + } + + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping: TYPE_MAPPING) { + return this._commandOptionsProxy('typeMapping', typeMapping); + } + + async _execute( + isReadonly: boolean | undefined, + fn: (client: RedisClient) => Promise + ): Promise { + if (this._self.#clientInfo === undefined) { + throw new Error("Attempted execution on released RedisSentinelClient lease"); + } + + return await this._self.#internal.execute(fn, this._self.#clientInfo); + } + + async sendCommand( + isReadonly: boolean | undefined, + args: CommandArguments, + options?: CommandOptions, + ): Promise { + return this._execute( + isReadonly, + client => client.sendCommand(args, options) + ); + } + + executeScript( + script: RedisScript, + isReadonly: boolean | undefined, + args: Array, + options?: CommandOptions + ) { + return this._execute( + isReadonly, + client => client.executeScript(script, args, options) + ); + } + + /** + * @internal + */ + async _executePipeline( + isReadonly: boolean | undefined, + commands: Array + ) { + return this._execute( + isReadonly, + client => client._executePipeline(commands) + ); + } + + /**f + * @internal + */ + async _executeMulti( + isReadonly: boolean | undefined, + commands: Array + ) { + return this._execute( + isReadonly, + client => client._executeMulti(commands) + ); + } + + MULTI(): RedisSentinelMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { + return new (this as any).Multi(this); + } + + multi = this.MULTI; + + WATCH(key: RedisVariadicArgument) { + if (this._self.#clientInfo === undefined) { + throw new Error("Attempted execution on released RedisSentinelClient lease"); + } + + return this._execute( + false, + client => client.watch(key) + ) + } + + watch = this.WATCH; + + UNWATCH() { + if (this._self.#clientInfo === undefined) { + throw new Error('Attempted execution on released RedisSentinelClient lease'); + } + + return this._execute( + false, + client => client.unwatch() + ) + } + + unwatch = this.UNWATCH; + + release() { + if (this._self.#clientInfo === undefined) { + throw new Error('RedisSentinelClient lease already released'); + } + + const result = this._self.#internal.releaseClientLease(this._self.#clientInfo); + this._self.#clientInfo = undefined; + return result; + } +} + +export default class RedisSentinel< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends EventEmitter { + readonly _self: RedisSentinel; + + #internal: RedisSentinelInternal; + #options: RedisSentinelOptions; + + get isOpen() { + return this._self.#internal.isOpen; + } + + get isReady() { + return this._self.#internal.isReady; + } + + get commandOptions() { + return this._self.#commandOptions; + } + + #commandOptions?: CommandOptions; + + #trace: (msg: string) => unknown = () => { }; + + #reservedClientInfo?: ClientInfo; + #masterClientCount = 0; + #masterClientInfo?: ClientInfo; + + constructor(options: RedisSentinelOptions) { + super(); + + this._self = this; + + this.#options = options; + + if (options?.commandOptions) { + this.#commandOptions = options.commandOptions; + } + + this.#internal = new RedisSentinelInternal(options); + this.#internal.on('error', err => this.emit('error', err)); + + /* pass through underling events */ + /* TODO: perhaps make this a struct and one vent, instead of multiple events */ + this.#internal.on('topology-change', (event: RedisSentinelEvent) => { + if (!this.emit('topology-change', event)) { + this._self.#trace(`RedisSentinel: re-emit for topology-change for ${event.type} event returned false`); + } + }); + } + + static factory< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >(config?: SentinelCommander) { + const Sentinel = attachConfig({ + BaseClass: RedisSentinel, + commands: COMMANDS, + createCommand: createCommand, + createModuleCommand: createModuleCommand, + createFunctionCommand: createFunctionCommand, + createScriptCommand: createScriptCommand, + config + }); + + Sentinel.prototype.Multi = RedisSentinelMultiCommand.extend(config); + + return (options?: Omit>) => { + // returning a "proxy" to prevent the namespaces.self to leak between "proxies" + return Object.create(new Sentinel(options)) as RedisSentinelType; + }; + } + + static create< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {} + >(options?: RedisSentinelOptions) { + return RedisSentinel.factory(options)(options); + } + + withCommandOptions< + OPTIONS extends CommandOptions, + TYPE_MAPPING extends TypeMapping, + >(options: OPTIONS) { + const proxy = Object.create(this); + proxy._commandOptions = options; + return proxy as RedisSentinelType< + M, + F, + S, + RESP, + TYPE_MAPPING extends TypeMapping ? TYPE_MAPPING : {} + >; + } + + private _commandOptionsProxy< + K extends keyof CommandOptions, + V extends CommandOptions[K] + >( + key: K, + value: V + ) { + const proxy = Object.create(this._self); + proxy._commandOptions = Object.create(this._self.#commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy as RedisSentinelType< + M, + F, + S, + RESP, + K extends 'typeMapping' ? V extends TypeMapping ? V : {} : TYPE_MAPPING + >; + } + + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping: TYPE_MAPPING) { + return this._commandOptionsProxy('typeMapping', typeMapping); + } + + async connect() { + await this._self.#internal.connect(); + + if (this._self.#options.reserveClient) { + this._self.#reservedClientInfo = await this._self.#internal.getClientLease(); + } + + return this as unknown as RedisSentinelType; + } + + async _execute( + isReadonly: boolean | undefined, + fn: (client: RedisClient) => Promise + ): Promise { + let clientInfo: ClientInfo | undefined; + if (!isReadonly || !this._self.#internal.useReplicas) { + if (this._self.#reservedClientInfo) { + clientInfo = this._self.#reservedClientInfo; + } else { + this._self.#masterClientInfo ??= await this._self.#internal.getClientLease(); + clientInfo = this._self.#masterClientInfo; + this._self.#masterClientCount++; + } + } + + try { + return await this._self.#internal.execute(fn, clientInfo); + } finally { + if ( + clientInfo !== undefined && + clientInfo === this._self.#masterClientInfo && + --this._self.#masterClientCount === 0 + ) { + const promise = this._self.#internal.releaseClientLease(clientInfo); + this._self.#masterClientInfo = undefined; + if (promise) await promise; + } + } + } + + async use(fn: (sentinelClient: RedisSentinelClientType) => Promise) { + const clientInfo = await this._self.#internal.getClientLease(); + + try { + return await fn( + RedisSentinelClient.create(this._self.#internal, clientInfo, this._self.#commandOptions, this._self.#options) + ); + } finally { + const promise = this._self.#internal.releaseClientLease(clientInfo); + if (promise) await promise; + } + } + + async sendCommand( + isReadonly: boolean | undefined, + args: CommandArguments, + options?: CommandOptions, + ): Promise { + return this._execute( + isReadonly, + client => client.sendCommand(args, options) + ); + } + + executeScript( + script: RedisScript, + isReadonly: boolean | undefined, + args: Array, + options?: CommandOptions + ) { + return this._execute( + isReadonly, + client => client.executeScript(script, args, options) + ); + } + + /** + * @internal + */ + async _executePipeline( + isReadonly: boolean | undefined, + commands: Array + ) { + return this._execute( + isReadonly, + client => client._executePipeline(commands) + ); + } + + /**f + * @internal + */ + async _executeMulti( + isReadonly: boolean | undefined, + commands: Array + ) { + return this._execute( + isReadonly, + client => client._executeMulti(commands) + ); + } + + MULTI(): RedisSentinelMultiCommandType<[], M, F, S, RESP, TYPE_MAPPING> { + return new (this as any).Multi(this); + } + + multi = this.MULTI; + + async close() { + return this._self.#internal.close(); + } + + destroy() { + return this._self.#internal.destroy(); + } + + async SUBSCRIBE( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this._self.#internal.subscribe(channels, listener, bufferMode); + } + + subscribe = this.SUBSCRIBE; + + async UNSUBSCRIBE( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this._self.#internal.unsubscribe(channels, listener, bufferMode); + } + + unsubscribe = this.UNSUBSCRIBE; + + async PSUBSCRIBE( + patterns: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this._self.#internal.pSubscribe(patterns, listener, bufferMode); + } + + pSubscribe = this.PSUBSCRIBE; + + async PUNSUBSCRIBE( + patterns?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this._self.#internal.pUnsubscribe(patterns, listener, bufferMode); + } + + pUnsubscribe = this.PUNSUBSCRIBE; + + async aquire(): Promise> { + const clientInfo = await this._self.#internal.getClientLease(); + return RedisSentinelClient.create(this._self.#internal, clientInfo, this._self.#commandOptions, this._self.#options); + } + + getSentinelNode(): RedisNode | undefined { + return this._self.#internal.getSentinelNode(); + } + + getMasterNode(): RedisNode | undefined { + return this._self.#internal.getMasterNode(); + } + + getReplicaNodes(): Map { + return this._self.#internal.getReplicaNodes(); + } + + setTracer(tracer?: Array) { + if (tracer) { + this._self.#trace = (msg: string) => { tracer.push(msg) }; + } else { + this._self.#trace = () => { }; + } + + this._self.#internal.setTracer(tracer); + } +} + +class RedisSentinelInternal< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> extends EventEmitter { + #isOpen = false; + + get isOpen() { + return this.#isOpen; + } + + #isReady = false; + + get isReady() { + return this.#isReady; + } + + readonly #name: string; + readonly #nodeClientOptions: RedisClientOptions; + readonly #sentinelClientOptions: RedisClientOptions; + readonly #scanInterval: number; + readonly #passthroughClientErrorEvents: boolean; + + #anotherReset = false; + + #configEpoch: number = 0; + + #sentinelRootNodes: Array; + #sentinelClient?: RedisClientType; + + #masterClients: Array> = []; + #masterClientQueue: WaitQueue; + readonly #masterPoolSize: number; + + #replicaClients: Array> = []; + #replicaClientsIdx: number = 0; + readonly #replicaPoolSize: number; + + get useReplicas() { + return this.#replicaPoolSize > 0; + } + + #connectPromise?: Promise; + #maxCommandRediscovers: number; + readonly #pubSubProxy: PubSubProxy; + + #scanTimer?: NodeJS.Timeout + + #destroy = false; + + #trace: (msg: string) => unknown = () => { }; + + constructor(options: RedisSentinelOptions) { + super(); + + this.#name = options.name; + + this.#sentinelRootNodes = Array.from(options.sentinelRootNodes); + this.#maxCommandRediscovers = options.maxCommandRediscovers ?? 16; + this.#masterPoolSize = options.masterPoolSize ?? 1; + this.#replicaPoolSize = options.replicaPoolSize ?? 0; + this.#scanInterval = options.scanInterval ?? 0; + this.#passthroughClientErrorEvents = options.passthroughClientErrorEvents ?? false; + + this.#nodeClientOptions = options.nodeClientOptions ? Object.assign({} as RedisClientOptions, options.nodeClientOptions) : {}; + if (this.#nodeClientOptions.url !== undefined) { + throw new Error("invalid nodeClientOptions for Sentinel"); + } + + this.#sentinelClientOptions = options.sentinelClientOptions ? Object.assign({} as RedisClientOptions, options.sentinelClientOptions) : {}; + this.#sentinelClientOptions.modules = RedisSentinelModule; + + if (this.#sentinelClientOptions.url !== undefined) { + throw new Error("invalid sentinelClientOptions for Sentinel"); + } + + this.#masterClientQueue = new WaitQueue(); + for (let i = 0; i < this.#masterPoolSize; i++) { + this.#masterClientQueue.push(i); + } + + /* persistent object for life of sentinel object */ + this.#pubSubProxy = new PubSubProxy( + this.#nodeClientOptions, + err => this.emit('error', err) + ); + } + + #createClient(node: RedisNode, clientOptions: RedisClientOptions, reconnectStrategy?: undefined | false) { + const options = { ...clientOptions } as RedisClientOptions; + + if (clientOptions.socket) { + options.socket = { ...clientOptions.socket }; + } else { + options.socket = {}; + } + + options.socket.host = node.host; + options.socket.port = node.port; + options.socket.reconnectStrategy = reconnectStrategy; + + return RedisClient.create(options); + } + + getClientLease(): ClientInfo | Promise { + const id = this.#masterClientQueue.shift(); + if (id !== undefined) { + return { id }; + } + + return this.#masterClientQueue.wait().then(id => ({ id })); + } + + releaseClientLease(clientInfo: ClientInfo) { + const client = this.#masterClients[clientInfo.id]; + // client can be undefined if releasing in middle of a reconfigure + if (client !== undefined) { + const dirtyPromise = client.resetIfDirty(); + if (dirtyPromise) { + return dirtyPromise + .then(() => this.#masterClientQueue.push(clientInfo.id)); + } + } + + this.#masterClientQueue.push(clientInfo.id); + } + + async connect() { + if (this.#isOpen) { + throw new Error("already attempting to open") + } + + try { + this.#isOpen = true; + + this.#connectPromise = this.#connect(); + await this.#connectPromise; + this.#isReady = true; + } finally { + this.#connectPromise = undefined; + if (this.#scanInterval > 0) { + this.#scanTimer = setInterval(this.#reset.bind(this), this.#scanInterval); + } + } + } + + async #connect() { + let count = 0; + while (true) { + this.#trace("starting connect loop"); + + if (this.#destroy) { + this.#trace("in #connect and want to destroy") + return; + } + try { + this.#anotherReset = false; + await this.transform(this.analyze(await this.observe())); + if (this.#anotherReset) { + this.#trace("#connect: anotherReset is true, so continuing"); + continue; + } + + this.#trace("#connect: returning"); + return; + } catch (e: any) { + this.#trace(`#connect: exception ${e.message}`); + if (!this.#isReady && count > this.#maxCommandRediscovers) { + throw e; + } + + if (e.message !== 'no valid master node') { + console.log(e); + } + await setTimeout(1000); + } finally { + this.#trace("finished connect"); + } + } + } + + async execute( + fn: (client: RedisClientType) => Promise, + clientInfo?: ClientInfo + ): Promise { + let iter = 0; + + while (true) { + if (this.#connectPromise !== undefined) { + await this.#connectPromise; + } + + const client = this.#getClient(clientInfo); + + if (!client.isReady) { + await this.#reset(); + continue; + } + this.#trace("attemping to send command to " + client.options?.socket?.host + ":" + client.options?.socket?.port) + + try { + /* + // force testing of READONLY errors + if (clientInfo !== undefined) { + if (Math.floor(Math.random() * 10) < 1) { + console.log("throwing READONLY error"); + throw new Error("READONLY You can't write against a read only replica."); + } + } + */ + return await fn(client); + } catch (err) { + if (++iter > this.#maxCommandRediscovers || !(err instanceof Error)) { + throw err; + } + + /* + rediscover and retry if doing a command against a "master" + a) READONLY error (topology has changed) but we haven't been notified yet via pubsub + b) client is "not ready" (disconnected), which means topology might have changed, but sentinel might not see it yet + */ + if (clientInfo !== undefined && (err.message.startsWith('READONLY') || !client.isReady)) { + await this.#reset(); + continue; + } + + throw err; + } + } + } + + async #createPubSub(client: RedisClientType) { + /* Whenever sentinels or slaves get added, or when slave configuration changes, reconfigure */ + await client.pSubscribe(['switch-master', '[-+]sdown', '+slave', '+sentinel', '[-+]odown', '+slave-reconf-done'], (message, channel) => { + this.#handlePubSubControlChannel(channel, message); + }, true); + + return client; + } + + async #handlePubSubControlChannel(channel: Buffer, message: Buffer) { + this.#trace("pubsub control channel message on " + channel); + this.#reset(); + } + + // if clientInfo is defined, it corresponds to a master client in the #masterClients array, otherwise loop around replicaClients + #getClient(clientInfo?: ClientInfo): RedisClientType { + if (clientInfo !== undefined) { + return this.#masterClients[clientInfo.id]; + } + + if (this.#replicaClientsIdx >= this.#replicaClients.length) { + this.#replicaClientsIdx = 0; + } + + if (this.#replicaClients.length == 0) { + throw new Error("no replicas available for read"); + } + + return this.#replicaClients[this.#replicaClientsIdx++]; + } + + async #reset() { + /* closing / don't reset */ + if (this.#isReady == false || this.#destroy == true) { + return; + } + + // already in #connect() + if (this.#connectPromise !== undefined) { + this.#anotherReset = true; + return await this.#connectPromise; + } + + try { + this.#connectPromise = this.#connect(); + return await this.#connectPromise; + } finally { + this.#trace("finished reconfgure"); + this.#connectPromise = undefined; + } + } + + async close() { + this.#destroy = true; + + if (this.#connectPromise != undefined) { + await this.#connectPromise; + } + + this.#isReady = false; + + if (this.#scanTimer) { + clearInterval(this.#scanTimer); + this.#scanTimer = undefined; + } + + const promises = []; + + if (this.#sentinelClient !== undefined) { + if (this.#sentinelClient.isOpen) { + promises.push(this.#sentinelClient.close()); + } + this.#sentinelClient = undefined; + } + + for (const client of this.#masterClients) { + if (client.isOpen) { + promises.push(client.close()); + } + } + + this.#masterClients = []; + + for (const client of this.#replicaClients) { + if (client.isOpen) { + promises.push(client.close()); + } + } + + this.#replicaClients = []; + + await Promise.all(promises); + + this.#pubSubProxy.destroy(); + + this.#isOpen = false; + } + + // destroy has to be async because its stopping others async events, timers and the like + // and shouldn't return until its finished. + async destroy() { + this.#destroy = true; + + if (this.#connectPromise != undefined) { + await this.#connectPromise; + } + + this.#isReady = false; + + if (this.#scanTimer) { + clearInterval(this.#scanTimer); + this.#scanTimer = undefined; + } + + if (this.#sentinelClient !== undefined) { + if (this.#sentinelClient.isOpen) { + this.#sentinelClient.destroy(); + } + this.#sentinelClient = undefined; + } + + for (const client of this.#masterClients) { + if (client.isOpen) { + client.destroy(); + } + } + this.#masterClients = []; + + for (const client of this.#replicaClients) { + if (client.isOpen) { + client.destroy(); + } + } + this.#replicaClients = []; + + this.#pubSubProxy.destroy(); + + this.#isOpen = false + this.#destroy = false; + } + + async subscribe( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this.#pubSubProxy.subscribe(channels, listener, bufferMode); + } + + async unsubscribe( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this.#pubSubProxy.unsubscribe(channels, listener, bufferMode); + } + + async pSubscribe( + patterns: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this.#pubSubProxy.pSubscribe(patterns, listener, bufferMode); + } + + async pUnsubscribe( + patterns?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this.#pubSubProxy.pUnsubscribe(patterns, listener, bufferMode); + } + + // observe/analyze/transform remediation functions + async observe() { + for (const node of this.#sentinelRootNodes) { + let client: RedisClientType | undefined; + try { + this.#trace(`observe: trying to connect to sentinel: ${node.host}:${node.port}`) + client = this.#createClient(node, this.#sentinelClientOptions, false) + .on('error', (err) => this.emit('error', `obseve client error: ${err}`)); + await client.connect(); + this.#trace(`observe: connected to sentinel`) + + const promises = []; + promises.push(client.sentinel.sentinelSentinels(this.#name)); + promises.push(client.sentinel.sentinelMaster(this.#name)); + promises.push(client.sentinel.sentinelReplicas(this.#name)); + + const [sd, md, rd] = await Promise.all(promises); + + this.#trace("observe: got all sentinel data"); + + const sentinelData = sd as Array; + const masterData = md as any; + const replicaData = rd as Array; + + const ret = { + sentinelConnected: node, + sentinelData: sentinelData, + masterData: masterData, + replicaData: replicaData, + currentMaster: this.getMasterNode(), + currentReplicas: this.getReplicaNodes(), + currentSentinel: this.getSentinelNode(), + replicaPoolSize: this.#replicaPoolSize, + useReplicas: this.useReplicas + } + + return ret; + } catch (err) { + this.#trace(`observe: error ${err}`); + this.emit('error', err); + } finally { + if (client !== undefined && client.isOpen) { + this.#trace(`observe: destroying sentinel client`); + client.destroy(); + } + } + } + + this.#trace(`observe: none of the sentinels are available`); + throw new Error('None of the sentinels are available'); + } + + analyze(observed: Awaited["observe"]>>) { + let master = parseNode(observed.masterData); + if (master === undefined) { + this.#trace(`analyze: no valid master node because ${observed.masterData.flags}`); + throw new Error("no valid master node"); + } + + if (master.host === observed.currentMaster?.host && master.port === observed.currentMaster?.port) { + this.#trace(`analyze: master node hasn't changed from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); + master = undefined; + } else { + this.#trace(`analyze: master node has changed to ${master.host}:${master.port} from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); + } + + let sentinel: RedisNode | undefined = observed.sentinelConnected; + if (sentinel.host === observed.currentSentinel?.host && sentinel.port === observed.currentSentinel.port) { + this.#trace(`analyze: sentinel node hasn't changed`); + sentinel = undefined; + } else { + this.#trace(`analyze: sentinel node has changed to ${sentinel.host}:${sentinel.port}`); + } + + const replicasToClose: Array = []; + const replicasToOpen = new Map(); + + const desiredSet = new Set(); + const seen = new Set(); + + if (observed.useReplicas) { + const replicaList = createNodeList(observed.replicaData) + + for (const node of replicaList) { + desiredSet.add(JSON.stringify(node)); + } + + for (const [node, value] of observed.currentReplicas) { + if (!desiredSet.has(JSON.stringify(node))) { + replicasToClose.push(node); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToClose`); + } else { + seen.add(JSON.stringify(node)); + if (value != observed.replicaPoolSize) { + replicasToOpen.set(node, observed.replicaPoolSize - value); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); + } + } + } + + for (const node of replicaList) { + if (!seen.has(JSON.stringify(node))) { + replicasToOpen.set(node, observed.replicaPoolSize); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); + } + } + } + + const ret = { + sentinelList: [observed.sentinelConnected].concat(createNodeList(observed.sentinelData)), + epoch: Number(observed.masterData['config-epoch']), + + sentinelToOpen: sentinel, + masterToOpen: master, + replicasToClose: replicasToClose, + replicasToOpen: replicasToOpen, + }; + + return ret; + } + + async transform(analyzed: ReturnType["analyze"]>) { + this.#trace("transform: enter"); + + let promises: Array> = []; + + if (analyzed.sentinelToOpen) { + this.#trace(`transform: opening a new sentinel`); + if (this.#sentinelClient !== undefined && this.#sentinelClient.isOpen) { + this.#trace(`transform: destroying old sentinel as open`); + this.#sentinelClient.destroy() + this.#sentinelClient = undefined; + } else { + this.#trace(`transform: not destroying old sentinel as not open`); + } + + this.#trace(`transform: creating new sentinel to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); + const node = analyzed.sentinelToOpen; + const client = this.#createClient(analyzed.sentinelToOpen, this.#sentinelClientOptions, false); + client.on('error', (err: Error) => { + if (this.#passthroughClientErrorEvents) { + this.emit('error', new Error(`Sentinel Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event: ClientErrorEvent = { + type: 'SENTINEL', + node: clientSocketToNode(client.options!.socket!), + error: err + }; + this.emit('client-error', event); + this.#reset(); + }); + this.#sentinelClient = client; + + this.#trace(`transform: adding sentinel client connect() to promise list`); + const promise = this.#sentinelClient.connect().then((client) => { return this.#createPubSub(client) }); + promises.push(promise); + + this.#trace(`created sentinel client to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); + const event: RedisSentinelEvent = { + type: "SENTINEL_CHANGE", + node: analyzed.sentinelToOpen + } + this.#trace(`transform: emiting topology-change event for sentinel_change`); + if (!this.emit('topology-change', event)) { + this.#trace(`transform: emit for topology-change for sentinel_change returned false`); + } + } + + if (analyzed.masterToOpen) { + this.#trace(`transform: opening a new master`); + const masterPromises = []; + const masterWatches: Array = []; + + this.#trace(`transform: destroying old masters if open`); + for (const client of this.#masterClients) { + masterWatches.push(client.isWatching); + + if (client.isOpen) { + client.destroy() + } + } + + this.#masterClients = []; + + this.#trace(`transform: creating all master clients and adding connect promises`); + for (let i = 0; i < this.#masterPoolSize; i++) { + const node = analyzed.masterToOpen; + const client = this.#createClient(analyzed.masterToOpen, this.#nodeClientOptions); + client.on('error', (err: Error) => { + if (this.#passthroughClientErrorEvents) { + this.emit('error', new Error(`Master Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event: ClientErrorEvent = { + type: "MASTER", + node: clientSocketToNode(client.options!.socket!), + error: err + }; + this.emit('client-error', event); + }); + + if (masterWatches[i]) { + client.setDirtyWatch("sentinel config changed in middle of a WATCH Transaction"); + } + this.#masterClients.push(client); + masterPromises.push(client.connect()); + + this.#trace(`created master client to ${analyzed.masterToOpen.host}:${analyzed.masterToOpen.port}`); + } + + this.#trace(`transform: adding promise to change #pubSubProxy node`); + masterPromises.push(this.#pubSubProxy.changeNode(analyzed.masterToOpen)); + promises.push(...masterPromises); + const event: RedisSentinelEvent = { + type: "MASTER_CHANGE", + node: analyzed.masterToOpen + } + this.#trace(`transform: emiting topology-change event for master_change`); + if (!this.emit('topology-change', event)) { + this.#trace(`transform: emit for topology-change for master_change returned false`); + } + this.#configEpoch++; + } + + const replicaCloseSet = new Set(); + for (const node of analyzed.replicasToClose) { + const str = JSON.stringify(node); + replicaCloseSet.add(str); + } + + const newClientList: Array> = []; + const removedSet = new Set(); + + for (const replica of this.#replicaClients) { + const node = clientSocketToNode(replica.options!.socket!); + const str = JSON.stringify(node); + + if (replicaCloseSet.has(str) || !replica.isOpen) { + if (replica.isOpen) { + this.#trace(`destroying replica client to ${replica.options?.socket?.host}:${replica.options?.socket?.port}`); + replica.destroy() + } + if (!removedSet.has(str)) { + const event: RedisSentinelEvent = { + type: "REPLICA_REMOVE", + node: node + } + this.emit('topology-change', event); + removedSet.add(str); + } + } else { + newClientList.push(replica); + } + } + this.#replicaClients = newClientList; + + if (analyzed.replicasToOpen.size != 0) { + for (const [node, size] of analyzed.replicasToOpen) { + for (let i = 0; i < size; i++) { + const client = this.#createClient(node, this.#nodeClientOptions); + client.on('error', (err: Error) => { + if (this.#passthroughClientErrorEvents) { + this.emit('error', new Error(`Replica Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event: ClientErrorEvent = { + type: "REPLICA", + node: clientSocketToNode(client.options!.socket!), + error: err + }; + this.emit('client-error', event); + }); + + this.#replicaClients.push(client); + promises.push(client.connect()); + + this.#trace(`created replica client to ${node.host}:${node.port}`); + } + const event: RedisSentinelEvent = { + type: "REPLICA_ADD", + node: node + } + this.emit('topology-change', event); + } + } + + if (analyzed.sentinelList.length != this.#sentinelRootNodes.length) { + this.#sentinelRootNodes = analyzed.sentinelList; + const event: RedisSentinelEvent = { + type: "SENTINE_LIST_CHANGE", + size: analyzed.sentinelList.length + } + this.emit('topology-change', event); + } + + await Promise.all(promises); + this.#trace("transform: exit"); + } + + // introspection functions + getMasterNode(): RedisNode | undefined { + if (this.#masterClients.length == 0) { + return undefined; + } + + for (const master of this.#masterClients) { + if (master.isReady) { + return clientSocketToNode(master.options!.socket!); + } + } + + return undefined; + } + + getSentinelNode(): RedisNode | undefined { + if (this.#sentinelClient === undefined) { + return undefined; + } + + return clientSocketToNode(this.#sentinelClient.options!.socket!); + } + + getReplicaNodes(): Map { + const ret = new Map(); + const initialMap = new Map(); + + for (const replica of this.#replicaClients) { + const node = clientSocketToNode(replica.options!.socket!); + const hash = JSON.stringify(node); + + if (replica.isReady) { + initialMap.set(hash, (initialMap.get(hash) ?? 0) + 1); + } else { + if (!initialMap.has(hash)) { + initialMap.set(hash, 0); + } + } + } + + for (const [key, value] of initialMap) { + ret.set(JSON.parse(key) as RedisNode, value); + } + + return ret; + } + + setTracer(tracer?: Array) { + if (tracer) { + this.#trace = (msg: string) => { tracer.push(msg) }; + } else { + // empty function is faster than testing if something is defined or not + this.#trace = () => { }; + } + } +} + +export class RedisSentinelFactory extends EventEmitter { + options: RedisSentinelOptions; + #sentinelRootNodes: Array; + #replicaIdx: number = -1; + + constructor(options: RedisSentinelOptions) { + super(); + + this.options = options; + this.#sentinelRootNodes = options.sentinelRootNodes; + } + + async updateSentinelRootNodes() { + for (const node of this.#sentinelRootNodes) { + const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; + if (options.socket === undefined) { + options.socket = {}; + } + options.socket.host = node.host; + options.socket.port = node.port; + options.socket.reconnectStrategy = false; + options.modules = RedisSentinelModule; + + const client = RedisClient.create(options).on('error', (err) => this.emit(`updateSentinelRootNodes: ${err}`)); + try { + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); + } + continue; + } + + try { + const sentinelData = await client.sentinel.sentinelSentinels(this.options.name) as Array; + this.#sentinelRootNodes = [node].concat(createNodeList(sentinelData)); + return; + } finally { + client.destroy(); + } + } + + throw new Error("Couldn't connect to any sentinel node"); + } + + async getMasterNode() { + let connected = false; + + for (const node of this.#sentinelRootNodes) { + const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; + if (options.socket === undefined) { + options.socket = {}; + } + options.socket.host = node.host; + options.socket.port = node.port; + options.socket.reconnectStrategy = false; + options.modules = RedisSentinelModule; + + const client = RedisClient.create(options).on('error', err => this.emit(`getMasterNode: ${err}`)); + + try { + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); + } + continue; + } + + connected = true; + + try { + const masterData = await client.sentinel.sentinelMaster(this.options.name) as any; + + let master = parseNode(masterData); + if (master === undefined) { + continue; + } + + return master; + } finally { + client.destroy(); + } + } + + if (connected) { + throw new Error("Master Node Not Enumerated"); + } + + throw new Error("couldn't connect to any sentinels"); + } + + async getMasterClient() { + const master = await this.getMasterNode(); + const options: RedisClientOptions = { ...this.options.nodeClientOptions }; + if (options.socket === undefined) { + options.socket = {}; + } + options.socket.host = master.host; + options.socket.port = master.port; + + return RedisClient.create(options);; + } + + async getReplicaNodes() { + let connected = false; + + for (const node of this.#sentinelRootNodes) { + const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; + if (options.socket === undefined) { + options.socket = {}; + } + options.socket.host = node.host; + options.socket.port = node.port; + options.socket.reconnectStrategy = false; + options.modules = RedisSentinelModule; + + const client = RedisClient.create(options).on('error', err => this.emit(`getReplicaNodes: ${err}`)); + + try { + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); + } + continue; + } + + connected = true; + + try { + const replicaData = await client.sentinel.sentinelReplicas(this.options.name) as Array; + + const replicas = createNodeList(replicaData); + if (replicas.length == 0) { + continue; + } + + return replicas; + } finally { + client.destroy(); + } + } + + if (connected) { + throw new Error("No Replicas Nodes Enumerated"); + } + + throw new Error("couldn't connect to any sentinels"); + } + + async getReplicaClient() { + const replicas = await this.getReplicaNodes(); + if (replicas.length == 0) { + throw new Error("no available replicas"); + } + + this.#replicaIdx++; + if (this.#replicaIdx >= replicas.length) { + this.#replicaIdx = 0; + } + + const options: RedisClientOptions = { ...this.options.nodeClientOptions }; + if (options.socket === undefined) { + options.socket = {}; + } + options.socket.host = replicas[this.#replicaIdx].host; + options.socket.port = replicas[this.#replicaIdx].port; + + return RedisClient.create(options); + } +} diff --git a/packages/client/lib/sentinel/module.ts b/packages/client/lib/sentinel/module.ts new file mode 100644 index 00000000000..ab90da521bc --- /dev/null +++ b/packages/client/lib/sentinel/module.ts @@ -0,0 +1,6 @@ +import { RedisModules } from '@redis/client'; +import sentinel from './commands'; + +export default { + sentinel +} as const satisfies RedisModules; diff --git a/packages/client/lib/sentinel/multi-commands.ts b/packages/client/lib/sentinel/multi-commands.ts new file mode 100644 index 00000000000..12da9b2c97c --- /dev/null +++ b/packages/client/lib/sentinel/multi-commands.ts @@ -0,0 +1,215 @@ +import COMMANDS from '../commands'; +import RedisMultiCommand, { MULTI_REPLY, MultiReply, MultiReplyType } from '../multi-command'; +import { ReplyWithTypeMapping, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, TypeMapping } from '../RESP/types'; +import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; +import { RedisSentinelType } from './types'; + +type CommandSignature< + REPLIES extends Array, + C extends Command, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = (...args: Parameters) => RedisSentinelMultiCommandType< + [...REPLIES, ReplyWithTypeMapping, TYPE_MAPPING>], + M, + F, + S, + RESP, + TYPE_MAPPING +>; + +type WithCommands< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof typeof COMMANDS]: CommandSignature; +}; + +type WithModules< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; +}; + +type WithFunctions< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; +}; + +type WithScripts< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof S]: CommandSignature; +}; + +export type RedisSentinelMultiCommandType< + REPLIES extends Array, + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = ( + RedisSentinelMultiCommand & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); + +export default class RedisSentinelMultiCommand { + private static _createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: RedisSentinelMultiCommand, ...args: Array) { + const redisArgs = command.transformArguments(...args); + return this.addCommand( + command.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return function (this: { _self: RedisSentinelMultiCommand }, ...args: Array) { + const redisArgs = command.transformArguments(...args); + return this._self.addCommand( + command.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return function (this: { _self: RedisSentinelMultiCommand }, ...args: Array) { + const fnArgs = fn.transformArguments(...args); + const redisArgs: CommandArguments = prefix.concat(fnArgs); + redisArgs.preserve = fnArgs.preserve; + return this._self.addCommand( + fn.IS_READ_ONLY, + redisArgs, + transformReply + ); + }; + } + + private static _createScriptCommand(script: RedisScript, resp: RespVersions) { + const transformReply = getTransformReply(script, resp); + return function (this: RedisSentinelMultiCommand, ...args: Array) { + const scriptArgs = script.transformArguments(...args); + this._setState( + script.IS_READ_ONLY + ); + this._multi.addScript( + script, + scriptArgs, + transformReply + ); + return this; + }; + } + + static extend< + M extends RedisModules = Record, + F extends RedisFunctions = Record, + S extends RedisScripts = Record, + RESP extends RespVersions = 2 + >(config?: CommanderConfig) { + return attachConfig({ + BaseClass: RedisSentinelMultiCommand, + commands: COMMANDS, + createCommand: RedisSentinelMultiCommand._createCommand, + createModuleCommand: RedisSentinelMultiCommand._createModuleCommand, + createFunctionCommand: RedisSentinelMultiCommand._createFunctionCommand, + createScriptCommand: RedisSentinelMultiCommand._createScriptCommand, + config + }); + } + + private readonly _multi = new RedisMultiCommand(); + private readonly _sentinel: RedisSentinelType + private _isReadonly: boolean | undefined = true; + + constructor(sentinel: RedisSentinelType) { + this._sentinel = sentinel; + } + + private _setState( + isReadonly: boolean | undefined, + ) { + this._isReadonly &&= isReadonly; + } + + addCommand( + isReadonly: boolean | undefined, + args: CommandArguments, + transformReply?: TransformReply + ) { + this._setState(isReadonly); + this._multi.addCommand(args, transformReply); + return this; + } + + async exec(execAsPipeline = false) { + if (execAsPipeline) return this.execAsPipeline(); + + return this._multi.transformReplies( + await this._sentinel._executeMulti( + this._isReadonly, + this._multi.queue + ) + ) as MultiReplyType; + } + + EXEC = this.exec; + + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); + } + + async execAsPipeline() { + if (this._multi.queue.length === 0) return [] as MultiReplyType; + + return this._multi.transformReplies( + await this._sentinel._executePipeline( + this._isReadonly, + this._multi.queue + ) + ) as MultiReplyType; + } + + execAsPipelineTyped() { + return this.execAsPipeline(); + } +} diff --git a/packages/client/lib/sentinel/pub-sub-proxy.ts b/packages/client/lib/sentinel/pub-sub-proxy.ts new file mode 100644 index 00000000000..a27f6e50c95 --- /dev/null +++ b/packages/client/lib/sentinel/pub-sub-proxy.ts @@ -0,0 +1,213 @@ +import EventEmitter from 'node:events'; +import { RedisModules, RedisFunctions, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; +import { RedisClientOptions } from '../client'; +import { PUBSUB_TYPE, PubSubListener, PubSubTypeListeners } from '../client/pub-sub'; +import { RedisNode } from './types'; +import RedisClient from '../client'; + +type Client = RedisClient< + RedisModules, + RedisFunctions, + RedisScripts, + RespVersions, + TypeMapping +>; + +type Subscriptions = Record< + PUBSUB_TYPE['CHANNELS'] | PUBSUB_TYPE['PATTERNS'], + PubSubTypeListeners +>; + +type PubSubState = { + client: Client; + connectPromise: Promise | undefined; +}; + +type OnError = (err: unknown) => unknown; + +export class PubSubProxy extends EventEmitter { + #clientOptions; + #onError; + + #node?: RedisNode; + #state?: PubSubState; + #subscriptions?: Subscriptions; + + constructor(clientOptions: RedisClientOptions, onError: OnError) { + super(); + + this.#clientOptions = clientOptions; + this.#onError = onError; + } + + #createClient() { + if (this.#node === undefined) { + throw new Error("pubSubProxy: didn't define node to do pubsub against"); + } + + const options = { ...this.#clientOptions }; + + if (this.#clientOptions.socket) { + options.socket = { ...this.#clientOptions.socket }; + } else { + options.socket = {}; + } + + options.socket.host = this.#node.host; + options.socket.port = this.#node.port; + + return new RedisClient(options); + } + + async #initiatePubSubClient(withSubscriptions = false) { + const client = this.#createClient() + .on('error', this.#onError); + + const connectPromise = client.connect() + .then(async client => { + if (this.#state?.client !== client) { + // if pubsub was deactivated while connecting (`this.#pubSubClient === undefined`) + // or if the node changed (`this.#pubSubClient.client !== client`) + client.destroy(); + return this.#state?.connectPromise; + } + + if (withSubscriptions && this.#subscriptions) { + await Promise.all([ + client.extendPubSubListeners(PUBSUB_TYPE.CHANNELS, this.#subscriptions[PUBSUB_TYPE.CHANNELS]), + client.extendPubSubListeners(PUBSUB_TYPE.PATTERNS, this.#subscriptions[PUBSUB_TYPE.PATTERNS]) + ]); + } + + if (this.#state.client !== client) { + // if the node changed (`this.#pubSubClient.client !== client`) + client.destroy(); + return this.#state?.connectPromise; + } + + this.#state!.connectPromise = undefined; + return client; + }) + .catch(err => { + this.#state = undefined; + throw err; + }); + + this.#state = { + client, + connectPromise + }; + + return connectPromise; + } + + #getPubSubClient() { + if (!this.#state) return this.#initiatePubSubClient(); + + return ( + this.#state.connectPromise ?? + this.#state.client + ); + } + + async changeNode(node: RedisNode) { + this.#node = node; + + if (!this.#state) return; + + // if `connectPromise` is undefined, `this.#subscriptions` is already set + // and `this.#state.client` might not have the listeners set yet + if (this.#state.connectPromise === undefined) { + this.#subscriptions = { + [PUBSUB_TYPE.CHANNELS]: this.#state.client.getPubSubListeners(PUBSUB_TYPE.CHANNELS), + [PUBSUB_TYPE.PATTERNS]: this.#state.client.getPubSubListeners(PUBSUB_TYPE.PATTERNS) + }; + + this.#state.client.destroy(); + } + + await this.#initiatePubSubClient(true); + } + + #executeCommand(fn: (client: Client) => T) { + const client = this.#getPubSubClient(); + if (client instanceof RedisClient) { + return fn(client); + } + + return client.then(client => { + // if pubsub was deactivated while connecting + if (client === undefined) return; + + return fn(client); + }).catch(err => { + if (this.#state?.client.isPubSubActive) { + this.#state.client.destroy(); + this.#state = undefined; + } + + throw err; + }); + } + + subscribe( + channels: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this.#executeCommand( + client => client.SUBSCRIBE(channels, listener, bufferMode) + ); + } + + #unsubscribe(fn: (client: Client) => Promise) { + return this.#executeCommand(async client => { + const reply = await fn(client); + + if (!client.isPubSubActive) { + client.destroy(); + this.#state = undefined; + } + + return reply; + }); + } + + async unsubscribe( + channels?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this.#unsubscribe(client => client.UNSUBSCRIBE(channels, listener, bufferMode)); + } + + async pSubscribe( + patterns: string | Array, + listener: PubSubListener, + bufferMode?: T + ) { + return this.#executeCommand( + client => client.PSUBSCRIBE(patterns, listener, bufferMode) + ); + } + + async pUnsubscribe( + patterns?: string | Array, + listener?: PubSubListener, + bufferMode?: T + ) { + return this.#unsubscribe(client => client.PUNSUBSCRIBE(patterns, listener, bufferMode)); + } + + destroy() { + this.#subscriptions = undefined; + if (this.#state === undefined) return; + + // `connectPromise` already handles the case of `this.#pubSubState = undefined` + if (!this.#state.connectPromise) { + this.#state.client.destroy(); + } + + this.#state = undefined; + } +} diff --git a/packages/client/lib/sentinel/test-util.ts b/packages/client/lib/sentinel/test-util.ts new file mode 100644 index 00000000000..113bbddb389 --- /dev/null +++ b/packages/client/lib/sentinel/test-util.ts @@ -0,0 +1,605 @@ +import { createConnection } from 'node:net'; +import { setTimeout } from 'node:timers/promises'; +import { once } from 'node:events'; +import { promisify } from 'node:util'; +import { exec } from 'node:child_process'; +import { RedisSentinelOptions, RedisSentinelType } from './types'; +import RedisClient from '../client'; +import RedisSentinel from '.'; +import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; +const execAsync = promisify(exec); +import RedisSentinelModule from './module' + +interface ErrorWithCode extends Error { + code: string; +} + +async function isPortAvailable(port: number): Promise { + var socket = undefined; + try { + socket = createConnection({ port }); + await once(socket, 'connect'); + } catch (err) { + if (err instanceof Error && (err as ErrorWithCode).code === 'ECONNREFUSED') { + return true; + } + } finally { + if (socket !== undefined) { + socket.end(); + } + } + + return false; +} + +const portIterator = (async function* (): AsyncIterableIterator { + for (let i = 6379; i < 65535; i++) { + if (await isPortAvailable(i)) { + yield i; + } + } + + throw new Error('All ports are in use'); +})(); + +export interface RedisServerDockerConfig { + image: string; + version: string; +} + +export interface RedisServerDocker { + port: number; + dockerId: string; +} + +abstract class DockerBase { + async spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array, environment?: string): Promise { + const port = (await portIterator.next()).value; + let cmdLine = `docker run --init -d --network host `; + if (environment !== undefined) { + cmdLine += `-e ${environment} `; + } + cmdLine += `${image}:${version} ${serverArguments.join(' ')}`; + cmdLine = cmdLine.replace('{port}', `--port ${port.toString()}`); + // console.log("spawnRedisServerDocker: cmdLine = " + cmdLine); + const { stdout, stderr } = await execAsync(cmdLine); + + if (!stdout) { + throw new Error(`docker run error - ${stderr}`); + } + + while (await isPortAvailable(port)) { + await setTimeout(50); + } + + return { + port, + dockerId: stdout.trim() + }; + } + + async dockerRemove(dockerId: string): Promise { + try { + await this.dockerStop(dockerId); `` + } catch (err) { + // its ok if stop failed, as we are just going to remove, will just be slower + console.log(`dockerStop failed in remove: ${err}`); + } + + const { stderr } = await execAsync(`docker rm -f ${dockerId}`); + if (stderr) { + console.log("docker rm failed"); + throw new Error(`docker rm error - ${stderr}`); + } + } + + async dockerStop(dockerId: string): Promise { + /* this is an optimization to get around slow docker stop times, but will fail if container is already stopped */ + try { + await execAsync(`docker exec ${dockerId} /bin/bash -c "kill -SIGINT 1"`); + } catch (err) { + /* this will fail if container is already not running, can be ignored */ + } + + let ret = await execAsync(`docker stop ${dockerId}`); + if (ret.stderr) { + throw new Error(`docker stop error - ${ret.stderr}`); + } + } + + async dockerStart(dockerId: string): Promise { + const { stderr } = await execAsync(`docker start ${dockerId}`); + if (stderr) { + throw new Error(`docker start error - ${stderr}`); + } + } +} + +export interface RedisSentinelConfig { + numberOfNodes?: number; + nodeDockerConfig?: RedisServerDockerConfig; + nodeServerArguments?: Array + + numberOfSentinels?: number; + sentinelDockerConfig?: RedisServerDockerConfig; + sentinelServerArgument?: Array + + sentinelName: string; + sentinelQuorum?: number; + + password?: string; +} + +type ArrayElement = + ArrayType extends readonly (infer ElementType)[] ? ElementType : never; + +export interface SentinelController { + getMaster(): Promise; + getMasterPort(): Promise; + getRandomNode(): string; + getRandonNonMasterNode(): Promise; + getNodePort(id: string): number; + getAllNodesPort(): Array; + getSentinelPort(id: string): number; + getAllSentinelsPort(): Array; + getSetinel(i: number): string; + stopNode(id: string): Promise; + restartNode(id: string): Promise; + stopSentinel(id: string): Promise; + restartSentinel(id: string): Promise; + getSentinelClient(opts?: Partial>): RedisSentinelType<{}, {}, {}, 2, {}>; +} + +export class SentinelFramework extends DockerBase { + #nodeList: Awaited> = []; + /* port -> docker info/client */ + #nodeMap: Map>>>; + #sentinelList: Awaited> = []; + /* port -> docker info/client */ + #sentinelMap: Map>>>; + + config: RedisSentinelConfig; + + #spawned: boolean = false; + + get spawned() { + return this.#spawned; + } + + constructor(config: RedisSentinelConfig) { + super(); + + this.config = config; + + this.#nodeMap = new Map>>>(); + this.#sentinelMap = new Map>>>(); + } + + getSentinelClient(opts?: Partial>, errors = true) { + if (opts?.sentinelRootNodes !== undefined) { + throw new Error("cannot specify sentinelRootNodes here"); + } + if (opts?.name !== undefined) { + throw new Error("cannot specify sentinel db name here"); + } + + const options: RedisSentinelOptions = { + name: this.config.sentinelName, + sentinelRootNodes: this.#sentinelList.map((sentinel) => { return { host: '127.0.0.1', port: sentinel.docker.port } }), + passthroughClientErrorEvents: errors + } + + if (this.config.password !== undefined) { + options.nodeClientOptions = {password: this.config.password}; + options.sentinelClientOptions = {password: this.config.password}; + } + + if (opts) { + Object.assign(options, opts); + } + + return RedisSentinel.create(options); + } + + async spawnRedisSentinel() { + if (this.#spawned) { + return; + } + + if (this.#nodeMap.size != 0 || this.#sentinelMap.size != 0) { + throw new Error("inconsistent state with partial setup"); + } + + this.#nodeList = await this.spawnRedisSentinelNodes(); + this.#nodeList.map((value) => this.#nodeMap.set(value.docker.port.toString(), value)); + + this.#sentinelList = await this.spawnRedisSentinelSentinels(); + this.#sentinelList.map((value) => this.#sentinelMap.set(value.docker.port.toString(), value)); + + this.#spawned = true; + } + + async cleanup() { + if (!this.#spawned) { + return; + } + + return Promise.all( + [...this.#nodeMap!.values(), ...this.#sentinelMap!.values()].map( + async ({ docker, client }) => { + if (client.isOpen) { + client.destroy(); + } + this.dockerRemove(docker.dockerId); + } + ) + ).finally(async () => { + this.#spawned = false; + this.#nodeMap.clear(); + this.#sentinelMap.clear(); + }); + } + + protected async spawnRedisSentinelNodeDocker() { + const imageInfo: RedisServerDockerConfig = this.config.nodeDockerConfig ?? { image: "redis/redis-stack-server", version: "latest" }; + const serverArguments: Array = this.config.nodeServerArguments ?? []; + let environment; + if (this.config.password !== undefined) { + environment = `REDIS_ARGS="{port} --requirepass ${this.config.password}"`; + } else { + environment = 'REDIS_ARGS="{port}"'; + } + + const docker = await this.spawnRedisServerDocker(imageInfo, serverArguments, environment); + const client = await RedisClient.create({ + password: this.config.password, + socket: { + port: docker.port + } + }).on("error", () => { }).connect(); + + return { + docker, + client + }; + } + + protected async spawnRedisSentinelNodes() { + const master = await this.spawnRedisSentinelNodeDocker(); + + const promises: Array> = []; + + for (let i = 0; i < (this.config.numberOfNodes ?? 0) - 1; i++) { + promises.push( + this.spawnRedisSentinelNodeDocker().then(async node => { + if (this.config.password !== undefined) { + await node.client.configSet({'masterauth': this.config.password}) + } + await node.client.replicaOf('127.0.0.1', master.docker.port); + return node; + }) + ); + } + + return [ + master, + ...await Promise.all(promises) + ]; + } + + protected async spawnRedisSentinelSentinelDocker() { + const imageInfo: RedisServerDockerConfig = this.config.sentinelDockerConfig ?? { image: "redis", version: "latest" } + let serverArguments: Array; + if (this.config.password === undefined) { + serverArguments = this.config.sentinelServerArgument ?? + [ + "/bin/bash", + "-c", + "\"touch /tmp/sentinel.conf ; /usr/local/bin/redis-sentinel /tmp/sentinel.conf {port} \"" + ]; + } else { + serverArguments = this.config.sentinelServerArgument ?? + [ + "/bin/bash", + "-c", + `"touch /tmp/sentinel.conf ; /usr/local/bin/redis-sentinel /tmp/sentinel.conf {port} --requirepass ${this.config.password}"` + ]; + } + + const docker = await this.spawnRedisServerDocker(imageInfo, serverArguments); + const client = await RedisClient.create({ + modules: RedisSentinelModule, + password: this.config.password, + socket: { + port: docker.port + } + }).on("error", () => { }).connect(); + + return { + docker, + client + }; + } + + protected async spawnRedisSentinelSentinels() { + const quorum = this.config.sentinelQuorum?.toString() ?? "2"; + const node = this.#nodeList[0]; + + const promises: Array> = []; + + for (let i = 0; i < (this.config.numberOfSentinels ?? 3); i++) { + promises.push( + this.spawnRedisSentinelSentinelDocker().then(async sentinel => { + await sentinel.client.sentinel.sentinelMonitor(this.config.sentinelName, '127.0.0.1', node.docker.port.toString(), quorum); + const options: Array<{option: RedisArgument, value: RedisArgument}> = []; + options.push({ option: "down-after-milliseconds", value: "100" }); + options.push({ option: "failover-timeout", value: "5000" }); + if (this.config.password !== undefined) { + options.push({ option: "auth-pass", value: this.config.password }); + } + await sentinel.client.sentinel.sentinelSet(this.config.sentinelName, options) + return sentinel; + }) + ); + } + + return [ + ...await Promise.all(promises) + ] + } + + async getAllRunning() { + for (const port of this.getAllNodesPort()) { + let first = true; + while (await isPortAvailable(port)) { + if (!first) { + console.log(`problematic restart ${port}`); + await setTimeout(500); + } else { + first = false; + } + await this.restartNode(port.toString()); + } + } + + for (const port of this.getAllSentinelsPort()) { + let first = true; + while (await isPortAvailable(port)) { + if (!first) { + await setTimeout(500); + } else { + first = false; + } + await this.restartSentinel(port.toString()); + } + } + } + + async addSentinel() { + const quorum = this.config.sentinelQuorum?.toString() ?? "2"; + const node = this.#nodeList[0]; + const sentinel = await this.spawnRedisSentinelSentinelDocker(); + + await sentinel.client.sentinel.sentinelMonitor(this.config.sentinelName, '127.0.0.1', node.docker.port.toString(), quorum); + const options: Array<{option: RedisArgument, value: RedisArgument}> = []; + options.push({ option: "down-after-milliseconds", value: "100" }); + options.push({ option: "failover-timeout", value: "5000" }); + if (this.config.password !== undefined) { + options.push({ option: "auth-pass", value: this.config.password }); + } + await sentinel.client.sentinel.sentinelSet(this.config.sentinelName, options); + + this.#sentinelList.push(sentinel); + this.#sentinelMap.set(sentinel.docker.port.toString(), sentinel); + } + + async addNode() { + const masterPort = await this.getMasterPort(); + const newNode = await this.spawnRedisSentinelNodeDocker(); + + if (this.config.password !== undefined) { + await newNode.client.configSet({'masterauth': this.config.password}) + } + await newNode.client.replicaOf('127.0.0.1', masterPort); + + this.#nodeList.push(newNode); + this.#nodeMap.set(newNode.docker.port.toString(), newNode); + } + + async getMaster(tracer?: Array): Promise { + for (const sentinel of this.#sentinelMap!.values()) { + let info; + + try { + if (!sentinel.client.isReady) { + continue; + } + + info = await sentinel.client.sentinel.sentinelMaster(this.config.sentinelName) as any; + if (tracer) { + tracer.push('getMaster: master data returned from sentinel'); + tracer.push(JSON.stringify(info, undefined, '\t')) + } + } catch (err) { + console.log("getMaster: sentinelMaster call failed: " + err); + continue; + } + + const master = this.#nodeMap.get(info.port); + if (master === undefined) { + throw new Error(`couldn't find master node for ${info.port}`); + } + + if (tracer) { + tracer.push(`getMaster: master port is either ${info.port} or ${master.docker.port}`); + } + + if (!master.client.isOpen) { + throw new Error(`Sentinel's expected master node (${info.port}) is now down`); + } + + return info.port; + } + + throw new Error("Couldn't get master"); + } + + async getMasterPort(tracer?: Array): Promise { + const data = await this.getMaster(tracer) + + return this.#nodeMap.get(data!)!.docker.port; + } + + getRandomNode() { + return this.#nodeList[Math.floor(Math.random() * this.#nodeList.length)].docker.port.toString(); + } + + async getRandonNonMasterNode(): Promise { + const masterPort = await this.getMasterPort(); + while (true) { + const node = this.#nodeList[Math.floor(Math.random() * this.#nodeList.length)]; + if (node.docker.port != masterPort) { + return node.docker.port.toString(); + } + } + } + + async stopNode(id: string) { +// console.log(`stopping node ${id}`); + let node = this.#nodeMap.get(id); + if (node === undefined) { + throw new Error("unknown node: " + id); + } + + if (node.client.isOpen) { + node.client.destroy(); + } + + return await this.dockerStop(node.docker.dockerId); + } + + async restartNode(id: string) { + let node = this.#nodeMap.get(id); + if (node === undefined) { + throw new Error("unknown node: " + id); + } + + await this.dockerStart(node.docker.dockerId); + if (!node.client.isOpen) { + node.client = await RedisClient.create({ + password: this.config.password, + socket: { + port: node.docker.port + } + }).on("error", () => { }).connect(); + } + } + + async stopSentinel(id: string) { + let sentinel = this.#sentinelMap.get(id); + if (sentinel === undefined) { + throw new Error("unknown sentinel: " + id); + } + + if (sentinel.client.isOpen) { + sentinel.client.destroy(); + } + + return await this.dockerStop(sentinel.docker.dockerId); + } + + async restartSentinel(id: string) { + let sentinel = this.#sentinelMap.get(id); + if (sentinel === undefined) { + throw new Error("unknown sentinel: " + id); + } + + await this.dockerStart(sentinel.docker.dockerId); + if (!sentinel.client.isOpen) { + sentinel.client = await RedisClient.create({ + modules: RedisSentinelModule, + password: this.config.password, + socket: { + port: sentinel.docker.port + } + }).on("error", () => { }).connect(); + } + } + + getNodePort(id: string) { + let node = this.#nodeMap.get(id); + if (node === undefined) { + throw new Error("unknown node: " + id); + } + + return node.docker.port; + } + + getAllNodesPort() { + let ports: Array = []; + for (const node of this.#nodeList) { + ports.push(node.docker.port); + } + + return ports + } + + getAllDockerIds() { + let ids = new Map(); + for (const node of this.#nodeList) { + ids.set(node.docker.dockerId, node.docker.port); + } + + return ids; + } + + getSentinelPort(id: string) { + let sentinel = this.#sentinelMap.get(id); + if (sentinel === undefined) { + throw new Error("unknown sentinel: " + id); + } + + return sentinel.docker.port; + } + + getAllSentinelsPort() { + let ports: Array = []; + for (const sentinel of this.#sentinelList) { + ports.push(sentinel.docker.port); + } + + return ports + } + + getSetinel(i: number): string { + return this.#sentinelList[i].docker.port.toString(); + } + + sentinelSentinels() { + for (const sentinel of this.#sentinelList) { + if (sentinel.client.isReady) { + return sentinel.client.sentinel.sentinelSentinels(this.config.sentinelName); + } + } + } + + sentinelMaster() { + for (const sentinel of this.#sentinelList) { + if (sentinel.client.isReady) { + return sentinel.client.sentinel.sentinelMaster(this.config.sentinelName); + } + } + } + + sentinelReplicas() { + for (const sentinel of this.#sentinelList) { + if (sentinel.client.isReady) { + return sentinel.client.sentinel.sentinelReplicas(this.config.sentinelName); + } + } + } +} diff --git a/packages/client/lib/sentinel/types.ts b/packages/client/lib/sentinel/types.ts new file mode 100644 index 00000000000..571100766e3 --- /dev/null +++ b/packages/client/lib/sentinel/types.ts @@ -0,0 +1,174 @@ +import { RedisClientOptions } from '../client'; +import { CommandOptions } from '../client/commands-queue'; +import { CommandSignature, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; +import COMMANDS from '../commands'; +import RedisSentinel, { RedisSentinelClient } from '.'; + +export interface RedisNode { + host: string; + port: number; +} + +export interface RedisSentinelOptions< + M extends RedisModules = RedisModules, + F extends RedisFunctions = RedisFunctions, + S extends RedisScripts = RedisScripts, + RESP extends RespVersions = RespVersions, + TYPE_MAPPING extends TypeMapping = TypeMapping +> extends SentinelCommander { + /** + * The sentinel identifier for a particular database cluster + */ + name: string; + /** + * An array of root nodes that are part of the sentinel cluster, which will be used to get the 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 sentinel configuration from the server + */ + sentinelRootNodes: Array; + /** + * The maximum number of times a command will retry due to topology changes. + */ + maxCommandRediscovers?: number; + /** + * The configuration values for every node in the cluster. Use this for example when specifying an ACL user to connect with + */ + nodeClientOptions?: RedisClientOptions; + /** + * The configuration values for every sentinel in the cluster. Use this for example when specifying an ACL user to connect with + */ + sentinelClientOptions?: RedisClientOptions; + /** + * The number of clients connected to the master node + */ + masterPoolSize?: number; + /** + * The number of clients connected to each replica node. + * When greater than 0, the client will distribute the load by executing read-only commands (such as `GET`, `GEOSEARCH`, etc.) across all the cluster nodes. + */ + replicaPoolSize?: number; + /** + * TODO + */ + scanInterval?: number; + /** + * TODO + */ + passthroughClientErrorEvents?: boolean; + /** + * When `true`, one client will be reserved for the sentinel object. + * When `false`, the sentinel object will wait for the first available client from the pool. + */ + reserveClient?: boolean; +} + +export interface SentinelCommander< + M extends RedisModules, + F extends RedisFunctions, + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping, + // POLICIES extends CommandPolicies +> extends CommanderConfig { + commandOptions?: CommandOptions; +} + +export type RedisSentinelClientOptions = Omit< + RedisClientOptions, + keyof SentinelCommander +>; + +type WithCommands< + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof typeof COMMANDS]: CommandSignature<(typeof COMMANDS)[P], RESP, TYPE_MAPPING>; +}; + +type WithModules< + M extends RedisModules, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof M]: { + [C in keyof M[P]]: CommandSignature; + }; +}; + +type WithFunctions< + F extends RedisFunctions, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [L in keyof F]: { + [C in keyof F[L]]: CommandSignature; + }; +}; + +type WithScripts< + S extends RedisScripts, + RESP extends RespVersions, + TYPE_MAPPING extends TypeMapping +> = { + [P in keyof S]: CommandSignature; +}; + +export type RedisSentinelClientType< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, +> = ( + RedisSentinelClient & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); + +export type RedisSentinelType< + M extends RedisModules = {}, + F extends RedisFunctions = {}, + S extends RedisScripts = {}, + RESP extends RespVersions = 2, + TYPE_MAPPING extends TypeMapping = {}, + // POLICIES extends CommandPolicies = {} +> = ( + RedisSentinel & + WithCommands & + WithModules & + WithFunctions & + WithScripts +); + +export interface SentinelCommandOptions< + TYPE_MAPPING extends TypeMapping = TypeMapping +> extends CommandOptions {} + +export type ProxySentinel = RedisSentinel; +export type ProxySentinelClient = RedisSentinelClient; +export type NamespaceProxySentinel = { _self: ProxySentinel }; +export type NamespaceProxySentinelClient = { _self: ProxySentinelClient }; + +export type NodeInfo = { + ip: any, + port: any, + flags: any, +}; + +export type RedisSentinelEvent = NodeChangeEvent | SizeChangeEvent; + +export type NodeChangeEvent = { + type: "SENTINEL_CHANGE" | "MASTER_CHANGE" | "REPLICA_ADD" | "REPLICA_REMOVE"; + node: RedisNode; +} + +export type SizeChangeEvent = { + type: "SENTINE_LIST_CHANGE"; + size: Number; +} + +export type ClientErrorEvent = { + type: 'MASTER' | 'REPLICA' | 'SENTINEL' | 'PUBSUBPROXY'; + node: RedisNode; + error: Error; +} diff --git a/packages/client/lib/sentinel/utils.ts b/packages/client/lib/sentinel/utils.ts new file mode 100644 index 00000000000..44de98fe71a --- /dev/null +++ b/packages/client/lib/sentinel/utils.ts @@ -0,0 +1,103 @@ +import { Command, RedisFunction, RedisScript, RespVersions } from '../RESP/types'; +import { RedisSocketOptions } from '../client/socket'; +import { functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; +import { NamespaceProxySentinel, NamespaceProxySentinelClient, NodeInfo, ProxySentinel, ProxySentinelClient, RedisNode } from './types'; + +/* TODO: should use map interface, would need a transform reply probably? as resp2 is list form, which this depends on */ +export function parseNode(node: NodeInfo): RedisNode | undefined{ + if (node.flags.includes("s_down") || node.flags.includes("disconnected") || node.flags.includes("failover_in_progress")) { + return undefined; + } + + return { host: node.ip, port: Number(node.port) }; +} + +export function createNodeList(nodes: Array) { + var nodeList: Array = []; + + for (const nodeData of nodes) { + const node = parseNode(nodeData) + if (node === undefined) { + continue; + } + nodeList.push(node); + } + + return nodeList; +} + +export function clientSocketToNode(socket: RedisSocketOptions): RedisNode { + return { + host: socket.host!, + port: socket.port! + } +} + +export function createCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: T, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this._self.sendCommand( + command.IS_READ_ONLY, + redisArgs, + this._self.commandOptions + ); + + return transformReply ? + transformReply(reply, redisArgs.preserve) : + reply; + }; +} + +export function createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions) { + const prefix = functionArgumentsPrefix(name, fn), + transformReply = getTransformReply(fn, resp); + return async function (this: T, ...args: Array) { + const fnArgs = fn.transformArguments(...args), + redisArgs = prefix.concat(fnArgs), + reply = await this._self._self.sendCommand( + fn.IS_READ_ONLY, + redisArgs, + this._self._self.commandOptions + ); + + return transformReply ? + transformReply(reply, fnArgs.preserve) : + reply; + } +}; + +export function createModuleCommand(command: Command, resp: RespVersions) { + const transformReply = getTransformReply(command, resp); + return async function (this: T, ...args: Array) { + const redisArgs = command.transformArguments(...args), + reply = await this._self._self.sendCommand( + command.IS_READ_ONLY, + redisArgs, + this._self._self.commandOptions + ); + + return transformReply ? + transformReply(reply, redisArgs.preserve) : + reply; + } +}; + +export function createScriptCommand(script: RedisScript, resp: RespVersions) { + const prefix = scriptArgumentsPrefix(script), + transformReply = getTransformReply(script, resp); + return async function (this: T, ...args: Array) { + const scriptArgs = script.transformArguments(...args), + redisArgs = prefix.concat(scriptArgs), + reply = await this._self.executeScript( + script, + script.IS_READ_ONLY, + redisArgs, + this._self.commandOptions + ); + + return transformReply ? + transformReply(reply, scriptArgs.preserve) : + reply; + }; +} diff --git a/packages/client/lib/sentinel/wait-queue.ts b/packages/client/lib/sentinel/wait-queue.ts new file mode 100644 index 00000000000..138801eb4d9 --- /dev/null +++ b/packages/client/lib/sentinel/wait-queue.ts @@ -0,0 +1,24 @@ +import { SinglyLinkedList } from '../client/linked-list'; + +export class WaitQueue { + #list = new SinglyLinkedList(); + #queue = new SinglyLinkedList<(item: T) => unknown>(); + + push(value: T) { + const resolve = this.#queue.shift(); + if (resolve !== undefined) { + resolve(value); + return; + } + + this.#list.push(value); + } + + shift() { + return this.#list.shift(); + } + + wait() { + return new Promise(resolve => this.#queue.push(resolve)); + } +} diff --git a/packages/gears/lib/commands/TFUNCTION_LIST.ts b/packages/gears/lib/commands/TFUNCTION_LIST.ts new file mode 100644 index 00000000000..da022e8854d --- /dev/null +++ b/packages/gears/lib/commands/TFUNCTION_LIST.ts @@ -0,0 +1,51 @@ +import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types'; + +export interface TFunctionListOptions { + LIBRARYNAME?: RedisArgument; +} + +export type TFunctionListReplyItem = [ + [BlobStringReply<'library_name'>, BlobStringReply | NullReply], + [BlobStringReply<'engine'>, BlobStringReply], + [BlobStringReply<'functions'>, ArrayReply, BlobStringReply], + [BlobStringReply<'description'>, BlobStringReply | NullReply], + [BlobStringReply<'flags'>, SetReply], + ]>>] +]; + +export type TFunctionListReply = ArrayReply>; + +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: false, + transformArguments(options?: TFunctionListOptions) { + const args: CommandArguments = ['FUNCTION', 'LIST']; + + if (options?.LIBRARYNAME) { + args.push('LIBRARYNAME', options.LIBRARYNAME); + } + + return args; + }, + transformReply: { + 2: (reply: UnwrapReply>) => { + return reply.map(library => { + const unwrapped = library as unknown as UnwrapReply; + return { + library_name: unwrapped[1], + engine: unwrapped[3], + functions: (unwrapped[5] as unknown as UnwrapReply).map(fn => { + const unwrapped = fn as unknown as UnwrapReply; + return { + name: unwrapped[1], + description: unwrapped[3], + flags: unwrapped[5] + }; + }) + }; + }); + }, + 3: undefined as unknown as () => TFunctionListReply + } +} as const satisfies Command; diff --git a/packages/redis/README.md b/packages/redis/README.md index 82386d725de..23307bb6e24 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -199,6 +199,7 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each - [Command Options](../../docs/command-options.md). - [Pool](../../docs/pool.md). - [Clustering](../../docs/clustering.md). +- [Sentinel](../../docs/sentinel.md). ## Supported Redis versions From 8340a9e8301c9343784b9de134ef46ce3343f898 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 5 Feb 2024 11:18:27 -0500 Subject: [PATCH 307/325] some cleanups --- README.md | 36 +- package-lock.json | 1560 +++++------------ package.json | 16 +- packages/bloom/README.md | 11 +- packages/bloom/package.json | 3 + packages/client/index.ts | 3 +- packages/client/lib/client/index.ts | 4 +- packages/client/lib/sentinel/index.spec.ts | 2 +- packages/client/lib/sentinel/module.ts | 3 +- packages/client/package.json | 4 +- packages/gears/lib/commands/TFUNCTION_LIST.ts | 51 - packages/graph/package.json | 3 + packages/json/README.md | 24 +- packages/json/package.json | 3 + packages/redis/README.md | 40 +- packages/redis/package.json | 3 + packages/search/README.md | 10 +- packages/search/package.json | 3 + packages/time-series/README.md | 180 +- packages/time-series/package.json | 3 + tsconfig.base.json | 6 +- 21 files changed, 610 insertions(+), 1358 deletions(-) delete mode 100644 packages/gears/lib/commands/TFUNCTION_LIST.ts diff --git a/README.md b/README.md index 461bb198e89..783f6785bab 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,35 @@ node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js. +## Installation + +Start a redis-server via docker (or any other method you prefer): + +```bash +docker run -p 6379:6379 -it redis/redis-stack-server:latest +``` + +To install node-redis, simply: + +```bash +npm install redis +``` + +> "redis" is the "whole in one" package that includes all the other packages. If you only need a subset of the commands, you can install the individual packages. See the list below. + ## Packages -| Name | Description | -|----------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [redis](./packages/redis) | [![Downloads](https://img.shields.io/npm/dm/redis.svg)](https://www.npmjs.com/package/redis) [![Version](https://img.shields.io/npm/v/redis.svg)](https://www.npmjs.com/package/redis) | -| [@redis/client](./packages/client) | [![Downloads](https://img.shields.io/npm/dm/@redis/client.svg)](https://www.npmjs.com/package/@redis/client) [![Version](https://img.shields.io/npm/v/@redis/client.svg)](https://www.npmjs.com/package/@redis/client) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/client/) | -| [@redis/bloom](./packages/bloom) | [![Downloads](https://img.shields.io/npm/dm/@redis/bloom.svg)](https://www.npmjs.com/package/@redis/bloom) [![Version](https://img.shields.io/npm/v/@redis/bloom.svg)](https://www.npmjs.com/package/@redis/bloom) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/bloom/) [Redis Bloom](https://oss.redis.com/redisbloom/) commands | -| [@redis/graph](./packages/graph) | [![Downloads](https://img.shields.io/npm/dm/@redis/graph.svg)](https://www.npmjs.com/package/@redis/graph) [![Version](https://img.shields.io/npm/v/@redis/graph.svg)](https://www.npmjs.com/package/@redis/graph) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/graph/) [Redis Graph](https://oss.redis.com/redisgraph/) commands | -| [@redis/json](./packages/json) | [![Downloads](https://img.shields.io/npm/dm/@redis/json.svg)](https://www.npmjs.com/package/@redis/json) [![Version](https://img.shields.io/npm/v/@redis/json.svg)](https://www.npmjs.com/package/@redis/json) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/json/) [Redis JSON](https://oss.redis.com/redisjson/) commands | -| [@redis/search](./packages/search) | [![Downloads](https://img.shields.io/npm/dm/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Version](https://img.shields.io/npm/v/@redis/search.svg)](https://www.npmjs.com/package/@redis/search) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/search/) [RediSearch](https://oss.redis.com/redisearch/) commands | -| [@redis/time-series](./packages/time-series) | [![Downloads](https://img.shields.io/npm/dm/@redis/time-series.svg)](https://www.npmjs.com/package/@redis/time-series) [![Version](https://img.shields.io/npm/v/@redis/time-series.svg)](https://www.npmjs.com/package/@redis/time-series) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://redis.js.org/documentation/time-series/) [Redis Time-Series](https://oss.redis.com/redistimeseries/) commands | +| Name | Description | +|------------------------------------------------|---------------------------------------------------------------------------------------------| +| [`redis`](./packages/redis) | The client with all the ["redis-stack"](https://github.com/redis-stack/redis-stack) modules | +| [`@redis/client`](./packages/client) | The base clients (i.e `RedisClient`, `RedisCluster`, etc.) | +| [`@redis/bloom`](./packages/bloom) | [Redis Bloom](https://redis.io/docs/data-types/probabilistic/) commands | +| [`redis/graph`](./packages/graph) | [Redis Graph](https://redis.io/docs/data-types/probabilistic/) commands | +| [`@redis/json`](./packages/json) | [Redis JSON](https://redis.io/docs/data-types/json/) commands | +| [`@redis/search`](./packages/search) | [RediSearch](https://redis.io/docs/interact/search-and-query/) commands | +| [`@redis/time-series`](./packages/time-series) | [Redis Time-Series](https://redis.io/docs/data-types/timeseries/) commands | + +> Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! ## Contributing diff --git a/package-lock.json b/package-lock.json index aff547130b9..312ece6a26c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,26 +11,14 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.6", - "@types/node": "^20.10.3", - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/parser": "^6.13.2", - "gh-pages": "^6.1.0", + "@types/node": "^20.11.16", + "gh-pages": "^6.1.1", "mocha": "^10.2.0", "nyc": "^15.1.0", - "release-it": "^17.0.0", - "tsx": "^4.6.2", - "typedoc": "^0.25.4", - "typescript": "^5.3.2" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" + "release-it": "^17.0.3", + "tsx": "^4.7.0", + "typedoc": "^0.25.7", + "typescript": "^5.3.3" } }, "node_modules/@ampproject/remapping": { @@ -175,15 +163,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", @@ -215,15 +194,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", @@ -486,15 +456,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", @@ -877,148 +838,6 @@ "node": ">=12" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "peer": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "peer": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true, - "peer": true - }, "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -1115,15 +934,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", @@ -1559,12 +1369,6 @@ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -1572,20 +1376,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", - "dev": true - }, "node_modules/@types/sinon": { "version": "17.0.3", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", @@ -1616,226 +1414,6 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.19.1", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "peer": true - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -1861,23 +1439,6 @@ "node": ">=8" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -1991,25 +1552,31 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/array-uniq": { @@ -2041,17 +1608,18 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -2089,9 +1657,9 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { "node": ">= 0.4" @@ -2299,12 +1867,13 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -2483,9 +2052,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001581", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", - "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", "dev": true, "funding": [ { @@ -2518,6 +2087,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -2551,18 +2132,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -2850,6 +2419,12 @@ } } }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -2895,13 +2470,6 @@ "node": ">=4.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true - }, "node_modules/default-browser": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", @@ -3038,31 +2606,6 @@ "node": ">=0.3.1" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dot-prop": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", @@ -3085,9 +2628,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.648", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", - "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", + "version": "1.4.656", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.656.tgz", + "integrity": "sha512-9AQB5eFTHyR3Gvt2t/NwR0le2jBSUNwCnMbUCejFWHD+so4tH40/dRLgoE+jxlPeWS43XJewyvCv+I8LPMl49Q==", "dev": true }, "node_modules/email-addresses": { @@ -3179,6 +2722,15 @@ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -3328,133 +2880,6 @@ "source-map": "~0.6.1" } }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "peer": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -3468,32 +2893,6 @@ "node": ">=4" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "peer": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "peer": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -3573,13 +2972,6 @@ "node": ">=4" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -3596,36 +2988,10 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "peer": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "peer": true - }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3694,19 +3060,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "peer": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -3787,28 +3140,6 @@ "flat": "cli.js" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "peer": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true, - "peer": true - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3973,16 +3304,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.3.tgz", + "integrity": "sha512-JIcZczvcMVE7AUOP+X72bh8HqHBRxFdz5PDHYtNG/lE3yk9b3KZBJlwFcTyPYjg3L4RLLmZJzvjxhaZVapxFrQ==", "dev": true, "dependencies": { + "es-errors": "^1.0.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4101,45 +3436,17 @@ "async": "^3.2.4", "commander": "^11.0.0", "email-addresses": "^5.0.0", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^11.1.1", - "globby": "^6.1.0" - }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gh-pages/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gh-pages/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, "node_modules/git-up": { @@ -4162,15 +3469,15 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -4182,38 +3489,15 @@ } }, "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "peer": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "is-glob": "^4.0.1" }, "engines": { - "node": "*" + "node": ">= 6" } }, "node_modules/global-dirs": { @@ -4232,19 +3516,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, "node_modules/globalthis": { @@ -4263,23 +3540,19 @@ } }, "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/gopd": { @@ -4337,12 +3610,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -4398,12 +3665,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -4428,15 +3695,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -4551,9 +3809,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -4575,6 +3833,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -4713,6 +3980,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/internal-slot": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", @@ -4759,14 +4038,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5148,12 +4429,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -5280,15 +4561,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", @@ -5320,6 +4592,18 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/istanbul-lib-report/node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -5335,6 +4619,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -5426,20 +4743,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "peer": true - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5500,20 +4803,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -5577,13 +4866,6 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true - }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", @@ -5660,15 +4942,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -5755,18 +5028,15 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/minimist": { @@ -5818,6 +5088,38 @@ "url": "https://opencollective.com/mochajs" } }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -5830,31 +5132,19 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "balanced-match": "^1.0.0" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/mute-stream": { @@ -5878,12 +5168,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -5921,9 +5205,9 @@ } }, "node_modules/nise": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", - "integrity": "sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -6134,17 +5418,8 @@ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, + "p-limit": "^2.2.0" + }, "engines": { "node": ">=8" } @@ -6277,24 +5552,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "peer": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", @@ -6663,6 +5920,39 @@ "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/package-json/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/package-json/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6751,12 +6041,15 @@ "dev": true }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/picocolors": { @@ -6871,16 +6164,6 @@ "node": ">=8" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", @@ -6959,16 +6242,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -7224,30 +6497,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/release-it/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "node_modules/release-it/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "yallist": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/release-it/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/release-it/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "engines": { - "node": ">=14.16" + "dependencies": { + "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/release-it/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/release-it/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", @@ -7308,12 +6590,12 @@ "dev": true }, "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/resolve-pkg-maps": { @@ -7526,18 +6808,12 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/semver-diff": { @@ -7555,7 +6831,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver/node_modules/lru-cache": { + "node_modules/semver-diff/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -7567,7 +6843,22 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/yallist": { + "node_modules/semver-diff/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", @@ -7715,15 +7006,30 @@ "node": ">=0.3.1" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" } }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -7959,15 +7265,18 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -7996,35 +7305,6 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "peer": true - }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -8079,18 +7359,6 @@ "node": ">=0.8.0" } }, - "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", - "dev": true, - "engines": { - "node": ">=16.13.0" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -8116,19 +7384,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -8139,16 +7394,12 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/typed-array-buffer": { @@ -8246,6 +7497,30 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", @@ -8390,16 +7665,39 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/update-notifier/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/update-notifier/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "peer": true, "dependencies": { - "punycode": "^2.1.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/update-notifier/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/url-join": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", @@ -8492,16 +7790,16 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8846,7 +8144,7 @@ }, "devDependencies": { "@redis/test-utils": "*", - "@types/sinon": "^17.0.2", + "@types/sinon": "^17.0.3", "sinon": "^17.0.1" }, "engines": { diff --git a/package.json b/package.json index 7f2375e1228..c626d4a48e8 100644 --- a/package.json +++ b/package.json @@ -6,22 +6,20 @@ ], "scripts": { "test": "npm run test -ws --if-present", - "build": "NODE_OPTIONS='--max-old-space-size=4096' tsc --build", + "build": "tsc --build", "documentation": "typedoc", "gh-pages": "gh-pages -d ./documentation -e ./documentation -u 'documentation-bot '" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", "@types/mocha": "^10.0.6", - "@types/node": "^20.10.3", - "@typescript-eslint/eslint-plugin": "^6.13.2", - "@typescript-eslint/parser": "^6.13.2", - "gh-pages": "^6.1.0", + "@types/node": "^20.11.16", + "gh-pages": "^6.1.1", "mocha": "^10.2.0", "nyc": "^15.1.0", - "release-it": "^17.0.0", - "tsx": "^4.6.2", - "typedoc": "^0.25.4", - "typescript": "^5.3.2" + "release-it": "^17.0.3", + "tsx": "^4.7.0", + "typedoc": "^0.25.7", + "typescript": "^5.3.3" } } diff --git a/packages/bloom/README.md b/packages/bloom/README.md index 8eb1445d188..e527ff5552c 100644 --- a/packages/bloom/README.md +++ b/packages/bloom/README.md @@ -1,14 +1,17 @@ # @redis/bloom -This package provides support for the [RedisBloom](https://redisbloom.io) module, which adds additional probabilistic data structures to Redis. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RediBloom commands. +This package provides support for the [RedisBloom](https://redis.io/docs/data-types/probabilistic/) module, which adds additional probabilistic data structures to Redis. -To use these extra commands, your Redis server must have the RedisBloom module installed. +Should be used with [`redis`/`@redis/client`](https://github.com/redis/node-redis). + +:warning: To use these extra commands, your Redis server must have the RedisBloom module installed. RedisBloom provides the following probabilistic data structures: * Bloom Filter: for checking set membership with a high degree of certainty. * Cuckoo Filter: for checking set membership with a high degree of certainty. -* Count-Min Sketch: Determine the frequency of events in a stream. +* T-Digest: for estimating the quantiles of a stream of data. * Top-K: Maintain a list of k most frequently seen items. +* Count-Min Sketch: Determine the frequency of events in a stream. -For complete examples, see `bloom-filter.js`, `cuckoo-filter.js`, `count-min-sketch.js` and `topk.js` in the Node Redis examples folder. +For some examples, see [`bloom-filter.js`](https://github.com/redis/node-redis/tree/master/examples/bloom-filter.js), [`cuckoo-filter.js`](https://github.com/redis/node-redis/tree/master/examples/cuckoo-filter.js), [`count-min-sketch.js`](https://github.com/redis/node-redis/tree/master/examples/count-min-sketch.js) and [`topk.js`](https://github.com/redis/node-redis/tree/master/examples/topk.js) in the [examples folder](https://github.com/redis/node-redis/tree/master/examples). diff --git a/packages/bloom/package.json b/packages/bloom/package.json index 6bdeb508218..850ad802a5d 100644 --- a/packages/bloom/package.json +++ b/packages/bloom/package.json @@ -17,6 +17,9 @@ "devDependencies": { "@redis/test-utils": "*" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/client/index.ts b/packages/client/index.ts index c6f8814a6c5..56cdf703ca3 100644 --- a/packages/client/index.ts +++ b/packages/client/index.ts @@ -17,8 +17,7 @@ export { RedisClusterType, RedisClusterOptions }; export const createCluster = RedisCluster.create; import RedisSentinel from './lib/sentinel'; -import { RedisSentinelOptions, RedisSentinelType } from './lib/sentinel/types'; -export { RedisSentinelType, RedisSentinelOptions }; +export { RedisSentinelOptions, RedisSentinelType } from './lib/sentinel/types'; export const createSentinel = RedisSentinel.create; // export { GeoReplyWith } from './lib/commands/generic-transformers'; diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index a24770e6f99..041b0b7225c 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -460,7 +460,9 @@ export default class RedisClient< }) .on('reconnecting', () => this.emit('reconnecting')) .on('drain', () => this.#maybeScheduleWrite()) - .on('end', () => this.emit('end')); + .on('end', () => { + console.log('socket on end, emitting end', this.emit('end')); + }); } #pingTimer?: NodeJS.Timeout; diff --git a/packages/client/lib/sentinel/index.spec.ts b/packages/client/lib/sentinel/index.spec.ts index a7238a5fdfd..e62acc181f7 100644 --- a/packages/client/lib/sentinel/index.spec.ts +++ b/packages/client/lib/sentinel/index.spec.ts @@ -88,7 +88,7 @@ async function steadyState(frame: SentinelFramework) { } ["redis-sentinel-test-password", undefined].forEach(function (password) { - describe.only(`Sentinel - password = ${password}`, () => { + describe.skip(`Sentinel - password = ${password}`, () => { const config: RedisSentinelConfig = { sentinelName: "test", numberOfNodes: 3, password: password }; const frame = new SentinelFramework(config); let tracer = new Array(); diff --git a/packages/client/lib/sentinel/module.ts b/packages/client/lib/sentinel/module.ts index ab90da521bc..e6e98e72f6d 100644 --- a/packages/client/lib/sentinel/module.ts +++ b/packages/client/lib/sentinel/module.ts @@ -1,4 +1,5 @@ -import { RedisModules } from '@redis/client'; + +import { RedisModules } from '../RESP/types'; import sentinel from './commands'; export default { diff --git a/packages/client/package.json b/packages/client/package.json index ce6d28ff348..cb82f67bd53 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -16,11 +16,11 @@ }, "devDependencies": { "@redis/test-utils": "*", - "@types/sinon": "^17.0.2", + "@types/sinon": "^17.0.3", "sinon": "^17.0.1" }, "engines": { - "node": ">=14" + "node": ">= 18" }, "repository": { "type": "git", diff --git a/packages/gears/lib/commands/TFUNCTION_LIST.ts b/packages/gears/lib/commands/TFUNCTION_LIST.ts deleted file mode 100644 index da022e8854d..00000000000 --- a/packages/gears/lib/commands/TFUNCTION_LIST.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types'; - -export interface TFunctionListOptions { - LIBRARYNAME?: RedisArgument; -} - -export type TFunctionListReplyItem = [ - [BlobStringReply<'library_name'>, BlobStringReply | NullReply], - [BlobStringReply<'engine'>, BlobStringReply], - [BlobStringReply<'functions'>, ArrayReply, BlobStringReply], - [BlobStringReply<'description'>, BlobStringReply | NullReply], - [BlobStringReply<'flags'>, SetReply], - ]>>] -]; - -export type TFunctionListReply = ArrayReply>; - -export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, - transformArguments(options?: TFunctionListOptions) { - const args: CommandArguments = ['FUNCTION', 'LIST']; - - if (options?.LIBRARYNAME) { - args.push('LIBRARYNAME', options.LIBRARYNAME); - } - - return args; - }, - transformReply: { - 2: (reply: UnwrapReply>) => { - return reply.map(library => { - const unwrapped = library as unknown as UnwrapReply; - return { - library_name: unwrapped[1], - engine: unwrapped[3], - functions: (unwrapped[5] as unknown as UnwrapReply).map(fn => { - const unwrapped = fn as unknown as UnwrapReply; - return { - name: unwrapped[1], - description: unwrapped[3], - flags: unwrapped[5] - }; - }) - }; - }); - }, - 3: undefined as unknown as () => TFunctionListReply - } -} as const satisfies Command; diff --git a/packages/graph/package.json b/packages/graph/package.json index 0a6b728482d..13db5312487 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -17,6 +17,9 @@ "devDependencies": { "@redis/test-utils": "*" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/json/README.md b/packages/json/README.md index e7f70174116..86996a68370 100644 --- a/packages/json/README.md +++ b/packages/json/README.md @@ -1,12 +1,14 @@ # @redis/json -This package provides support for the [RedisJSON](https://redis.io/docs/stack/json/) module, which adds JSON as a native data type to Redis. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RedisJSON commands. +This package provides support for the [RedisJSON](https://redis.io/docs/data-types/json/) module, which adds JSON as a native data type to Redis. -To use these extra commands, your Redis server must have the RedisJSON module installed. +Should be used with [`redis`/`@redis/client`](https://github.com/redis/node-redis). + +:warning: To use these extra commands, your Redis server must have the RedisJSON module installed. ## Usage -For a complete example, see [`managing-json.js`](https://github.com/redis/node-redis/blob/master/examples/managing-json.js) in the Node Redis examples folder. +For a complete example, see [`managing-json.js`](https://github.com/redis/node-redis/blob/master/examples/managing-json.js) in the [examples folder](https://github.com/redis/node-redis/tree/master/examples). ### Storing JSON Documents in Redis @@ -15,33 +17,27 @@ The [`JSON.SET`](https://redis.io/commands/json.set/) command stores a JSON valu Here, we'll store a JSON document in the root of the Redis key "`mydoc`": ```javascript -import { createClient } from 'redis'; - -... await client.json.set('noderedis:jsondata', '$', { name: 'Roberta McDonald', - pets: [ - { + pets: [{ name: 'Rex', species: 'dog', age: 3, isMammal: true - }, - { + }, { name: 'Goldie', species: 'fish', age: 2, isMammal: false - } - ] + }] }); ``` -For more information about RedisJSON's path syntax, [check out the documentation](https://redis.io/docs/stack/json/path/). +For more information about RedisJSON's path syntax, [check out the documentation](https://redis.io/docs/data-types/json/path/). ### Retrieving JSON Documents from Redis -With RedisJSON, we can retrieve all or part(s) of a JSON document using the [`JSON.GET`](https://redis.io/commands/json.get/) command and one or more JSON Paths. Let's get the name and age of one of the pets: +With RedisJSON, we can retrieve all or part(s) of a JSON document using the [`JSON.GET`](https://redis.io/commands/json.get/) command and one or more JSON Paths. Let's get the name and age of one of the pets: ```javascript const results = await client.json.get('noderedis:jsondata', { diff --git a/packages/json/package.json b/packages/json/package.json index 12cfd674c4f..53711a5c0b6 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -17,6 +17,9 @@ "devDependencies": { "@redis/test-utils": "*" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/redis/README.md b/packages/redis/README.md index 23307bb6e24..8afb99836f3 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -1,32 +1,5 @@ # Node-Redis -[![Tests](https://img.shields.io/github/actions/workflow/status/redis/node-redis/tests.yml?branch=master)](https://github.com/redis/node-redis/actions/workflows/tests.yml) -[![Coverage](https://codecov.io/gh/redis/node-redis/branch/master/graph/badge.svg?token=xcfqHhJC37)](https://codecov.io/gh/redis/node-redis) -[![License](https://img.shields.io/github/license/redis/node-redis.svg)](https://github.com/redis/node-redis/blob/master/LICENSE) - -[![Discord](https://img.shields.io/discord/697882427875393627.svg?style=social&logo=discord)](https://discord.gg/redis) -[![Twitch](https://img.shields.io/twitch/status/redisinc?style=social)](https://www.twitch.tv/redisinc) -[![YouTube](https://img.shields.io/youtube/channel/views/UCD78lHSwYqMlyetR0_P4Vig?style=social)](https://www.youtube.com/redisinc) -[![Twitter](https://img.shields.io/twitter/follow/redisinc?style=social)](https://twitter.com/redisinc) - -node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js. - -## Installation - -Start a redis via docker: - -``` bash -docker run -p 6379:6379 -it redis/redis-stack-server:latest -``` - -To install node-redis, simply: - -```bash -npm install redis -``` - -Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! - ## Usage ### Basic Example @@ -43,7 +16,7 @@ const value = await client.get('key'); await client.close(); ``` -> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. +> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#error-events) for more details. 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]`: @@ -55,6 +28,8 @@ createClient({ 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). +### Connection State + To client exposes 2 `boolean`s that track the client state: 1. `isOpen` - the client is either connecting or connected. 2. `isReady` - the client is connected and ready to send @@ -175,7 +150,7 @@ await Promise.all([ ### Events -The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes: +The client extends `EventEmitter` and emits the following events: | Name | When | Listener arguments | |-------------------------|------------------------------------------------------------------------------------|------------------------------------------------------------| @@ -186,11 +161,9 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each | `reconnecting` | Client is trying to reconnect to the server | *No arguments* | | `sharded-channel-moved` | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | -> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details. - -> The client will not emit [any other events](../../docs/v3-to-v4.md#all-the-removed-events) beyond those listed above. +> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#error-events) for more details. -### Links +### Read more - [Transactions (`MULTI`/`EXEC`)](../../docs/transactions.md). - [Pub/Sub](../../docs/pub-sub.md). @@ -200,6 +173,7 @@ The Node Redis client class is an Nodejs EventEmitter and it emits an event each - [Pool](../../docs/pool.md). - [Clustering](../../docs/clustering.md). - [Sentinel](../../docs/sentinel.md). +- [FAQ](../../docs/FAQ.md). ## Supported Redis versions diff --git a/packages/redis/package.json b/packages/redis/package.json index 40cd3901483..0603e6c9480 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -17,6 +17,9 @@ "@redis/search": "2.0.0-next.2", "@redis/time-series": "2.0.0-next.2" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/search/README.md b/packages/search/README.md index 60186ba7f92..70a91fdeb2f 100644 --- a/packages/search/README.md +++ b/packages/search/README.md @@ -1,18 +1,20 @@ # @redis/search -This package provides support for the [RediSearch](https://redisearch.io) module, which adds indexing and querying support for data stored in Redis Hashes or as JSON documents with the RedisJSON module. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RediSearch commands. +This package provides support for the [RediSearch](https://redis.io/docs/interact/search-and-query/) module, which adds indexing and querying support for data stored in Redis Hashes or as JSON documents with the [RedisJSON](https://redis.io/docs/data-types/json/) module. -To use these extra commands, your Redis server must have the RediSearch module installed. To index and query JSON documents, you'll also need to add the RedisJSON module. +Should be used with [`redis`/`@redis/client`](https://github.com/redis/node-redis). + +:warning: To use these extra commands, your Redis server must have the RediSearch module installed. To index and query JSON documents, you'll also need to add the RedisJSON module. ## Usage -For complete examples, see [`search-hashes.js`](https://github.com/redis/node-redis/blob/master/examples/search-hashes.js) and [`search-json.js`](https://github.com/redis/node-redis/blob/master/examples/search-json.js) in the Node Redis examples folder. +For complete examples, see [`search-hashes.js`](https://github.com/redis/node-redis/blob/master/examples/search-hashes.js) and [`search-json.js`](https://github.com/redis/node-redis/blob/master/examples/search-json.js) in the [examples folder](https://github.com/redis/node-redis/tree/master/examples). ### Indexing and Querying Data in Redis Hashes #### Creating an Index -Before we can perform any searches, we need to tell RediSearch how to index our data, and which Redis keys to find that data in. The [FT.CREATE](https://redis.io/commands/ft.create) command creates a RediSearch index. Here's how to use it to create an index we'll call `idx:animals` where we want to index hashes containing `name`, `species` and `age` fields, and whose key names in Redis begin with the prefix `noderedis:animals`: +Before we can perform any searches, we need to tell RediSearch how to index our data, and which Redis keys to find that data in. The [FT.CREATE](https://redis.io/commands/ft.create) command creates a RediSearch index. Here's how to use it to create an index we'll call `idx:animals` where we want to index hashes containing `name`, `species` and `age` fields, and whose key names in Redis begin with the prefix `noderedis:animals`: ```javascript await client.ft.create('idx:animals', { diff --git a/packages/search/package.json b/packages/search/package.json index 67bb18da5d2..ea6c8a6b4c2 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -17,6 +17,9 @@ "devDependencies": { "@redis/test-utils": "*" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/packages/time-series/README.md b/packages/time-series/README.md index 5923979cd48..ff42bfb6b3d 100644 --- a/packages/time-series/README.md +++ b/packages/time-series/README.md @@ -1,8 +1,10 @@ # @redis/time-series -This package provides support for the [RedisTimeSeries](https://redistimeseries.io) module, which adds a time series data structure to Redis. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RedisTimeSeries commands. +This package provides support for the [RedisTimeSeries](https://redis.io/docs/data-types/timeseries/) module, which adds a time series data structure to Redis. -To use these extra commands, your Redis server must have the RedisTimeSeries module installed. +Should be used with [`redis`/`@redis/client`](https://github.com/redis/node-redis). + +:warning: To use these extra commands, your Redis server must have the RedisTimeSeries module installed. ## Usage @@ -20,20 +22,18 @@ import { createClient } from 'redis'; import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding, TimeSeriesAggregationType } from '@redis/time-series'; ... - - const created = await client.ts.create('temperature', { - RETENTION: 86400000, // 1 day in milliseconds - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, // No compression - When not specified, the option is set to COMPRESSED - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, // No duplicates - When not specified: set to the global DUPLICATE_POLICY configuration of the database (which by default, is BLOCK). - }); - - if (created === 'OK') { - console.log('Created timeseries.'); - } else { - console.log('Error creating timeseries :('); - process.exit(1); - } - +const created = await client.ts.create('temperature', { + RETENTION: 86400000, // 1 day in milliseconds + ENCODING: TimeSeriesEncoding.UNCOMPRESSED, // No compression - When not specified, the option is set to COMPRESSED + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, // No duplicates - When not specified: set to the global DUPLICATE_POLICY configuration of the database (which by default, is BLOCK). +}); + +if (created === 'OK') { + console.log('Created timeseries.'); +} else { + console.log('Error creating timeseries :('); + process.exit(1); +} ``` ### Adding new value to a Time Series data structure in Redis @@ -43,33 +43,31 @@ With RedisTimeSeries, we can add a single value to time series data structure us ```javascript let value = Math.floor(Math.random() * 1000) + 1; // Random data point value - let currentTimestamp = 1640995200000; // Jan 1 2022 00:00:00 - let num = 0; - - while (num < 10000) { - // Add a new value to the timeseries, providing our own timestamp: - // https://redis.io/commands/ts.add/ - await client.ts.add('temperature', currentTimestamp, value); - console.log(`Added timestamp ${currentTimestamp}, value ${value}.`); - - num += 1; - value = Math.floor(Math.random() * 1000) + 1; // Get another random value - currentTimestamp += 1000; // Move on one second. - } - - // Add multiple values to the timeseries in round trip to the server: - // https://redis.io/commands/ts.madd/ - const response = await client.ts.mAdd([{ - key: 'temperature', - timestamp: currentTimestamp + 60000, - value: Math.floor(Math.random() * 1000) + 1 - }, { - key: 'temperature', - timestamp: currentTimestamp + 120000, - value: Math.floor(Math.random() * 1000) + 1 - }]); - - +let currentTimestamp = 1640995200000; // Jan 1 2022 00:00:00 +let num = 0; + +while (num < 10000) { + // Add a new value to the timeseries, providing our own timestamp: + // https://redis.io/commands/ts.add/ + await client.ts.add('temperature', currentTimestamp, value); + console.log(`Added timestamp ${currentTimestamp}, value ${value}.`); + + num += 1; + value = Math.floor(Math.random() * 1000) + 1; // Get another random value + currentTimestamp += 1000; // Move on one second. +} + +// Add multiple values to the timeseries in round trip to the server: +// https://redis.io/commands/ts.madd/ +const response = await client.ts.mAdd([{ + key: 'temperature', + timestamp: currentTimestamp + 60000, + value: Math.floor(Math.random() * 1000) + 1 +}, { + key: 'temperature', + timestamp: currentTimestamp + 120000, + value: Math.floor(Math.random() * 1000) + 1 +}]); ``` ### Retrieving Time Series data from Redis @@ -77,31 +75,29 @@ let value = Math.floor(Math.random() * 1000) + 1; // Random data point value With RedisTimeSeries, we can retrieve the time series data using the [`TS.RANGE`](https://redis.io/commands/ts.range/) command by passing the criteria as follows: ```javascript - // Query the timeseries with TS.RANGE: - // https://redis.io/commands/ts.range/ - const fromTimestamp = 1640995200000; // Jan 1 2022 00:00:00 - const toTimestamp = 1640995260000; // Jan 1 2022 00:01:00 - const rangeResponse = await client.ts.range('temperature', fromTimestamp, toTimestamp, { - // Group into 10 second averages. - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 10000 - } - }); - - console.log('RANGE RESPONSE:'); - // rangeResponse looks like: - // [ - // { timestamp: 1640995200000, value: 356.8 }, - // { timestamp: 1640995210000, value: 534.8 }, - // { timestamp: 1640995220000, value: 481.3 }, - // { timestamp: 1640995230000, value: 437 }, - // { timestamp: 1640995240000, value: 507.3 }, - // { timestamp: 1640995250000, value: 581.2 }, - // { timestamp: 1640995260000, value: 600 } - // ] - +// https://redis.io/commands/ts.range/ +const fromTimestamp = 1640995200000; // Jan 1 2022 00:00:00 +const toTimestamp = 1640995260000; // Jan 1 2022 00:01:00 +const rangeResponse = await client.ts.range('temperature', fromTimestamp, toTimestamp, { + // Group into 10 second averages. + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 10000 + } +}); + +console.log('RANGE RESPONSE:'); +// rangeResponse looks like: +// [ +// { timestamp: 1640995200000, value: 356.8 }, +// { timestamp: 1640995210000, value: 534.8 }, +// { timestamp: 1640995220000, value: 481.3 }, +// { timestamp: 1640995230000, value: 437 }, +// { timestamp: 1640995240000, value: 507.3 }, +// { timestamp: 1640995250000, value: 581.2 }, +// { timestamp: 1640995260000, value: 600 } +// ] ``` ### Altering Time Series data Stored in Redis @@ -111,12 +107,10 @@ RedisTimeSeries includes commands that can update values in a time series data s Using the [`TS.ALTER`](https://redis.io/commands/ts.alter/) command, we can update time series retention like this: ```javascript - - // https://redis.io/commands/ts.alter/ - const alterResponse = await client.ts.alter('temperature', { - RETENTION: 0 // Keep the entries forever - }); - +// https://redis.io/commands/ts.alter/ +const alterResponse = await client.ts.alter('temperature', { + RETENTION: 0 // Keep the entries forever +}); ``` ### Retrieving Information about the timeseries Stored in Redis @@ -126,26 +120,24 @@ RedisTimeSeries also includes commands that can help to view the information on Using the [`TS.INFO`](https://redis.io/commands/ts.info/) command, we can view timeseries information like this: ```javascript - - // Get some information about the state of the timeseries. - // https://redis.io/commands/ts.info/ - const tsInfo = await client.ts.info('temperature'); - - // tsInfo looks like this: - // { - // totalSamples: 1440, - // memoryUsage: 28904, - // firstTimestamp: 1641508920000, - // lastTimestamp: 1641595320000, - // retentionTime: 86400000, - // chunkCount: 7, - // chunkSize: 4096, - // chunkType: 'uncompressed', - // duplicatePolicy: 'block', - // labels: [], - // sourceKey: null, - // rules: [] - // } - +// Get some information about the state of the timeseries. +// https://redis.io/commands/ts.info/ +const tsInfo = await client.ts.info('temperature'); + +// tsInfo looks like this: +// { +// totalSamples: 1440, +// memoryUsage: 28904, +// firstTimestamp: 1641508920000, +// lastTimestamp: 1641595320000, +// retentionTime: 86400000, +// chunkCount: 7, +// chunkSize: 4096, +// chunkType: 'uncompressed', +// duplicatePolicy: 'block', +// labels: [], +// sourceKey: null, +// rules: [] +// } ``` diff --git a/packages/time-series/package.json b/packages/time-series/package.json index 8f42844e95f..e0317fd231f 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -17,6 +17,9 @@ "devDependencies": { "@redis/test-utils": "*" }, + "engines": { + "node": ">= 18" + }, "repository": { "type": "git", "url": "git://github.com/redis/node-redis.git" diff --git a/tsconfig.base.json b/tsconfig.base.json index bb779b5407d..bd2bcac0845 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,8 +1,8 @@ { "compilerOptions": { "lib": ["ES2023"], - "module": "CommonJS", - "moduleResolution": "Node", + "module": "NodeNext", + "moduleResolution": "NodeNext", "target": "ES2022", "strict": true, @@ -12,7 +12,9 @@ "skipLibCheck": true, "composite": true, + "sourceMap": true, "declaration": true, + "declarationMap": true, "allowJs": true } } From 77ecdf2721a02bbe8dfea6edfb3b6a596b2df605 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 12 Feb 2024 18:38:00 -0500 Subject: [PATCH 308/325] fix #2679 - fix socket types, and clean some code --- docs/client-configuration.md | 53 +++--- docs/v4-to-v5.md | 38 ++-- packages/client/lib/client/index.ts | 4 +- packages/client/lib/client/socket.ts | 273 +++++++++++++++------------ 4 files changed, 205 insertions(+), 163 deletions(-) diff --git a/docs/client-configuration.md b/docs/client-configuration.md index 1854f07158a..69a2db16c37 100644 --- a/docs/client-configuration.md +++ b/docs/client-configuration.md @@ -1,31 +1,32 @@ # `createClient` configuration -| Property | Default | Description | -|--------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| url | | `redis[s]://[[username][:password]@][host][:port][/db-number]` (see [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details) | -| socket | | Socket connection properties. Unlisted [`net.connect`](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) properties (and [`tls.connect`](https://nodejs.org/api/tls.html#tlsconnectoptions-callback)) are also supported | -| socket.port | `6379` | Redis server port | -| socket.host | `'localhost'` | Redis server hostname | -| socket.family | `0` | IP Stack version (one of `4 \| 6 \| 0`) | -| socket.path | | Path to the UNIX Socket | -| socket.connectTimeout | `5000` | Connection Timeout (in milliseconds) | -| socket.noDelay | `true` | Toggle [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) | -| socket.keepAlive | `5000` | Toggle [`keep-alive`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) functionality | -| socket.tls | | See explanation and examples [below](#TLS) | -| socket.reconnectStrategy | `retries => Math.min(retries * 50, 500)` | A function containing the [Reconnect Strategy](#reconnect-strategy) logic | -| username | | ACL username ([see ACL guide](https://redis.io/topics/acl)) | -| password | | ACL password or the old "--requirepass" password | -| name | | Client name ([see `CLIENT SETNAME`](https://redis.io/commands/client-setname)) | -| database | | Redis database number (see [`SELECT`](https://redis.io/commands/select) command) | -| modules | | Included [Redis Modules](../README.md#packages) | -| scripts | | Script definitions (see [Lua Scripts](../README.md#lua-scripts)) | -| functions | | Function definitions (see [Functions](../README.md#functions)) | -| commandsQueueMaxLength | | Maximum length of the client's internal command queue | -| disableOfflineQueue | `false` | Disables offline queuing, see [FAQ](./FAQ.md#what-happens-when-the-network-goes-down) | -| readonly | `false` | Connect in [`READONLY`](https://redis.io/commands/readonly) mode | -| legacyMode | `false` | Maintain some backwards compatibility (see the [Migration Guide](./v3-to-v4.md)) | -| isolationPoolOptions | | See the [Isolated Execution Guide](./isolated-execution.md) | -| pingInterval | | Send `PING` command at interval (in ms). Useful with ["Azure Cache for Redis"](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-best-practices-connection#idle-timeout) | +| Property | Default | Description | +|------------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| url | | `redis[s]://[[username][:password]@][host][:port][/db-number]` (see [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details) | +| socket | | Socket connection properties. Unlisted [`net.connect`](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) properties (and [`tls.connect`](https://nodejs.org/api/tls.html#tlsconnectoptions-callback)) are also supported | +| socket.port | `6379` | Redis server port | +| socket.host | `'localhost'` | Redis server hostname | +| socket.family | `0` | IP Stack version (one of `4 \| 6 \| 0`) | +| socket.path | | Path to the UNIX Socket | +| socket.connectTimeout | `5000` | Connection timeout (in milliseconds) | +| socket.noDelay | `true` | Toggle [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) | +| socket.keepAlive | `true` | Toggle [`keep-alive`](https://nodejs.org/api/net.html#socketsetkeepaliveenable-initialdelay) functionality | +| socket.keepAliveInitialDelay | `5000` | If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket | +| socket.tls | | See explanation and examples [below](#TLS) | +| socket.reconnectStrategy | `retries => Math.min(retries * 50, 500)` | A function containing the [Reconnect Strategy](#reconnect-strategy) logic | +| username | | ACL username ([see ACL guide](https://redis.io/topics/acl)) | +| password | | ACL password or the old "--requirepass" password | +| name | | Client name ([see `CLIENT SETNAME`](https://redis.io/commands/client-setname)) | +| database | | Redis database number (see [`SELECT`](https://redis.io/commands/select) command) | +| modules | | Included [Redis Modules](../README.md#packages) | +| scripts | | Script definitions (see [Lua Scripts](../README.md#lua-scripts)) | +| functions | | Function definitions (see [Functions](../README.md#functions)) | +| commandsQueueMaxLength | | Maximum length of the client's internal command queue | +| disableOfflineQueue | `false` | Disables offline queuing, see [FAQ](./FAQ.md#what-happens-when-the-network-goes-down) | +| readonly | `false` | Connect in [`READONLY`](https://redis.io/commands/readonly) mode | +| legacyMode | `false` | Maintain some backwards compatibility (see the [Migration Guide](./v3-to-v4.md)) | +| isolationPoolOptions | | See the [Isolated Execution Guide](./isolated-execution.md) | +| pingInterval | | Send `PING` command at interval (in ms). Useful with ["Azure Cache for Redis"](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-best-practices-connection#idle-timeout) | ## Reconnect Strategy diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index 0863c7478a9..fb68656d5ce 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -1,5 +1,27 @@ # v4 to v5 migration guide +## Client Configuration + +### Keep Alive + +To better align with Node.js build-in [`net`](https://nodejs.org/api/net.html) and [`tls`](https://nodejs.org/api/tls.html) modules, the `keepAlive` option has been split into 2 options: `keepAlive` (`boolean`) and `keepAliveInitialDelay` (`number`). The defaults remain `true` and `5000`. + +### Legacy Mode + +In the previous version, you could access "legacy" mode by creating a client and passing in `{ legacyMode: true }`. Now, you can create one off of an existing client by calling the `.legacy()` function. This allows easier access to both APIs and enables better TypeScript support. + +```javascript +// use `client` for the current API +const client = createClient(); +await client.set('key', 'value'); + +// use `legacyClient` for the "legacy" API +const legacyClient = client.legacy(); +legacyClient.set('key', 'value', (err, reply) => { + // ... +}); +``` + ## Command Options In v4, command options are passed as a first optional argument: @@ -59,22 +81,6 @@ for await (const keys of client.scanIterator()) { for more information, see the [Scan Iterators guide](./scan-iterators.md). -## Legacy Mode - -In the previous version, you could access "legacy" mode by creating a client and passing in `{ legacyMode: true }`. Now, you can create one off of an existing client by calling the `.legacy()` function. This allows easier access to both APIs and enables better TypeScript support. - -```javascript -// use `client` for the current API -const client = createClient(); -await client.set('key', 'value'); - -// use `legacyClient` for the "legacy" API -const legacyClient = client.legacy(); -legacyClient.set('key', 'value', (err, reply) => { - // ... -}); -``` - ## Isolation Pool [TODO](./blocking-commands.md). diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 041b0b7225c..e77396d91a4 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -1,5 +1,5 @@ import COMMANDS from '../commands'; -import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket'; +import RedisSocket, { RedisSocketOptions } from './socket'; import RedisCommandsQueue, { CommandOptions } from './commands-queue'; import { EventEmitter } from 'node:events'; import { attachConfig, functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; @@ -244,7 +244,7 @@ export default class RedisClient< }; if (protocol === 'rediss:') { - (parsed.socket as RedisTlsSocketOptions).tls = true; + parsed!.socket!.tls = true; } else if (protocol !== 'redis:') { throw new TypeError('Invalid protocol'); } diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index ca75016d987..03dbcde1546 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -1,84 +1,65 @@ -import { EventEmitter } from 'node:events'; -import * as net from 'node:net'; -import * as tls from 'node:tls'; +import { EventEmitter, once } from 'node:events'; +import net from 'node:net'; +import tls from 'node:tls'; import { ConnectionTimeoutError, ClientClosedError, SocketClosedUnexpectedlyError, ReconnectStrategyError } from '../errors'; import { setTimeout } from 'node:timers/promises'; import { RedisArgument } from '../RESP/types'; -export interface RedisSocketCommonOptions { +type NetOptions = { + tls?: false; +}; + +type TcpOptions = NetOptions & Omit< + net.TcpNetConnectOpts, + 'timeout' | 'onread' | 'readable' | 'writable' | 'port' +> & { + port?: number; +}; + +type IpcOptions = NetOptions & Omit< + net.IpcNetConnectOpts, + 'timeout' | 'onread' | 'readable' | 'writable' +>; + +type TlsOptions = { + tls: true; +} & tls.ConnectionOptions; + +type ReconnectStrategyFunction = (retries: number, cause: Error) => false | Error | number; + +export type RedisSocketOptions = { /** - * Connection Timeout (in milliseconds) + * Connection timeout (in milliseconds) */ connectTimeout?: number; - /** - * Toggle [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) - */ - noDelay?: boolean; - /** - * Toggle [`keep-alive`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) - */ - keepAlive?: number | false; /** * When the socket closes unexpectedly (without calling `.close()`/`.destroy()`), the client uses `reconnectStrategy` to decide what to do. The following values are supported: * 1. `false` -> do not reconnect, close the client and flush the command queue. * 2. `number` -> wait for `X` milliseconds before reconnecting. * 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. - * Defaults to `retries => Math.min(retries * 50, 500)` */ - reconnectStrategy?: false | number | ((retries: number, cause: Error) => false | Error | number); -} - -export interface RedisNetConnectOpts extends Omit, 'keepAlive'>, Partial, RedisSocketCommonOptions { - tls?: false; -}; - -export interface RedisTlsSocketOptions extends Partial, RedisSocketCommonOptions { - tls: true; -}; - -export type RedisSocketOptions = RedisNetConnectOpts | RedisTlsSocketOptions - -interface CreateSocketReturn { - connectEvent: string; - socket: T; -} + reconnectStrategy?: false | number | ReconnectStrategyFunction; +} & (TcpOptions | IpcOptions | TlsOptions); export type RedisSocketInitiator = () => void | Promise; export default class RedisSocket extends EventEmitter { - static #initiateOptions(options?: RedisSocketOptions): RedisSocketOptions { - options ??= {}; - if (!(options as net.IpcSocketConnectOpts).path) { - (options as net.TcpSocketConnectOpts).port ??= 6379; - (options as net.TcpSocketConnectOpts).host ??= 'localhost'; - } - - options.connectTimeout ??= 5000; - options.keepAlive ??= 5000; - options.noDelay ??= true; - - return options; - } - - static #isTlsSocket(options: RedisSocketOptions): options is RedisTlsSocketOptions { - return (options as RedisTlsSocketOptions).tls === true; - } - - readonly #initiator: RedisSocketInitiator; - - readonly #options: RedisSocketOptions; + readonly #initiator; + readonly #connectTimeout; + readonly #reconnectStrategy; + readonly #socketFactory; #socket?: net.Socket | tls.TLSSocket; #isOpen = false; - get isOpen(): boolean { + get isOpen() { return this.#isOpen; } #isReady = false; - get isReady(): boolean { + get isReady() { return this.#isReady; } @@ -88,28 +69,101 @@ export default class RedisSocket extends EventEmitter { super(); this.#initiator = initiator; - this.#options = RedisSocket.#initiateOptions(options); + this.#connectTimeout = options?.connectTimeout ?? 5000; + this.#reconnectStrategy = this.#createReconnectStrategy(options); + this.#socketFactory = this.#createSocketFactory(options); } - #reconnectStrategy(retries: number, cause: Error) { - if (this.#options.reconnectStrategy === false) { - return false; - } else if (typeof this.#options.reconnectStrategy === 'number') { - return this.#options.reconnectStrategy; - } else if (this.#options.reconnectStrategy) { - try { - const retryIn = this.#options.reconnectStrategy(retries, cause); - if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { - throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); + #createReconnectStrategy(options?: RedisSocketOptions): ReconnectStrategyFunction { + const strategy = options?.reconnectStrategy; + if (strategy === false || typeof strategy === 'number') { + return () => strategy; + } + + if (strategy) { + return (retries, cause) => { + try { + const retryIn = strategy(retries, cause); + if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== 'number') { + throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); + } + return retryIn; + } catch (err) { + this.emit('error', err); + return Math.min(retries * 50, 500); } + }; + } - return retryIn; - } catch (err) { - this.emit('error', err); - } + return retries => Math.min(retries * 50, 500); + } + + #createSocketFactory(options?: RedisSocketOptions) { + // TLS + if (options?.tls === true) { + const withDefaults: tls.ConnectionOptions = { + ...options, + port: options?.port ?? 6379, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + noDelay: options?.noDelay ?? true, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + keepAlive: options?.keepAlive ?? true, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + keepAliveInitialDelay: options?.keepAliveInitialDelay ?? 5000, + timeout: undefined, + onread: undefined, + readable: true, + writable: true + }; + return { + create() { + return tls.connect(withDefaults); + }, + event: 'secureConnect' + }; } - return Math.min(retries * 50, 500); + // IPC + if (options && 'path' in options) { + const withDefaults: net.IpcNetConnectOpts = { + ...options, + timeout: undefined, + onread: undefined, + readable: true, + writable: true + }; + return { + create() { + return net.createConnection(withDefaults); + }, + event: 'connect' + }; + } + + // TCP + const withDefaults: net.TcpNetConnectOpts = { + ...options, + port: options?.port ?? 6379, + noDelay: options?.noDelay ?? true, + keepAlive: options?.keepAlive ?? true, + keepAliveInitialDelay: options?.keepAliveInitialDelay ?? 5000, + timeout: undefined, + onread: undefined, + readable: true, + writable: true + }; + return { + create() { + return net.createConnection(withDefaults); + }, + event: 'connect' + }; } #shouldReconnect(retries: number, cause: Error) { @@ -164,56 +218,37 @@ export default class RedisSocket extends EventEmitter { } } while (this.#isOpen && !this.#isReady); } + + async #createSocket(): Promise { + const socket = this.#socketFactory.create(); + + let onTimeout; + if (this.#connectTimeout !== undefined) { + onTimeout = () => socket.destroy(new ConnectionTimeoutError()); + socket.once('timeout', onTimeout); + socket.setTimeout(this.#connectTimeout); + } - #createSocket(): Promise { - return new Promise((resolve, reject) => { - const { connectEvent, socket } = RedisSocket.#isTlsSocket(this.#options) ? - this.#createTlsSocket() : - this.#createNetSocket(); - - if (this.#options.connectTimeout) { - socket.setTimeout(this.#options.connectTimeout, () => socket.destroy(new ConnectionTimeoutError())); - } + if (this.#isSocketUnrefed) { + socket.unref(); + } - if (this.#isSocketUnrefed) { - socket.unref(); - } + await once(socket, this.#socketFactory.event); - socket - .setNoDelay(this.#options.noDelay) - .once('error', reject) - .once(connectEvent, () => { - socket - .setTimeout(0) - // https://github.com/nodejs/node/issues/31663 - .setKeepAlive(this.#options.keepAlive !== false, this.#options.keepAlive || 0) - .off('error', reject) - .once('error', (err: Error) => this.#onSocketError(err)) - .once('close', hadError => { - if (!hadError && this.#isOpen && this.#socket === socket) { - this.#onSocketError(new SocketClosedUnexpectedlyError()); - } - }) - .on('drain', () => this.emit('drain')) - .on('data', data => this.emit('data', data)); - - resolve(socket); - }); - }); - } + if (onTimeout) { + socket.removeListener('timeout', onTimeout); + } - #createNetSocket(): CreateSocketReturn { - return { - connectEvent: 'connect', - socket: net.connect(this.#options as net.NetConnectOpts) // TODO - }; - } + socket + .once('error', err => this.#onSocketError(err)) + .once('close', hadError => { + if (hadError || !this.#isOpen || this.#socket !== socket) return; + this.#onSocketError(new SocketClosedUnexpectedlyError()); + }) + .on('drain', () => this.emit('drain')) + .on('data', data => this.emit('data', data)); - #createTlsSocket(): CreateSocketReturn { - return { - connectEvent: 'secureConnect', - socket: tls.connect(this.#options as tls.ConnectionOptions) // TODO - }; + return socket; } #onSocketError(err: Error): void { @@ -229,11 +264,11 @@ export default class RedisSocket extends EventEmitter { }); } - write(iterator: IterableIterator>): void { + write(iterable: Iterable>) { if (!this.#socket) return; this.#socket.cork(); - for (const args of iterator) { + for (const args of iterable) { for (const toWrite of args) { this.#socket.write(toWrite); } @@ -282,12 +317,12 @@ export default class RedisSocket extends EventEmitter { this.emit('end'); } - ref(): void { + ref() { this.#isSocketUnrefed = false; this.#socket?.ref(); } - unref(): void { + unref() { this.#isSocketUnrefed = true; this.#socket?.unref(); } From 65eb69a787ad75204f1d18806cd1c55423a277f1 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 12 Feb 2024 18:38:09 -0500 Subject: [PATCH 309/325] fix legacy client command functions - do not return "empty" promise --- packages/client/lib/client/legacy-mode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index b30ebc68bc2..03e7cf4efe1 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -57,7 +57,7 @@ export class RedisLegacyClient { static #createCommand(name: string, command: Command, resp: RespVersions) { const transformReply = RedisLegacyClient.getTransformReply(command, resp); - return async function (this: RedisLegacyClient, ...args: LegacyCommandArguments) { + return function (this: RedisLegacyClient, ...args: LegacyCommandArguments) { const redisArgs = [name], callback = RedisLegacyClient.#transformArguments(redisArgs, args), promise = this.#client.sendCommand(redisArgs); From cc85112e54d555b0daabcb5a5399b44b3d0a499f Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 12 Feb 2024 18:38:18 -0500 Subject: [PATCH 310/325] remove console.log --- packages/client/lib/client/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index e77396d91a4..3a14dc40e1a 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -460,9 +460,7 @@ export default class RedisClient< }) .on('reconnecting', () => this.emit('reconnecting')) .on('drain', () => this.#maybeScheduleWrite()) - .on('end', () => { - console.log('socket on end, emitting end', this.emit('end')); - }); + .on('end', () => this.emit('end')); } #pingTimer?: NodeJS.Timeout; From 2309d09ca1072b179dc0e06194f87f5393c2e7c2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 15 Feb 2024 09:57:25 -0500 Subject: [PATCH 311/325] fix socket type issues --- packages/client/lib/cluster/cluster-slots.ts | 10 +- packages/client/lib/sentinel/index.ts | 114 +++++++++--------- packages/client/lib/sentinel/pub-sub-proxy.ts | 20 ++- 3 files changed, 68 insertions(+), 76 deletions(-) diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index f78dad984ce..824cf2ae813 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -5,6 +5,7 @@ import { EventEmitter } from 'node:stream'; import { ChannelListeners, PUBSUB_TYPE, PubSubTypeListeners } from '../client/pub-sub'; import { RedisArgument, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; import calculateSlot from 'cluster-key-slot'; +import { RedisSocketOptions } from '../client/socket'; interface NodeAddress { host: string; @@ -102,8 +103,8 @@ export default class RedisClusterSlots< > { static #SLOTS = 16384; - readonly #options: RedisClusterOptions; - readonly #clientFactory: ReturnType>; + readonly #options; + readonly #clientFactory; readonly #emit: EventEmitter['emit']; slots = new Array>(RedisClusterSlots.#SLOTS); masters = new Array>(); @@ -271,7 +272,7 @@ export default class RedisClusterSlots< return { ...this.#options.defaults, ...options, - socket + socket: socket as RedisSocketOptions }; } @@ -316,8 +317,7 @@ export default class RedisClusterSlots< host: node.host, port: node.port }, - readonly, - RESP: this.#options.RESP + readonly }) ).on('error', err => console.error(err)); } diff --git a/packages/client/lib/sentinel/index.ts b/packages/client/lib/sentinel/index.ts index 36253044756..210bf954ea9 100644 --- a/packages/client/lib/sentinel/index.ts +++ b/packages/client/lib/sentinel/index.ts @@ -649,19 +649,15 @@ class RedisSentinelInternal< } #createClient(node: RedisNode, clientOptions: RedisClientOptions, reconnectStrategy?: undefined | false) { - const options = { ...clientOptions } as RedisClientOptions; - - if (clientOptions.socket) { - options.socket = { ...clientOptions.socket }; - } else { - options.socket = {}; - } - - options.socket.host = node.host; - options.socket.port = node.port; - options.socket.reconnectStrategy = reconnectStrategy; - - return RedisClient.create(options); + return RedisClient.create({ + ...clientOptions, + socket: { + ...clientOptions.socket, + host: node.host, + port: node.port, + reconnectStrategy + } + }); } getClientLease(): ClientInfo | Promise { @@ -1332,16 +1328,16 @@ export class RedisSentinelFactory extends EventEmitter { async updateSentinelRootNodes() { for (const node of this.#sentinelRootNodes) { - const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; - if (options.socket === undefined) { - options.socket = {}; - } - options.socket.host = node.host; - options.socket.port = node.port; - options.socket.reconnectStrategy = false; - options.modules = RedisSentinelModule; - - const client = RedisClient.create(options).on('error', (err) => this.emit(`updateSentinelRootNodes: ${err}`)); + const client = RedisClient.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: RedisSentinelModule + }).on('error', (err) => this.emit(`updateSentinelRootNodes: ${err}`)); try { await client.connect(); } catch { @@ -1367,16 +1363,16 @@ export class RedisSentinelFactory extends EventEmitter { let connected = false; for (const node of this.#sentinelRootNodes) { - const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; - if (options.socket === undefined) { - options.socket = {}; - } - options.socket.host = node.host; - options.socket.port = node.port; - options.socket.reconnectStrategy = false; - options.modules = RedisSentinelModule; - - const client = RedisClient.create(options).on('error', err => this.emit(`getMasterNode: ${err}`)); + const client = RedisClient.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: RedisSentinelModule + }).on('error', err => this.emit(`getMasterNode: ${err}`)); try { await client.connect(); @@ -1412,30 +1408,30 @@ export class RedisSentinelFactory extends EventEmitter { async getMasterClient() { const master = await this.getMasterNode(); - const options: RedisClientOptions = { ...this.options.nodeClientOptions }; - if (options.socket === undefined) { - options.socket = {}; - } - options.socket.host = master.host; - options.socket.port = master.port; - - return RedisClient.create(options);; + return RedisClient.create({ + ...this.options.nodeClientOptions, + socket: { + ...this.options.nodeClientOptions?.socket, + host: master.host, + port: master.port + } + }); } async getReplicaNodes() { let connected = false; for (const node of this.#sentinelRootNodes) { - const options: RedisClientOptions = { ...this.options.sentinelClientOptions }; - if (options.socket === undefined) { - options.socket = {}; - } - options.socket.host = node.host; - options.socket.port = node.port; - options.socket.reconnectStrategy = false; - options.modules = RedisSentinelModule; - - const client = RedisClient.create(options).on('error', err => this.emit(`getReplicaNodes: ${err}`)); + const client = RedisClient.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: RedisSentinelModule + }).on('error', err => this.emit(`getReplicaNodes: ${err}`)); try { await client.connect(); @@ -1480,13 +1476,13 @@ export class RedisSentinelFactory extends EventEmitter { this.#replicaIdx = 0; } - const options: RedisClientOptions = { ...this.options.nodeClientOptions }; - if (options.socket === undefined) { - options.socket = {}; - } - options.socket.host = replicas[this.#replicaIdx].host; - options.socket.port = replicas[this.#replicaIdx].port; - - return RedisClient.create(options); + return RedisClient.create({ + ...this.options.nodeClientOptions, + socket: { + ...this.options.nodeClientOptions?.socket, + host: replicas[this.#replicaIdx].host, + port: replicas[this.#replicaIdx].port + } + }); } } diff --git a/packages/client/lib/sentinel/pub-sub-proxy.ts b/packages/client/lib/sentinel/pub-sub-proxy.ts index a27f6e50c95..68a6c3b58e6 100644 --- a/packages/client/lib/sentinel/pub-sub-proxy.ts +++ b/packages/client/lib/sentinel/pub-sub-proxy.ts @@ -45,18 +45,14 @@ export class PubSubProxy extends EventEmitter { throw new Error("pubSubProxy: didn't define node to do pubsub against"); } - const options = { ...this.#clientOptions }; - - if (this.#clientOptions.socket) { - options.socket = { ...this.#clientOptions.socket }; - } else { - options.socket = {}; - } - - options.socket.host = this.#node.host; - options.socket.port = this.#node.port; - - return new RedisClient(options); + return new RedisClient({ + ...this.#clientOptions, + socket: { + ...this.#clientOptions.socket, + host: this.#node.host, + port: this.#node.port + } + }); } async #initiatePubSubClient(withSubscriptions = false) { From 5ba5e093a87b2c4353f1338dd6b4956597d74368 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 19 Feb 2024 13:10:38 -0800 Subject: [PATCH 312/325] Update pub-sub.md --- docs/pub-sub.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pub-sub.md b/docs/pub-sub.md index bd1d842e0e5..f295010a4a8 100644 --- a/docs/pub-sub.md +++ b/docs/pub-sub.md @@ -1,6 +1,6 @@ # Pub/Sub -The Pub/Sub API is implemented by `RedisClient` and `RedisCluster`. +The Pub/Sub API is implemented by `RedisClient`, `RedisCluster`, and `RedisSentinel`. ## Pub/Sub with `RedisClient` From cf5587ec4a44d349964610f8f047efc9e5928306 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 19 Feb 2024 13:18:40 -0800 Subject: [PATCH 313/325] Update pub-sub.md --- docs/pub-sub.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/pub-sub.md b/docs/pub-sub.md index f295010a4a8..7bbb0733c18 100644 --- a/docs/pub-sub.md +++ b/docs/pub-sub.md @@ -4,7 +4,9 @@ The Pub/Sub API is implemented by `RedisClient`, `RedisCluster`, and `RedisSenti ## Pub/Sub with `RedisClient` -Pub/Sub requires a dedicated stand-alone client. You can easily get one by `.duplicate()`ing an existing `RedisClient`: +### RESP2 + +Using RESP2, Pub/Sub "takes over" the connection (a client with subscriptions will not execute commands), therefore it requires a dedicated connection. You can easily get one by `.duplicate()`ing an existing `RedisClient`: ```javascript const subscriber = client.duplicate(); @@ -12,7 +14,7 @@ subscriber.on('error', err => console.error(err)); await subscriber.connect(); ``` -When working with a `RedisCluster`, this is handled automatically for you. +> When working with either `RedisCluster` or `RedisSentinel`, this is handled automatically for you. ### `sharded-channel-moved` event @@ -29,6 +31,8 @@ The event listener signature is as follows: ) ``` +> When working with `RedisCluster`, this is handled automatically for you. + ## Subscribing ```javascript @@ -39,7 +43,7 @@ await client.pSubscribe('channe*', listener); await client.sSubscribe('channel', listener); ``` -> ⚠️ Subscribing to the same channel more than once will create multiple listeners which will each be called when a message is recieved. +> ⚠️ Subscribing to the same channel more than once will create multiple listeners, each of which will be called when a message is received. ## Publishing From 06ba71370643d2995aab27f1c557c76685893417 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 19 Feb 2024 13:26:59 -0800 Subject: [PATCH 314/325] copy #2628 into v5 --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 783f6785bab..0706e1bb770 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,20 @@ node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js. +## How do I Redis? + +[Learn for free at Redis University](https://university.redis.com/) + +[Build faster with the Redis Launchpad](https://launchpad.redis.com/) + +[Try the Redis Cloud](https://redis.com/try-free/) + +[Dive in developer tutorials](https://developer.redis.com/) + +[Join the Redis community](https://redis.com/community/) + +[Work at Redis](https://redis.com/company/careers/jobs/) + ## Installation Start a redis-server via docker (or any other method you prefer): From 7e27f72f72eb79dbb7822babc3313c83e6c8bbfe Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 19 Feb 2024 13:28:47 -0800 Subject: [PATCH 315/325] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0706e1bb770..990204eb3df 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ npm install redis | [`redis`](./packages/redis) | The client with all the ["redis-stack"](https://github.com/redis-stack/redis-stack) modules | | [`@redis/client`](./packages/client) | The base clients (i.e `RedisClient`, `RedisCluster`, etc.) | | [`@redis/bloom`](./packages/bloom) | [Redis Bloom](https://redis.io/docs/data-types/probabilistic/) commands | -| [`redis/graph`](./packages/graph) | [Redis Graph](https://redis.io/docs/data-types/probabilistic/) commands | +| [`@redis/graph`](./packages/graph) | [Redis Graph](https://redis.io/docs/data-types/probabilistic/) commands | | [`@redis/json`](./packages/json) | [Redis JSON](https://redis.io/docs/data-types/json/) commands | | [`@redis/search`](./packages/search) | [RediSearch](https://redis.io/docs/interact/search-and-query/) commands | | [`@redis/time-series`](./packages/time-series) | [Redis Time-Series](https://redis.io/docs/data-types/timeseries/) commands | From 3e167912fbf55e20c9ffb8a8f09bb6778ce33b2c Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 21 Feb 2024 10:29:24 +0200 Subject: [PATCH 316/325] More fixes for socket issue (#2710) * more typing fixes * try to redo typing a bit and genericize to make better * use genericized cluster options for cluster as well --- packages/client/lib/client/index.ts | 5 ++-- packages/client/lib/client/socket.ts | 43 ++++++++++++++++----------- packages/client/lib/cluster/index.ts | 3 +- packages/client/lib/sentinel/index.ts | 16 ++++++---- packages/client/lib/sentinel/types.ts | 5 ++-- packages/client/lib/sentinel/utils.ts | 8 +++-- 6 files changed, 48 insertions(+), 32 deletions(-) diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 3a14dc40e1a..3efa793eeb9 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -21,7 +21,8 @@ export interface RedisClientOptions< F extends RedisFunctions = RedisFunctions, S extends RedisScripts = RedisScripts, RESP extends RespVersions = RespVersions, - TYPE_MAPPING extends TypeMapping = TypeMapping + TYPE_MAPPING extends TypeMapping = TypeMapping, + SocketOptions extends RedisSocketOptions = RedisSocketOptions > extends CommanderConfig { /** * `redis[s]://[[username][:password]@][host][:port][/db-number]` @@ -31,7 +32,7 @@ export interface RedisClientOptions< /** * Socket connection properties */ - socket?: RedisSocketOptions; + socket?: SocketOptions; /** * ACL username ([see ACL guide](https://redis.io/topics/acl)) */ diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index 03dbcde1546..dcadad4c3dd 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -9,25 +9,9 @@ type NetOptions = { tls?: false; }; -type TcpOptions = NetOptions & Omit< - net.TcpNetConnectOpts, - 'timeout' | 'onread' | 'readable' | 'writable' | 'port' -> & { - port?: number; -}; - -type IpcOptions = NetOptions & Omit< - net.IpcNetConnectOpts, - 'timeout' | 'onread' | 'readable' | 'writable' ->; - -type TlsOptions = { - tls: true; -} & tls.ConnectionOptions; - type ReconnectStrategyFunction = (retries: number, cause: Error) => false | Error | number; -export type RedisSocketOptions = { +type RedisSocketOptionsCommon = { /** * Connection timeout (in milliseconds) */ @@ -39,7 +23,30 @@ export type RedisSocketOptions = { * 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. */ reconnectStrategy?: false | number | ReconnectStrategyFunction; -} & (TcpOptions | IpcOptions | TlsOptions); +} + +type RedisTcpOptions = RedisSocketOptionsCommon & NetOptions & Omit< + net.TcpNetConnectOpts, + 'timeout' | 'onread' | 'readable' | 'writable' | 'port' +> & { + port?: number; +}; + +type RedisTlsOptions = RedisSocketOptionsCommon & tls.ConnectionOptions & { + tls: true; + host: string; +} + +type RedisIpcOptions = RedisSocketOptionsCommon & Omit< + net.IpcNetConnectOpts, + 'timeout' | 'onread' | 'readable' | 'writable' +> & { + tls: false; +} + +export type RedisTcpSocketOptions = RedisTcpOptions | RedisTlsOptions; + +export type RedisSocketOptions = RedisTcpSocketOptions | RedisIpcOptions; export type RedisSocketInitiator = () => void | Promise; diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index e26582942d2..d6018fc270e 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -8,6 +8,7 @@ import RedisClusterSlots, { NodeAddressMap, ShardNode } from './cluster-slots'; import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command'; import { PubSubListener } from '../client/pub-sub'; import { ErrorReply } from '../errors'; +import { RedisTcpSocketOptions } from '../client/socket'; interface ClusterCommander< M extends RedisModules, @@ -21,7 +22,7 @@ interface ClusterCommander< } export type RedisClusterClientOptions = Omit< - RedisClientOptions, + RedisClientOptions, keyof ClusterCommander >; diff --git a/packages/client/lib/sentinel/index.ts b/packages/client/lib/sentinel/index.ts index 210bf954ea9..57819133e0c 100644 --- a/packages/client/lib/sentinel/index.ts +++ b/packages/client/lib/sentinel/index.ts @@ -14,6 +14,8 @@ import { setTimeout } from 'node:timers/promises'; import RedisSentinelModule from './module' import { RedisVariadicArgument } from '../commands/generic-transformers'; import { WaitQueue } from './wait-queue'; +import { TcpNetConnectOpts } from 'node:net'; +import { RedisTcpSocketOptions } from '../client/socket'; interface ClientInfo { id: number; @@ -578,8 +580,8 @@ class RedisSentinelInternal< } readonly #name: string; - readonly #nodeClientOptions: RedisClientOptions; - readonly #sentinelClientOptions: RedisClientOptions; + readonly #nodeClientOptions: RedisClientOptions; + readonly #sentinelClientOptions: RedisClientOptions; readonly #scanInterval: number; readonly #passthroughClientErrorEvents: boolean; @@ -624,12 +626,12 @@ class RedisSentinelInternal< this.#scanInterval = options.scanInterval ?? 0; this.#passthroughClientErrorEvents = options.passthroughClientErrorEvents ?? false; - this.#nodeClientOptions = options.nodeClientOptions ? Object.assign({} as RedisClientOptions, options.nodeClientOptions) : {}; + this.#nodeClientOptions = options.nodeClientOptions ? Object.assign({} as RedisClientOptions, options.nodeClientOptions) : {}; if (this.#nodeClientOptions.url !== undefined) { throw new Error("invalid nodeClientOptions for Sentinel"); } - this.#sentinelClientOptions = options.sentinelClientOptions ? Object.assign({} as RedisClientOptions, options.sentinelClientOptions) : {}; + this.#sentinelClientOptions = options.sentinelClientOptions ? Object.assign({} as RedisClientOptions, options.sentinelClientOptions) : {}; this.#sentinelClientOptions.modules = RedisSentinelModule; if (this.#sentinelClientOptions.url !== undefined) { @@ -754,7 +756,8 @@ class RedisSentinelInternal< await this.#reset(); continue; } - this.#trace("attemping to send command to " + client.options?.socket?.host + ":" + client.options?.socket?.port) + const sockOpts = client.options?.socket as TcpNetConnectOpts | undefined; + this.#trace("attemping to send command to " + sockOpts?.host + ":" + sockOpts?.port) try { /* @@ -1198,7 +1201,8 @@ class RedisSentinelInternal< if (replicaCloseSet.has(str) || !replica.isOpen) { if (replica.isOpen) { - this.#trace(`destroying replica client to ${replica.options?.socket?.host}:${replica.options?.socket?.port}`); + const sockOpts = replica.options?.socket as TcpNetConnectOpts | undefined; + this.#trace(`destroying replica client to ${sockOpts?.host}:${sockOpts?.port}`); replica.destroy() } if (!removedSet.has(str)) { diff --git a/packages/client/lib/sentinel/types.ts b/packages/client/lib/sentinel/types.ts index 571100766e3..1f868ec5177 100644 --- a/packages/client/lib/sentinel/types.ts +++ b/packages/client/lib/sentinel/types.ts @@ -3,6 +3,7 @@ import { CommandOptions } from '../client/commands-queue'; import { CommandSignature, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types'; import COMMANDS from '../commands'; import RedisSentinel, { RedisSentinelClient } from '.'; +import { RedisTcpSocketOptions } from '../client/socket'; export interface RedisNode { host: string; @@ -31,11 +32,11 @@ export interface RedisSentinelOptions< /** * The configuration values for every node in the cluster. Use this for example when specifying an ACL user to connect with */ - nodeClientOptions?: RedisClientOptions; + nodeClientOptions?: RedisClientOptions; /** * The configuration values for every sentinel in the cluster. Use this for example when specifying an ACL user to connect with */ - sentinelClientOptions?: RedisClientOptions; + sentinelClientOptions?: RedisClientOptions; /** * The number of clients connected to the master node */ diff --git a/packages/client/lib/sentinel/utils.ts b/packages/client/lib/sentinel/utils.ts index 44de98fe71a..4ae829183a2 100644 --- a/packages/client/lib/sentinel/utils.ts +++ b/packages/client/lib/sentinel/utils.ts @@ -1,5 +1,5 @@ import { Command, RedisFunction, RedisScript, RespVersions } from '../RESP/types'; -import { RedisSocketOptions } from '../client/socket'; +import { RedisSocketOptions, RedisTcpSocketOptions } from '../client/socket'; import { functionArgumentsPrefix, getTransformReply, scriptArgumentsPrefix } from '../commander'; import { NamespaceProxySentinel, NamespaceProxySentinelClient, NodeInfo, ProxySentinel, ProxySentinelClient, RedisNode } from './types'; @@ -27,9 +27,11 @@ export function createNodeList(nodes: Array) { } export function clientSocketToNode(socket: RedisSocketOptions): RedisNode { + const s = socket as RedisTcpSocketOptions; + return { - host: socket.host!, - port: socket.port! + host: s.host!, + port: s.port! } } From 88ef3b87ed1e4a830862bc9eeebeb21db9bb5844 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 28 Feb 2024 10:26:23 -0500 Subject: [PATCH 317/325] exclude ./lib/sentinel/test-util.ts from build --- packages/client/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 5e044cbaa1e..8caa47300d4 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -9,7 +9,8 @@ ], "exclude": [ "./lib/test-utils.ts", - "./lib/**/*.spec.ts" + "./lib/**/*.spec.ts", + "./lib/sentinel/test-util.ts" ], "typedocOptions": { "entryPoints": [ From f9252356aeeecf02adc107fb0cc3a25a8aca3518 Mon Sep 17 00:00:00 2001 From: Leibale Date: Wed, 28 Feb 2024 14:33:26 -0500 Subject: [PATCH 318/325] docs --- docs/v4-to-v5.md | 35 ++++++++++++++++------------------- docs/v5.md | 8 ++++---- packages/redis/README.md | 12 ++++++------ 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index fb68656d5ce..95c2230ce23 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -83,32 +83,29 @@ for more information, see the [Scan Iterators guide](./scan-iterators.md). ## Isolation Pool -[TODO](./blocking-commands.md). - +In v4, `RedisClient` had the ability to create a pool of connections using an "Isolation Pool" on top of the "main" connection. However, there was no way to use the pool without a "main" connection: ```javascript -await client.get(client.commandOptions({ isolated: true }), 'key'); +const client = await createClient() + .on('error', err => console.error(err)) + .connect(); + +await client.ping( + client.commandOptions({ isolated: true }) +); ``` +In v5 we've extracted this pool logic into its own class—`RedisClientPool`: + ```javascript -await client.sendCommand(['GET', 'key']); -const pool = client.createPool({ - min: 0, - max: Infinity -}); -await pool.blPop('key'); -await pool.sendCommand(['GET', 'key']); -await pool.use(client => client.blPop()); +const pool = await createClientPool() + .on('error', err => console.error(err)) + .connect(); -await cluster.sendCommand('key', true, ['GET', 'key']); -const clusterPool = cluster.createPool({ - min: 0, - max: Infinity -}); -await clusterPool.blPop('key'); -await clusterPool.sendCommand('key', true, ['GET', 'key']); -await clusterPool.use(client => client.blPop()); +await pool.ping(); ``` +See the [pool guide](./pool.md) for more information. + ## Cluster `MULTI` In v4, `cluster.multi()` did not support executing commands on replicas, even if they were readonly. diff --git a/docs/v5.md b/docs/v5.md index 3ac3f0611b3..4a1bd817b9b 100644 --- a/docs/v5.md +++ b/docs/v5.md @@ -22,6 +22,10 @@ await client.withTypeMapping({ }).hGetAll('key'); // Map ``` +# Sentinel Support + +[TODO](./sentinel.md) + # `multi.exec<'typed'>` / `multi.execTyped` We have introduced the ability to perform a "typed" `MULTI`/`EXEC` transaction. Rather than returning `Array`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible: @@ -32,7 +36,3 @@ await multi.exec(); // Array await multi.exec<'typed'>(); // [string] await multi.execTyped(); // [string] ``` - -# Request & Reply Policies - -see [here](../docs/clustering.md#command-routing). diff --git a/packages/redis/README.md b/packages/redis/README.md index 8afb99836f3..76929ffa48b 100644 --- a/packages/redis/README.md +++ b/packages/redis/README.md @@ -28,12 +28,6 @@ createClient({ 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). -### Connection State - -To client exposes 2 `boolean`s that track the client state: -1. `isOpen` - the client is either connecting or connected. -2. `isReady` - the client is connected and ready to send - ### 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.): @@ -148,6 +142,12 @@ await Promise.all([ ]); ``` +### Connection State + +To client exposes 2 `boolean`s that track the client state: +1. `isOpen` - the client is either connecting or connected. +2. `isReady` - the client is connected and ready to send + ### Events The client extends `EventEmitter` and emits the following events: From 31c881e90e88cc824cf67d5cef66a7fabef2a0e8 Mon Sep 17 00:00:00 2001 From: John Olmsted Date: Tue, 28 May 2024 10:16:52 -0400 Subject: [PATCH 319/325] Default reconnect strategy uses exponential backoff and jitter (#2736) * Default reconnect strategy uses exponential backoff and jitter Both are recommended parts of client reconnect strategies to prevent thundering herd problems when many clients lose their connection at once (for example, during a Redis upgrade). * Move default retry strategy to constant * Plain english explanation of default 'socket.reconnectStrategy' * Extract default connect strategy into helper function --- docs/client-configuration.md | 13 ++++++++++--- packages/client/lib/client/socket.ts | 13 +++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/client-configuration.md b/docs/client-configuration.md index 69a2db16c37..deb68437e16 100644 --- a/docs/client-configuration.md +++ b/docs/client-configuration.md @@ -13,7 +13,7 @@ | socket.keepAlive | `true` | Toggle [`keep-alive`](https://nodejs.org/api/net.html#socketsetkeepaliveenable-initialdelay) functionality | | socket.keepAliveInitialDelay | `5000` | If set to a positive number, it sets the initial delay before the first keepalive probe is sent on an idle socket | | socket.tls | | See explanation and examples [below](#TLS) | -| socket.reconnectStrategy | `retries => Math.min(retries * 50, 500)` | A function containing the [Reconnect Strategy](#reconnect-strategy) logic | +| socket.reconnectStrategy | Exponential backoff with a maximum of 2000 ms; plus 0-200 ms random jitter. | A function containing the [Reconnect Strategy](#reconnect-strategy) logic | | username | | ACL username ([see ACL guide](https://redis.io/topics/acl)) | | password | | ACL password or the old "--requirepass" password | | name | | Client name ([see `CLIENT SETNAME`](https://redis.io/commands/client-setname)) | @@ -35,12 +35,19 @@ When the socket closes unexpectedly (without calling `.quit()`/`.disconnect()`), 2. `number` -> wait for `X` milliseconds before reconnecting. 3. `(retries: number, cause: Error) => false | number | Error` -> `number` is the same as configuring a `number` directly, `Error` is the same as `false`, but with a custom error. -By default the strategy is `Math.min(retries * 50, 500)`, but it can be overwritten like so: +By default the strategy uses exponential backoff, but it can be overwritten like so: ```javascript createClient({ socket: { - reconnectStrategy: retries => Math.min(retries * 50, 1000) + reconnectStrategy: retries => { + // Generate a random jitter between 0 – 200 ms: + const jitter = Math.floor(Math.random() * 200); + // Delay is an exponential back off, (times^2) * 50 ms, with a maximum value of 2000 ms: + const delay = Math.min(Math.pow(2, retries) * 50, 2000); + + return delay + jitter; + } } }); ``` diff --git a/packages/client/lib/client/socket.ts b/packages/client/lib/client/socket.ts index dcadad4c3dd..3c2666e1067 100644 --- a/packages/client/lib/client/socket.ts +++ b/packages/client/lib/client/socket.ts @@ -97,12 +97,12 @@ export default class RedisSocket extends EventEmitter { return retryIn; } catch (err) { this.emit('error', err); - return Math.min(retries * 50, 500); + return this.defaultReconnectStrategy(retries); } }; } - return retries => Math.min(retries * 50, 500); + return this.defaultReconnectStrategy; } #createSocketFactory(options?: RedisSocketOptions) { @@ -333,4 +333,13 @@ export default class RedisSocket extends EventEmitter { this.#isSocketUnrefed = true; this.#socket?.unref(); } + + defaultReconnectStrategy(retries: number) { + // Generate a random jitter between 0 – 200 ms: + const jitter = Math.floor(Math.random() * 200); + // Delay is an exponential back off, (times^2) * 50 ms, with a maximum value of 2000 ms: + const delay = Math.min(Math.pow(2, retries) * 50, 2000); + + return delay + jitter; + } } From 271baf3a65f1ebaf2e0eb647d80d7e1c5e5a19a1 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Mon, 3 Jun 2024 17:16:07 +0300 Subject: [PATCH 320/325] HSCAN NOVALUES support (v5) (#2758) * HSCAN VALUES support (v5) * add hscanNoValuesIterator * nitpick --------- Co-authored-by: Leibale Eidelman --- packages/client/lib/client/index.ts | 13 +++++ .../lib/commands/HSCAN_NOVALUES.spec.ts | 56 +++++++++++++++++++ .../client/lib/commands/HSCAN_NOVALUES.ts | 22 ++++++++ packages/client/lib/commands/index.ts | 3 + 4 files changed, 94 insertions(+) create mode 100644 packages/client/lib/commands/HSCAN_NOVALUES.spec.ts create mode 100644 packages/client/lib/commands/HSCAN_NOVALUES.ts diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 3efa793eeb9..1c67e321a32 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -901,6 +901,19 @@ export default class RedisClient< } while (cursor !== '0'); } + async* hScanValuesIterator( + this: RedisClientType, + key: RedisArgument, + options?: ScanCommonOptions & ScanIteratorOptions + ) { + let cursor = options?.cursor ?? '0'; + do { + const reply = await this.hScanNoValues(key, cursor, options); + cursor = reply.cursor; + yield reply.fields; + } while (cursor !== '0'); + } + async* sScanIterator( this: RedisClientType, key: RedisArgument, diff --git a/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts b/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts new file mode 100644 index 00000000000..3564a958cc1 --- /dev/null +++ b/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts @@ -0,0 +1,56 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import HSCAN_NOVALUES from './HSCAN_NOVALUES'; + +describe('HSCAN_NOVALUES', () => { + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + HSCAN_NOVALUES.transformArguments('key', '0'), + ['HSCAN', 'key', '0', 'NOVALUES'] + ); + }); + + it('with MATCH', () => { + assert.deepEqual( + HSCAN_NOVALUES.transformArguments('key', '0', { + MATCH: 'pattern' + }), + ['HSCAN', 'key', '0', 'MATCH', 'pattern', 'NOVALUES'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + HSCAN_NOVALUES.transformArguments('key', '0', { + COUNT: 1 + }), + ['HSCAN', 'key', '0', 'COUNT', '1', 'NOVALUES'] + ); + }); + + it('with MATCH & COUNT', () => { + assert.deepEqual( + HSCAN_NOVALUES.transformArguments('key', '0', { + MATCH: 'pattern', + COUNT: 1 + }), + ['HSCAN', 'key', '0', 'MATCH', 'pattern', 'COUNT', '1', 'NOVALUES'] + ); + }); + }); + + testUtils.testWithClient('client.hScanNoValues', async client => { + const [, reply] = await Promise.all([ + client.hSet('key', 'field', 'value'), + client.hScanNoValues('key', '0') + ]); + + assert.deepEqual(reply, { + cursor: '0', + fields: [ + 'field', + ] + }); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/HSCAN_NOVALUES.ts b/packages/client/lib/commands/HSCAN_NOVALUES.ts new file mode 100644 index 00000000000..35ff861338c --- /dev/null +++ b/packages/client/lib/commands/HSCAN_NOVALUES.ts @@ -0,0 +1,22 @@ +import { RedisArgument, BlobStringReply, Command } from '../RESP/types'; +import { ScanCommonOptions, pushScanArguments } from './SCAN'; + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + cursor: RedisArgument, + options?: ScanCommonOptions + ) { + const args = pushScanArguments(['HSCAN', key], cursor, options); + args.push('NOVALUES'); + return args; + }, + transformReply([cursor, fields]: [BlobStringReply, Array]) { + return { + cursor, + fields + }; + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index b2898988386..55a61f577ed 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -144,6 +144,7 @@ import HRANDFIELD_COUNT_WITHVALUES from './HRANDFIELD_COUNT_WITHVALUES'; import HRANDFIELD_COUNT from './HRANDFIELD_COUNT'; import HRANDFIELD from './HRANDFIELD'; import HSCAN from './HSCAN'; +import HSCAN_NOVALUES from './HSCAN_NOVALUES'; import HSET from './HSET'; import HSETNX from './HSETNX'; import HSTRLEN from './HSTRLEN'; @@ -623,6 +624,8 @@ export default { hRandField: HRANDFIELD, HSCAN, hScan: HSCAN, + HSCAN_NOVALUES, + hScanNoValues: HSCAN_NOVALUES, HSET, hSet: HSET, HSETNX, From 85d5bf4125b8c4c5bd1fc91a2c1e5d0cf0600405 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Tue, 18 Jun 2024 17:01:41 +0300 Subject: [PATCH 321/325] add CLIENT KILL MAXAGE (v5) (#2760) * add CLIENT KILL MANAGE maxAge (v5) * replace "MANAGE" with "MAXAGE" * fix test --------- Co-authored-by: Leibale Eidelman --- packages/client/lib/commands/CLIENT_KILL.spec.ts | 10 ++++++++++ packages/client/lib/commands/CLIENT_KILL.ts | 13 +++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/CLIENT_KILL.spec.ts b/packages/client/lib/commands/CLIENT_KILL.spec.ts index 0685c46ba4a..79254af41f9 100644 --- a/packages/client/lib/commands/CLIENT_KILL.spec.ts +++ b/packages/client/lib/commands/CLIENT_KILL.spec.ts @@ -65,6 +65,16 @@ describe('CLIENT KILL', () => { ); }); + it('MAXAGE', () => { + assert.deepEqual( + CLIENT_KILL.transformArguments({ + filter: CLIENT_KILL_FILTERS.MAXAGE, + maxAge: 10 + }), + ['CLIENT', 'KILL', 'MAXAGE', '10'] + ); + }); + describe('SKIP_ME', () => { it('undefined', () => { assert.deepEqual( diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index 81d0bc85ee7..acf538f9a54 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -6,7 +6,8 @@ export const CLIENT_KILL_FILTERS = { ID: 'ID', TYPE: 'TYPE', USER: 'USER', - SKIP_ME: 'SKIPME' + SKIP_ME: 'SKIPME', + MAXAGE: 'MAXAGE' } as const; type CLIENT_KILL_FILTERS = typeof CLIENT_KILL_FILTERS; @@ -39,7 +40,11 @@ export type ClientKillSkipMe = CLIENT_KILL_FILTERS['SKIP_ME'] | (ClientKillFilte skipMe: boolean; }); -export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe; +export interface ClientKillMaxAge extends ClientKillFilterCommon { + maxAge: number; +} + +export type ClientKillFilter = ClientKillAddress | ClientKillLocalAddress | ClientKillId | ClientKillType | ClientKillUser | ClientKillSkipMe | ClientKillMaxAge; export default { FIRST_KEY_INDEX: undefined, @@ -96,5 +101,9 @@ function pushFilter(args: Array, filter: ClientKillFilter): void case CLIENT_KILL_FILTERS.SKIP_ME: args.push(filter.skipMe ? 'yes' : 'no'); break; + + case CLIENT_KILL_FILTERS.MAXAGE: + args.push(filter.maxAge.toString()); + break; } } From 4452117946faf53786d5fcb19b913f6bfa04fa88 Mon Sep 17 00:00:00 2001 From: gianDiazM Date: Mon, 1 Jul 2024 15:08:22 +0200 Subject: [PATCH 322/325] clientKillMaxAge typo, replace MANAGE by MAXAGE (#2782) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: “gianDiazM” <“gian.diaz.marquez@gmail.com”> --- packages/client/lib/commands/CLIENT_KILL.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index acf538f9a54..c5eb5304c57 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -40,7 +40,7 @@ export type ClientKillSkipMe = CLIENT_KILL_FILTERS['SKIP_ME'] | (ClientKillFilte skipMe: boolean; }); -export interface ClientKillMaxAge extends ClientKillFilterCommon { +export interface ClientKillMaxAge extends ClientKillFilterCommon { maxAge: number; } From 949b944b0f01fa207980b5aa925590d7c32f6073 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 1 Jul 2024 16:09:07 -0400 Subject: [PATCH 323/325] fix FIRST_KEY_INDEX for FT.SUG* commands --- packages/search/lib/commands/SUGADD.ts | 2 +- packages/search/lib/commands/SUGDEL.ts | 2 +- packages/search/lib/commands/SUGGET.ts | 2 +- packages/search/lib/commands/SUGLEN.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/search/lib/commands/SUGADD.ts b/packages/search/lib/commands/SUGADD.ts index c4cc1fb53e8..c18cd7846ed 100644 --- a/packages/search/lib/commands/SUGADD.ts +++ b/packages/search/lib/commands/SUGADD.ts @@ -6,7 +6,7 @@ export interface FtSugAddOptions { } export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) { const args = ['FT.SUGADD', key, string, score.toString()]; diff --git a/packages/search/lib/commands/SUGDEL.ts b/packages/search/lib/commands/SUGDEL.ts index ed9a8aef24f..5829ec40a2c 100644 --- a/packages/search/lib/commands/SUGDEL.ts +++ b/packages/search/lib/commands/SUGDEL.ts @@ -1,7 +1,7 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument) { return ['FT.SUGDEL', key, string]; diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts index 9359920fcb2..53dc57a86aa 100644 --- a/packages/search/lib/commands/SUGGET.ts +++ b/packages/search/lib/commands/SUGGET.ts @@ -6,7 +6,7 @@ export interface FtSugGetOptions { } export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) { const args = ['FT.SUGGET', key, prefix]; diff --git a/packages/search/lib/commands/SUGLEN.ts b/packages/search/lib/commands/SUGLEN.ts index a5418843d44..85dde8cfb70 100644 --- a/packages/search/lib/commands/SUGLEN.ts +++ b/packages/search/lib/commands/SUGLEN.ts @@ -1,7 +1,7 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; export default { - FIRST_KEY_INDEX: undefined, + FIRST_KEY_INDEX: 1, IS_READ_ONLY: true, transformArguments(key: RedisArgument) { return ['FT.SUGLEN', key]; From f7d824c07c59cd0ac7c03e21d143cf35eebd452d Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Fri, 11 Oct 2024 11:22:31 +0300 Subject: [PATCH 324/325] CAE-193: add "IGNORE" options to time series commands (for v5 branch) (#2753) * CAE-193: add "IGNORE" options to time series commands (for v5 branch) * add INCR/DECR and modify tests to not test ignore on older version * require maxTimeDiff/maxValDiff to be specified also rename them * fix add/ignore test after api change * update tests for api change in IGNORE option --- packages/time-series/lib/commands/ADD.spec.ts | 19 ++++++++++++++++--- packages/time-series/lib/commands/ADD.ts | 11 ++++++++++- .../time-series/lib/commands/ALTER.spec.ts | 19 ++++++++++++++++--- packages/time-series/lib/commands/ALTER.ts | 6 ++++-- .../time-series/lib/commands/CREATE.spec.ts | 19 ++++++++++++++++--- packages/time-series/lib/commands/CREATE.ts | 7 ++++++- .../time-series/lib/commands/DECRBY.spec.ts | 17 +++++++++++++++-- .../time-series/lib/commands/INCRBY.spec.ts | 17 +++++++++++++++-- packages/time-series/lib/commands/INCRBY.ts | 6 +++++- packages/time-series/lib/commands/index.ts | 8 +++++++- 10 files changed, 110 insertions(+), 19 deletions(-) diff --git a/packages/time-series/lib/commands/ADD.spec.ts b/packages/time-series/lib/commands/ADD.spec.ts index e9831d21d02..7dcf031c2b2 100644 --- a/packages/time-series/lib/commands/ADD.spec.ts +++ b/packages/time-series/lib/commands/ADD.spec.ts @@ -57,16 +57,29 @@ describe('TS.ADD', () => { ); }); - it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS', () => { + it ('with IGNORE', () => { + assert.deepEqual( + ADD.transformArguments('key', '*', 1, { + IGNORE: { + maxTimeDiff: 1, + maxValDiff: 1 + } + }), + ['TS.ADD', 'key', '*', '1', 'IGNORE', '1', '1'] + ) + }); + + it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS, IGNORE', () => { assert.deepEqual( ADD.transformArguments('key', '*', 1, { RETENTION: 1, ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED, CHUNK_SIZE: 1, ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { maxTimeDiff: 1, maxValDiff: 1} }), - ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/ADD.ts b/packages/time-series/lib/commands/ADD.ts index b40a6912ca8..1842dcfc346 100644 --- a/packages/time-series/lib/commands/ADD.ts +++ b/packages/time-series/lib/commands/ADD.ts @@ -8,15 +8,22 @@ import { TimeSeriesDuplicatePolicies, Labels, pushLabelsArgument, - Timestamp + Timestamp, + pushIgnoreArgument } from '.'; +export interface TsIgnoreOptions { + maxTimeDiff: number; + maxValDiff: number; +} + export interface TsAddOptions { RETENTION?: number; ENCODING?: TimeSeriesEncoding; CHUNK_SIZE?: number; ON_DUPLICATE?: TimeSeriesDuplicatePolicies; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export default { @@ -47,6 +54,8 @@ export default { pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; }, transformReply: undefined as unknown as () => NumberReply diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index b60bdece62e..4998dcb1a49 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -48,15 +48,28 @@ describe('TS.ALTER', () => { ); }); - it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + it('with IGNORE', () => { + assert.deepEqual( + ALTER.transformArguments('key', { + IGNORE: { + maxTimeDiff: 1, + maxValDiff: 1 + } + }), + ['TS.ALTER', 'key', 'IGNORE', '1', '1'] + ) + }); + + it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => { assert.deepEqual( ALTER.transformArguments('key', { RETENTION: 1, CHUNK_SIZE: 1, DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { maxTimeDiff: 1, maxValDiff: 1} }), - ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/ALTER.ts b/packages/time-series/lib/commands/ALTER.ts index ae30799b2eb..f77edb5c43f 100644 --- a/packages/time-series/lib/commands/ALTER.ts +++ b/packages/time-series/lib/commands/ALTER.ts @@ -1,8 +1,8 @@ import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { TsCreateOptions } from './CREATE'; -import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument } from '.'; +import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument, pushIgnoreArgument } from '.'; -export type TsAlterOptions = Pick; +export type TsAlterOptions = Pick; export default { FIRST_KEY_INDEX: 1, @@ -18,6 +18,8 @@ export default { pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; }, transformReply: undefined as unknown as () => SimpleStringReply<'OK'> diff --git a/packages/time-series/lib/commands/CREATE.spec.ts b/packages/time-series/lib/commands/CREATE.spec.ts index d400be8a035..abe198970b9 100644 --- a/packages/time-series/lib/commands/CREATE.spec.ts +++ b/packages/time-series/lib/commands/CREATE.spec.ts @@ -57,16 +57,29 @@ describe('TS.CREATE', () => { ); }); - it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + it('with IGNORE', () => { + assert.deepEqual( + CREATE.transformArguments('key', { + IGNORE: { + maxTimeDiff: 1, + maxValDiff: 1 + } + }), + ['TS.CREATE', 'key', 'IGNORE', '1', '1'] + ) + }); + + it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => { assert.deepEqual( CREATE.transformArguments('key', { RETENTION: 1, ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED, CHUNK_SIZE: 1, DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { maxTimeDiff: 1, maxValDiff: 1} }), - ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/CREATE.ts b/packages/time-series/lib/commands/CREATE.ts index b028a470277..abb84de12a2 100644 --- a/packages/time-series/lib/commands/CREATE.ts +++ b/packages/time-series/lib/commands/CREATE.ts @@ -7,8 +7,10 @@ import { TimeSeriesDuplicatePolicies, pushDuplicatePolicy, Labels, - pushLabelsArgument + pushLabelsArgument, + pushIgnoreArgument } from '.'; +import { TsIgnoreOptions } from './ADD'; export interface TsCreateOptions { RETENTION?: number; @@ -16,6 +18,7 @@ export interface TsCreateOptions { CHUNK_SIZE?: number; DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export default { @@ -34,6 +37,8 @@ export default { pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; }, transformReply: undefined as unknown as () => SimpleStringReply<'OK'> diff --git a/packages/time-series/lib/commands/DECRBY.spec.ts b/packages/time-series/lib/commands/DECRBY.spec.ts index f9e482bcae6..dbce98b2acd 100644 --- a/packages/time-series/lib/commands/DECRBY.spec.ts +++ b/packages/time-series/lib/commands/DECRBY.spec.ts @@ -56,6 +56,18 @@ describe('TS.DECRBY', () => { ); }); + it ('with IGNORE', () => { + assert.deepEqual( + DECRBY.transformArguments('key', 1, { + IGNORE: { + maxTimeDiff: 1, + maxValDiff: 1 + } + }), + ['TS.DECRBY', 'key', '1', 'IGNORE', '1', '1'] + ) + }); + it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { assert.deepEqual( DECRBY.transformArguments('key', 1, { @@ -63,9 +75,10 @@ describe('TS.DECRBY', () => { RETENTION: 1, UNCOMPRESSED: true, CHUNK_SIZE: 2, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { maxTimeDiff: 1, maxValDiff: 1 } }), - ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value'] + ['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/INCRBY.spec.ts b/packages/time-series/lib/commands/INCRBY.spec.ts index 463bf930104..33163a72c82 100644 --- a/packages/time-series/lib/commands/INCRBY.spec.ts +++ b/packages/time-series/lib/commands/INCRBY.spec.ts @@ -65,6 +65,18 @@ describe('TS.INCRBY', () => { ); }); + it ('with IGNORE', () => { + assert.deepEqual( + INCRBY.transformArguments('key', 1, { + IGNORE: { + maxTimeDiff: 1, + maxValDiff: 1 + } + }), + ['TS.INCRBY', 'key', '1', 'IGNORE', '1', '1'] + ) + }); + it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => { assert.deepEqual( INCRBY.transformArguments('key', 1, { @@ -72,10 +84,11 @@ describe('TS.INCRBY', () => { RETENTION: 1, UNCOMPRESSED: true, CHUNK_SIZE: 1, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { maxTimeDiff: 1, maxValDiff: 1 } }), ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', - 'CHUNK_SIZE', '1', 'LABELS', 'label', 'value'] + 'CHUNK_SIZE', '1', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/INCRBY.ts b/packages/time-series/lib/commands/INCRBY.ts index ece5defee6a..3160d3906d3 100644 --- a/packages/time-series/lib/commands/INCRBY.ts +++ b/packages/time-series/lib/commands/INCRBY.ts @@ -1,5 +1,6 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; -import { Timestamp, transformTimestampArgument, pushRetentionArgument, pushChunkSizeArgument, Labels, pushLabelsArgument } from '.'; +import { Timestamp, transformTimestampArgument, pushRetentionArgument, pushChunkSizeArgument, Labels, pushLabelsArgument, pushIgnoreArgument } from '.'; +import { TsIgnoreOptions } from './ADD'; export interface TsIncrByOptions { TIMESTAMP?: Timestamp; @@ -7,6 +8,7 @@ export interface TsIncrByOptions { UNCOMPRESSED?: boolean; CHUNK_SIZE?: number; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export function transformIncrByArguments( @@ -35,6 +37,8 @@ export function transformIncrByArguments( pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; } diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index e9137a15a00..84976ca7b31 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -1,5 +1,5 @@ import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; -import ADD from './ADD'; +import ADD, { TsIgnoreOptions } from './ADD'; import ALTER from './ALTER'; import CREATE from './CREATE'; import CREATERULE from './CREATERULE'; @@ -67,6 +67,12 @@ export default { revRange: REVRANGE } as const satisfies RedisCommands; +export function pushIgnoreArgument(args: Array, ignore?: TsIgnoreOptions) { + if (ignore !== undefined) { + args.push('IGNORE', ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString()); + } +} + export function pushRetentionArgument(args: Array, retention?: number) { if (retention !== undefined) { args.push('RETENTION', retention.toString()); From 2eaaa5873650faf3f297f4642208ded99fcda3c3 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Fri, 11 Oct 2024 11:24:27 +0300 Subject: [PATCH 325/325] add addscores to aggregate search command (v5) (#2818) --- packages/search/lib/commands/AGGREGATE.spec.ts | 7 +++++++ packages/search/lib/commands/AGGREGATE.ts | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index 1a40f264ff4..a5eae0233d6 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -20,6 +20,13 @@ describe('AGGREGATE', () => { ); }); + it('with ADDSCORES', () => { + assert.deepEqual( + AGGREGATE.transformArguments('index', '*', { ADDSCORES: true }), + ['FT.AGGREGATE', 'index', '*', 'ADDSCORES'] + ); + }); + describe('with LOAD', () => { describe('single', () => { describe('without alias', () => { diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index a12e455a0cb..767705a804f 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -118,6 +118,7 @@ interface FilterStep extends AggregateStep { export interface FtAggregateOptions { VERBATIM?: boolean; + ADDSCORES?: boolean; LOAD?: LoadField | Array; TIMEOUT?: number; STEPS?: Array; @@ -135,6 +136,10 @@ export default { args.push('VERBATIM'); } + if (options?.ADDSCORES) { + args.push('ADDSCORES'); + } + if (options?.LOAD) { const length = args.push('LOAD', '');