@upstash/redis 1.0.0-alpha.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,256 @@
1
+ # Upstash Redis
2
+
3
+ An HTTP/REST based Redis client built on top of
4
+ [Upstash REST API](https://docs.upstash.com/features/restapi).
5
+
6
+ [![Tests](https://github.com/upstash/upstash-redis/actions/workflows/tests.yaml/badge.svg)](https://github.com/upstash/upstash-redis/actions/workflows/tests.yaml)
7
+ ![npm (scoped)](https://img.shields.io/npm/v/@upstash/redis)
8
+ ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@upstash/redis)
9
+
10
+ It is the only connectionless (HTTP based) Redis client and designed for:
11
+
12
+ - Serverless functions (AWS Lambda ...)
13
+ - Cloudflare Workers (see
14
+ [the example](https://github.com/upstash/upstash-redis/tree/master/examples/cloudflare-workers))
15
+ - Fastly Compute@Edge (see
16
+ [the example](https://github.com/upstash/upstash-redis/tree/master/examples/fastly))
17
+ - Next.js, Jamstack ...
18
+ - Client side web/mobile applications
19
+ - WebAssembly
20
+ - and other environments where HTTP is preferred over TCP.
21
+
22
+ See [the list of APIs](https://docs.upstash.com/features/restapi#rest---redis-api-compatibility) supported.
23
+
24
+ ## Upgrading from v0.2.0?
25
+
26
+ Please read the [migration guide](https://github.com/upstash/upstash-redis#migrating-to-v1).
27
+ For further explanation we wrote a [blog post](https://blog.upstash.com/upstash-redis-sdk-v1).
28
+
29
+ ## Quick Start
30
+
31
+ ### Install
32
+
33
+ ```bash
34
+ npm install @upstash/redis
35
+ ```
36
+
37
+ ### Create database
38
+
39
+ Create a new redis database on [upstash](https://console.upstash.com/)
40
+
41
+ ### Environments
42
+
43
+ We support various platforms, such as nodejs, cloudflare and fastly.
44
+ Platforms differ slightly when it comes to environment variables and their `fetch` api. Please use the correct import when deploying to special platforms.
45
+
46
+ #### Node.js
47
+
48
+ Examples: Vercel, Netlify, AWS Lambda
49
+
50
+ If you are running on nodejs you can set `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` as environment variable and create a redis instance like this:
51
+
52
+ ```ts
53
+ import { Redis } from "@upstash/redis"
54
+
55
+ const redis = new Redis({
56
+ url: <UPSTASH_REDIS_REST_URL>,
57
+ token: <UPSTASH_REDIS_REST_TOKEN>,
58
+ })
59
+
60
+ // or load directly from env
61
+ const redis = Redis.fromEnv()
62
+ ```
63
+
64
+ - [Code example](https://github.com/upstash/upstash-redis/tree/main/examples/node)
65
+
66
+ #### Cloudflare Workers
67
+
68
+ Cloudflare handles environment variables differently than nodejs.
69
+ Please add `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` using `wrangler secret put ...` or in the cloudflare dashboard.
70
+
71
+ Afterwards you can create a redis instance:
72
+
73
+ ```ts
74
+ import { Redis } from "@upstash/redis/cloudflare"
75
+
76
+ const redis = new Redis({
77
+ url: <UPSTASH_REDIS_REST_URL>,
78
+ token: <UPSTASH_REDIS_REST_TOKEN>,
79
+ })
80
+ // or load directly from env
81
+ const redis = Redis.fromEnv()
82
+ ```
83
+
84
+ - [Code example](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers)
85
+ - [Documentation](https://docs.upstash.com/redis/tutorials/cloudflare_workers_with_redis)
86
+
87
+ #### Fastly
88
+
89
+ Fastly introduces a concept called [backend](https://developer.fastly.com/reference/api/services/backend/). You need to configure a backend in your `fastly.toml`. An example can be found [here](https://github.com/upstash/upstash-redis/blob/main/examples/fastly/fastly.toml).
90
+ Until the fastly api stabilizes we recommend creating an instance manually:
91
+
92
+ ```ts
93
+ import { Redis } from "@upstash/redis/fastly"
94
+
95
+ const redis = new Redis({
96
+ url: <UPSTASH_REDIS_REST_URL>,
97
+ token: <UPSTASH_REDIS_REST_TOKEN>,
98
+ backend: <BACKEND_NAME>,
99
+ })
100
+ ```
101
+
102
+ - [Code example](https://github.com/upstash/upstash-redis/tree/main/examples/fastly)
103
+ - [Documentation](https://blog.upstash.com/fastly-compute-edge-with-redi)
104
+
105
+ ### Working with types
106
+
107
+ Most commands allow you to provide a type to make working with typescript easier.
108
+
109
+ ```ts
110
+ const data = await redis.get<MyCustomType>("key")
111
+ // data is typed as `MyCustomType`
112
+ ```
113
+
114
+ ## Migrating to v1
115
+
116
+ ### Explicit authentication
117
+
118
+ The library is no longer automatically trying to load connection secrets from environment variables.
119
+ You must either supply them yourself:
120
+
121
+ ```ts
122
+ import { Redis } from "@upstash/redis"
123
+
124
+ const redis = new Redis({
125
+ url: <UPSTASH_REDIS_REST_URL>,
126
+ token: <UPSTASH_REDIS_REST_TOKEN>,
127
+ })
128
+ ```
129
+
130
+ Or use one of the static constructors to load from environment variables:
131
+
132
+ ```ts
133
+ // Nodejs
134
+ import { Redis } from "@upstash/redis"
135
+ const redis = Redis.fromEnv()
136
+ ```
137
+
138
+ ```ts
139
+ // or when deploying to cloudflare workers
140
+ import { Redis } from "@upstash/redis/cloudflare"
141
+ const redis = Redis.fromEnv()
142
+ ```
143
+
144
+ ### Error handling
145
+
146
+ Errors are now thrown automatically instead of being returned to you.
147
+
148
+ ```ts
149
+ // old
150
+ const { data, error } = await set("key", "value")
151
+ if (error) {
152
+ throw new Error(error)
153
+ }
154
+
155
+ // new
156
+ const data = await redis.set("key", "value") // error is thrown automatically
157
+ ```
158
+
159
+ ## Pipeline
160
+
161
+ `v1.0.0` introduces redis pipelines.
162
+ Pipelining commands allows you to send a single http request with multiple commands.
163
+
164
+ ```ts
165
+ import { Redis } from "@upstash/redis"
166
+
167
+ const redis = new Redis({
168
+ /* auth */
169
+ })
170
+
171
+ const p = redis.pipeline()
172
+
173
+ // Now you can chain multiple commands to create your pipeline:
174
+
175
+ p.set("key", 2)
176
+ p.incr("key")
177
+
178
+ // or inline:
179
+ p.hset("key2", "field", { hello: "world" }).hvals("key2")
180
+
181
+ // Execute the pipeline once you are done building it:
182
+ // `exec` returns an array where each element represents the response of a command in the pipeline.
183
+ // You can optionally provide a type like this to get a typed response.
184
+ const res = await p.exec<[Type1, Type2, Type3]>()
185
+ ```
186
+
187
+ For more information about pipelines using REST see [here](https://blog.upstash.com/pipeline).
188
+
189
+ ### Advanced
190
+
191
+ A low level `Command` class can be imported from `@upstash/redis` in case you need more control about types and or (de)serialization.
192
+
193
+ By default all objects you are storing in redis are serialized using `JSON.stringify` and recursively deserialized as well. Here's an example how you could customize that behaviour. Keep in mind that you need to provide a `fetch` polyfill if you are running on nodejs. We recommend [isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch).
194
+
195
+ ```ts
196
+ import { Command } from "@upstash/redis/commands"
197
+ import { HttpClient } from "@upstash/redis/http"
198
+
199
+ /**
200
+ * TData represents what the user will enter or receive,
201
+ * TResult is the raw data returned from upstash, which may need to be
202
+ * transformed or parsed.
203
+ */
204
+ const deserialize: (raw: TResult) => TData = ...
205
+
206
+ class CustomGetCommand<TData, TResult> extends Command<TData | null, TResult | null> {
207
+ constructor(key: string, ) {
208
+ super(["get", key], { deserialize })
209
+ }
210
+ }
211
+
212
+ const client = new HttpClient({
213
+ baseUrl: <UPSTASH_REDIS_REST_URL>,
214
+ headers: {
215
+ authorization: `Bearer ${<UPSTASH_REDIS_REST_TOKEN>}`,
216
+ },
217
+ })
218
+
219
+ const res = new CustomGetCommand("key").exec(client)
220
+
221
+ ```
222
+
223
+ #### Javascript MAX_SAFE_INTEGER
224
+
225
+ Javascript can not handle numbers larger than `2^53 -1` safely and would return wrong results when trying to deserialize them.
226
+ In these cases the default deserializer will return them as string instead. This might cause a mismatch with your custom types.
227
+
228
+ ```ts
229
+ await redis.set("key", "101600000000150081467")
230
+ const res = await redis<number>("get")
231
+ ```
232
+
233
+ In this example `res` will still be a string despite the type annotation.
234
+ Please keep that in mind and adjust accordingly.
235
+
236
+ ## Docs
237
+
238
+ See [the documentation](https://docs.upstash.com/features/javascriptsdk) for details.
239
+
240
+ ## Contributing
241
+
242
+ ### Installing dependencies
243
+
244
+ ```bash
245
+ pnpm install
246
+ ```
247
+
248
+ ### Database
249
+
250
+ Create a new redis database on [upstash](https://console.upstash.com/) and copy the url and token to `.env` (See `.env.example` for reference)
251
+
252
+ ### Running tests
253
+
254
+ ```sh
255
+ pnpm test
256
+ ```
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Redis
3
- } from "./chunk-Y5TC4HX2.mjs";
3
+ } from "./chunk-T66TTHSV.mjs";
4
4
  import {
5
5
  HttpClient
6
- } from "./chunk-U7OXAQMQ.mjs";
6
+ } from "./chunk-HIDCSH5S.mjs";
7
7
 
8
8
  // pkg/nodejs.ts
9
9
  import "isomorphic-fetch";
@@ -4,13 +4,17 @@ import {
4
4
 
5
5
  // pkg/util.ts
6
6
  function parseRecursive(obj) {
7
- return Array.isArray(obj) ? obj.map((o) => {
7
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
8
8
  try {
9
9
  return parseRecursive(o);
10
10
  } catch {
11
11
  return o;
12
12
  }
13
13
  }) : JSON.parse(obj);
14
+ if (typeof parsed === "number" && parsed.toString() != obj) {
15
+ return obj;
16
+ }
17
+ return parsed;
14
18
  }
15
19
  function parseResponse(result) {
16
20
  try {
@@ -20,7 +24,7 @@ function parseResponse(result) {
20
24
  }
21
25
  }
22
26
 
23
- // pkg/command.ts
27
+ // pkg/commands/command.ts
24
28
  var Command = class {
25
29
  constructor(command, opts) {
26
30
  var _a;
@@ -300,8 +304,8 @@ var HScanCommand = class extends Command {
300
304
 
301
305
  // pkg/commands/hset.ts
302
306
  var HSetCommand = class extends Command {
303
- constructor(key, field, value) {
304
- super(["hset", key, field, value]);
307
+ constructor(key, kv) {
308
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
305
309
  }
306
310
  };
307
311
 
@@ -951,6 +955,7 @@ var ZUnionStoreCommand = class extends Command {
951
955
  };
952
956
 
953
957
  export {
958
+ Command,
954
959
  AppendCommand,
955
960
  BitCountCommand,
956
961
  BitOpCommand,
@@ -4,7 +4,6 @@ import {
4
4
  } from "./chunk-7YUZYRJS.mjs";
5
5
 
6
6
  // pkg/http.ts
7
- import "isomorphic-fetch";
8
7
  var HttpClient = class {
9
8
  constructor(config) {
10
9
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
@@ -106,7 +106,7 @@ import {
106
106
  ZScanCommand,
107
107
  ZScoreCommand,
108
108
  ZUnionStoreCommand
109
- } from "./chunk-ZIB6XPPC.mjs";
109
+ } from "./chunk-HGM7M7CJ.mjs";
110
110
  import {
111
111
  UpstashError
112
112
  } from "./chunk-7YUZYRJS.mjs";
@@ -223,8 +223,8 @@ var Pipeline = class {
223
223
  hscan(...args) {
224
224
  return this.chain(new HScanCommand(...args));
225
225
  }
226
- hset(key, field, value) {
227
- return this.chain(new HSetCommand(key, field, value));
226
+ hset(key, kv) {
227
+ return this.chain(new HSetCommand(key, kv));
228
228
  }
229
229
  hsetnx(key, field, value) {
230
230
  return this.chain(new HSetNXCommand(key, field, value));
@@ -554,8 +554,8 @@ var Redis = class {
554
554
  hscan(...args) {
555
555
  return new HScanCommand(...args).exec(this.client);
556
556
  }
557
- hset(key, field, value) {
558
- return new HSetCommand(key, field, value).exec(this.client);
557
+ hset(key, kv) {
558
+ return new HSetCommand(key, kv).exec(this.client);
559
559
  }
560
560
  hsetnx(key, field, value) {
561
561
  return new HSetNXCommand(key, field, value).exec(this.client);
package/cloudflare.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Redis$1 } from './redis-dd052782';
2
- import './zunionstore-dffa797d';
1
+ import { R as Redis$1 } from './redis-71fa1ee6';
2
+ import './zunionstore-b38007ba';
3
3
  import './http';
4
4
 
5
5
  /**
package/cloudflare.js CHANGED
@@ -51,13 +51,17 @@ var UpstashError = class extends Error {
51
51
 
52
52
  // pkg/util.ts
53
53
  function parseRecursive(obj) {
54
- return Array.isArray(obj) ? obj.map((o) => {
54
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
55
55
  try {
56
56
  return parseRecursive(o);
57
57
  } catch {
58
58
  return o;
59
59
  }
60
60
  }) : JSON.parse(obj);
61
+ if (typeof parsed === "number" && parsed.toString() != obj) {
62
+ return obj;
63
+ }
64
+ return parsed;
61
65
  }
62
66
  function parseResponse(result) {
63
67
  try {
@@ -67,7 +71,7 @@ function parseResponse(result) {
67
71
  }
68
72
  }
69
73
 
70
- // pkg/command.ts
74
+ // pkg/commands/command.ts
71
75
  var Command = class {
72
76
  constructor(command, opts) {
73
77
  var _a;
@@ -347,8 +351,8 @@ var HScanCommand = class extends Command {
347
351
 
348
352
  // pkg/commands/hset.ts
349
353
  var HSetCommand = class extends Command {
350
- constructor(key, field, value) {
351
- super(["hset", key, field, value]);
354
+ constructor(key, kv) {
355
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
352
356
  }
353
357
  };
354
358
 
@@ -1109,8 +1113,8 @@ var Pipeline = class {
1109
1113
  hscan(...args) {
1110
1114
  return this.chain(new HScanCommand(...args));
1111
1115
  }
1112
- hset(key, field, value) {
1113
- return this.chain(new HSetCommand(key, field, value));
1116
+ hset(key, kv) {
1117
+ return this.chain(new HSetCommand(key, kv));
1114
1118
  }
1115
1119
  hsetnx(key, field, value) {
1116
1120
  return this.chain(new HSetNXCommand(key, field, value));
@@ -1440,8 +1444,8 @@ var Redis = class {
1440
1444
  hscan(...args) {
1441
1445
  return new HScanCommand(...args).exec(this.client);
1442
1446
  }
1443
- hset(key, field, value) {
1444
- return new HSetCommand(key, field, value).exec(this.client);
1447
+ hset(key, kv) {
1448
+ return new HSetCommand(key, kv).exec(this.client);
1445
1449
  }
1446
1450
  hsetnx(key, field, value) {
1447
1451
  return new HSetNXCommand(key, field, value).exec(this.client);
@@ -1680,7 +1684,6 @@ var Redis = class {
1680
1684
  };
1681
1685
 
1682
1686
  // pkg/http.ts
1683
- var import_isomorphic_fetch = require("isomorphic-fetch");
1684
1687
  var HttpClient = class {
1685
1688
  constructor(config) {
1686
1689
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
package/cloudflare.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  Redis
3
- } from "./chunk-Y5TC4HX2.mjs";
4
- import "./chunk-ZIB6XPPC.mjs";
3
+ } from "./chunk-T66TTHSV.mjs";
4
+ import "./chunk-HGM7M7CJ.mjs";
5
5
  import {
6
6
  HttpClient
7
- } from "./chunk-U7OXAQMQ.mjs";
7
+ } from "./chunk-HIDCSH5S.mjs";
8
8
  import "./chunk-7YUZYRJS.mjs";
9
9
 
10
10
  // pkg/cloudflare.ts
package/commands.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { at as Command, N as NonEmptyArray } from './zunionstore-dffa797d';
2
- export { A as AppendCommand, B as BitCountCommand, a as BitPosCommand, b as DecrByCommand, D as DecrCommand, c as DelCommand, E as EchoCommand, d as ExistsCommand, f as ExpireAtCommand, e as ExpireCommand, F as FlushAllCommand, g as FlushDBCommand, h as GetBitCommand, G as GetCommand, i as GetRangeCommand, H as HDelCommand, j as HExistsCommand, l as HGetAllCommand, k as HGetCommand, m as HIncrByCommand, n as HIncrByFloatCommand, o as HKeysCommand, p as HLenCommand, q as HMGetCommand, r as HScanCommand, s as HStrLenCommand, t as HValsCommand, u as IncrByCommand, v as IncrByFloatCommand, I as IncrCommand, K as KeysCommand, L as LIndexCommand, w as LLenCommand, x as LPopCommand, y as LRangeCommand, z as LTrimCommand, M as MGetCommand, O as PExpireAtCommand, J as PExpireCommand, R as PTtlCommand, P as PersistCommand, Q as PingCommand, U as RPopCommand, S as RenameCommand, T as RenameNXCommand, W as SCardCommand, X as SDiffCommand, Y as SDiffStoreCommand, a0 as SInterCommand, a1 as SInterStoreCommand, a2 as SMembersCommand, a3 as SPopCommand, a4 as SRandMemberCommand, a5 as SScanCommand, a7 as SUnionCommand, a8 as SUnionStoreCommand, V as ScanCommand, au as ScanCommandOptions, ad as ScoreMember, _ as SetBitCommand, av as SetCommand, Z as SetCommandOptions, $ as SetRangeCommand, a6 as StrLenCommand, a9 as TouchCommand, aa as TtlCommand, as as Type, ab as TypeCommand, ac as UnlinkCommand, aw as ZAddCommand, ae as ZAddCommandOptions, af as ZAddCommandOptionsWithIncr, ag as ZCardCommand, ah as ZCountCommand, ai as ZInterStoreCommand, ax as ZInterStoreCommandOptions, aj as ZLexCountCommand, ak as ZPopMaxCommand, al as ZPopMinCommand, am as ZRangeCommand, ay as ZRangeCommandOptions, an as ZRemRangeByLexCommand, ao as ZRemRangeByRankCommand, ap as ZRemRangeByScoreCommand, aq as ZScanCommand, ar as ZUnionStoreCommand, az as ZUnionStoreCommandOptions } from './zunionstore-dffa797d';
1
+ import { at as Command, N as NonEmptyArray } from './zunionstore-b38007ba';
2
+ export { A as AppendCommand, B as BitCountCommand, a as BitPosCommand, at as Command, b as DecrByCommand, D as DecrCommand, c as DelCommand, E as EchoCommand, d as ExistsCommand, f as ExpireAtCommand, e as ExpireCommand, F as FlushAllCommand, g as FlushDBCommand, h as GetBitCommand, G as GetCommand, i as GetRangeCommand, H as HDelCommand, j as HExistsCommand, l as HGetAllCommand, k as HGetCommand, m as HIncrByCommand, n as HIncrByFloatCommand, o as HKeysCommand, p as HLenCommand, q as HMGetCommand, r as HScanCommand, s as HStrLenCommand, t as HValsCommand, u as IncrByCommand, v as IncrByFloatCommand, I as IncrCommand, K as KeysCommand, L as LIndexCommand, w as LLenCommand, x as LPopCommand, y as LRangeCommand, z as LTrimCommand, M as MGetCommand, O as PExpireAtCommand, J as PExpireCommand, R as PTtlCommand, P as PersistCommand, Q as PingCommand, U as RPopCommand, S as RenameCommand, T as RenameNXCommand, W as SCardCommand, X as SDiffCommand, Y as SDiffStoreCommand, a0 as SInterCommand, a1 as SInterStoreCommand, a2 as SMembersCommand, a3 as SPopCommand, a4 as SRandMemberCommand, a5 as SScanCommand, a7 as SUnionCommand, a8 as SUnionStoreCommand, V as ScanCommand, au as ScanCommandOptions, ad as ScoreMember, _ as SetBitCommand, av as SetCommand, Z as SetCommandOptions, $ as SetRangeCommand, a6 as StrLenCommand, a9 as TouchCommand, aa as TtlCommand, as as Type, ab as TypeCommand, ac as UnlinkCommand, aw as ZAddCommand, ae as ZAddCommandOptions, af as ZAddCommandOptionsWithIncr, ag as ZCardCommand, ah as ZCountCommand, ai as ZInterStoreCommand, ax as ZInterStoreCommandOptions, aj as ZLexCountCommand, ak as ZPopMaxCommand, al as ZPopMinCommand, am as ZRangeCommand, ay as ZRangeCommandOptions, an as ZRemRangeByLexCommand, ao as ZRemRangeByRankCommand, ap as ZRemRangeByScoreCommand, aq as ZScanCommand, ar as ZUnionStoreCommand, az as ZUnionStoreCommandOptions } from './zunionstore-b38007ba';
3
3
  import './http';
4
4
 
5
5
  /**
@@ -37,7 +37,9 @@ declare class HMSetCommand<TData> extends Command<number, number> {
37
37
  * @see https://redis.io/commands/hset
38
38
  */
39
39
  declare class HSetCommand<TData> extends Command<number, number> {
40
- constructor(key: string, field: string, value: TData);
40
+ constructor(key: string, kv: {
41
+ [field: string]: TData;
42
+ });
41
43
  }
42
44
 
43
45
  /**
package/commands.js CHANGED
@@ -28,6 +28,7 @@ __export(commands_exports, {
28
28
  BitCountCommand: () => BitCountCommand,
29
29
  BitOpCommand: () => BitOpCommand,
30
30
  BitPosCommand: () => BitPosCommand,
31
+ Command: () => Command,
31
32
  DBSizeCommand: () => DBSizeCommand,
32
33
  DecrByCommand: () => DecrByCommand,
33
34
  DecrCommand: () => DecrCommand,
@@ -143,13 +144,17 @@ var UpstashError = class extends Error {
143
144
 
144
145
  // pkg/util.ts
145
146
  function parseRecursive(obj) {
146
- return Array.isArray(obj) ? obj.map((o) => {
147
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
147
148
  try {
148
149
  return parseRecursive(o);
149
150
  } catch {
150
151
  return o;
151
152
  }
152
153
  }) : JSON.parse(obj);
154
+ if (typeof parsed === "number" && parsed.toString() != obj) {
155
+ return obj;
156
+ }
157
+ return parsed;
153
158
  }
154
159
  function parseResponse(result) {
155
160
  try {
@@ -159,7 +164,7 @@ function parseResponse(result) {
159
164
  }
160
165
  }
161
166
 
162
- // pkg/command.ts
167
+ // pkg/commands/command.ts
163
168
  var Command = class {
164
169
  constructor(command, opts) {
165
170
  var _a;
@@ -439,8 +444,8 @@ var HScanCommand = class extends Command {
439
444
 
440
445
  // pkg/commands/hset.ts
441
446
  var HSetCommand = class extends Command {
442
- constructor(key, field, value) {
443
- super(["hset", key, field, value]);
447
+ constructor(key, kv) {
448
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
444
449
  }
445
450
  };
446
451
 
@@ -1095,6 +1100,7 @@ module.exports = __toCommonJS(commands_exports);
1095
1100
  BitCountCommand,
1096
1101
  BitOpCommand,
1097
1102
  BitPosCommand,
1103
+ Command,
1098
1104
  DBSizeCommand,
1099
1105
  DecrByCommand,
1100
1106
  DecrCommand,
package/commands.mjs CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  BitCountCommand,
4
4
  BitOpCommand,
5
5
  BitPosCommand,
6
+ Command,
6
7
  DBSizeCommand,
7
8
  DecrByCommand,
8
9
  DecrCommand,
@@ -106,13 +107,14 @@ import {
106
107
  ZScanCommand,
107
108
  ZScoreCommand,
108
109
  ZUnionStoreCommand
109
- } from "./chunk-ZIB6XPPC.mjs";
110
+ } from "./chunk-HGM7M7CJ.mjs";
110
111
  import "./chunk-7YUZYRJS.mjs";
111
112
  export {
112
113
  AppendCommand,
113
114
  BitCountCommand,
114
115
  BitOpCommand,
115
116
  BitPosCommand,
117
+ Command,
116
118
  DBSizeCommand,
117
119
  DecrByCommand,
118
120
  DecrCommand,
package/fastly.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Redis$1 } from './redis-dd052782';
2
- import './zunionstore-dffa797d';
1
+ import { R as Redis$1 } from './redis-71fa1ee6';
2
+ import './zunionstore-b38007ba';
3
3
  import './http';
4
4
 
5
5
  /**
package/fastly.js CHANGED
@@ -51,13 +51,17 @@ var UpstashError = class extends Error {
51
51
 
52
52
  // pkg/util.ts
53
53
  function parseRecursive(obj) {
54
- return Array.isArray(obj) ? obj.map((o) => {
54
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
55
55
  try {
56
56
  return parseRecursive(o);
57
57
  } catch {
58
58
  return o;
59
59
  }
60
60
  }) : JSON.parse(obj);
61
+ if (typeof parsed === "number" && parsed.toString() != obj) {
62
+ return obj;
63
+ }
64
+ return parsed;
61
65
  }
62
66
  function parseResponse(result) {
63
67
  try {
@@ -67,7 +71,7 @@ function parseResponse(result) {
67
71
  }
68
72
  }
69
73
 
70
- // pkg/command.ts
74
+ // pkg/commands/command.ts
71
75
  var Command = class {
72
76
  constructor(command, opts) {
73
77
  var _a;
@@ -347,8 +351,8 @@ var HScanCommand = class extends Command {
347
351
 
348
352
  // pkg/commands/hset.ts
349
353
  var HSetCommand = class extends Command {
350
- constructor(key, field, value) {
351
- super(["hset", key, field, value]);
354
+ constructor(key, kv) {
355
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
352
356
  }
353
357
  };
354
358
 
@@ -1109,8 +1113,8 @@ var Pipeline = class {
1109
1113
  hscan(...args) {
1110
1114
  return this.chain(new HScanCommand(...args));
1111
1115
  }
1112
- hset(key, field, value) {
1113
- return this.chain(new HSetCommand(key, field, value));
1116
+ hset(key, kv) {
1117
+ return this.chain(new HSetCommand(key, kv));
1114
1118
  }
1115
1119
  hsetnx(key, field, value) {
1116
1120
  return this.chain(new HSetNXCommand(key, field, value));
@@ -1440,8 +1444,8 @@ var Redis = class {
1440
1444
  hscan(...args) {
1441
1445
  return new HScanCommand(...args).exec(this.client);
1442
1446
  }
1443
- hset(key, field, value) {
1444
- return new HSetCommand(key, field, value).exec(this.client);
1447
+ hset(key, kv) {
1448
+ return new HSetCommand(key, kv).exec(this.client);
1445
1449
  }
1446
1450
  hsetnx(key, field, value) {
1447
1451
  return new HSetNXCommand(key, field, value).exec(this.client);
@@ -1680,7 +1684,6 @@ var Redis = class {
1680
1684
  };
1681
1685
 
1682
1686
  // pkg/http.ts
1683
- var import_isomorphic_fetch = require("isomorphic-fetch");
1684
1687
  var HttpClient = class {
1685
1688
  constructor(config) {
1686
1689
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
package/fastly.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  Redis
3
- } from "./chunk-Y5TC4HX2.mjs";
4
- import "./chunk-ZIB6XPPC.mjs";
3
+ } from "./chunk-T66TTHSV.mjs";
4
+ import "./chunk-HGM7M7CJ.mjs";
5
5
  import {
6
6
  HttpClient
7
- } from "./chunk-U7OXAQMQ.mjs";
7
+ } from "./chunk-HIDCSH5S.mjs";
8
8
  import "./chunk-7YUZYRJS.mjs";
9
9
 
10
10
  // pkg/fastly.ts
package/http.js CHANGED
@@ -40,7 +40,6 @@ var http_exports = {};
40
40
  __export(http_exports, {
41
41
  HttpClient: () => HttpClient
42
42
  });
43
- var import_isomorphic_fetch = require("isomorphic-fetch");
44
43
 
45
44
  // pkg/error.ts
46
45
  var UpstashError = class extends Error {
package/http.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HttpClient
3
- } from "./chunk-U7OXAQMQ.mjs";
3
+ } from "./chunk-HIDCSH5S.mjs";
4
4
  import "./chunk-7YUZYRJS.mjs";
5
5
  export {
6
6
  HttpClient
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Redis, RedisConfigNodejs } from './nodejs';
2
- import './redis-dd052782';
3
- import './zunionstore-dffa797d';
2
+ import './redis-71fa1ee6';
3
+ import './zunionstore-b38007ba';
4
4
  import './http';
5
5
 
6
6
  /**
package/index.js CHANGED
@@ -52,13 +52,17 @@ var UpstashError = class extends Error {
52
52
 
53
53
  // pkg/util.ts
54
54
  function parseRecursive(obj) {
55
- return Array.isArray(obj) ? obj.map((o) => {
55
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
56
56
  try {
57
57
  return parseRecursive(o);
58
58
  } catch {
59
59
  return o;
60
60
  }
61
61
  }) : JSON.parse(obj);
62
+ if (typeof parsed === "number" && parsed.toString() != obj) {
63
+ return obj;
64
+ }
65
+ return parsed;
62
66
  }
63
67
  function parseResponse(result) {
64
68
  try {
@@ -68,7 +72,7 @@ function parseResponse(result) {
68
72
  }
69
73
  }
70
74
 
71
- // pkg/command.ts
75
+ // pkg/commands/command.ts
72
76
  var Command = class {
73
77
  constructor(command, opts) {
74
78
  var _a;
@@ -348,8 +352,8 @@ var HScanCommand = class extends Command {
348
352
 
349
353
  // pkg/commands/hset.ts
350
354
  var HSetCommand = class extends Command {
351
- constructor(key, field, value) {
352
- super(["hset", key, field, value]);
355
+ constructor(key, kv) {
356
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
353
357
  }
354
358
  };
355
359
 
@@ -1110,8 +1114,8 @@ var Pipeline = class {
1110
1114
  hscan(...args) {
1111
1115
  return this.chain(new HScanCommand(...args));
1112
1116
  }
1113
- hset(key, field, value) {
1114
- return this.chain(new HSetCommand(key, field, value));
1117
+ hset(key, kv) {
1118
+ return this.chain(new HSetCommand(key, kv));
1115
1119
  }
1116
1120
  hsetnx(key, field, value) {
1117
1121
  return this.chain(new HSetNXCommand(key, field, value));
@@ -1441,8 +1445,8 @@ var Redis = class {
1441
1445
  hscan(...args) {
1442
1446
  return new HScanCommand(...args).exec(this.client);
1443
1447
  }
1444
- hset(key, field, value) {
1445
- return new HSetCommand(key, field, value).exec(this.client);
1448
+ hset(key, kv) {
1449
+ return new HSetCommand(key, kv).exec(this.client);
1446
1450
  }
1447
1451
  hsetnx(key, field, value) {
1448
1452
  return new HSetNXCommand(key, field, value).exec(this.client);
@@ -1681,7 +1685,6 @@ var Redis = class {
1681
1685
  };
1682
1686
 
1683
1687
  // pkg/http.ts
1684
- var import_isomorphic_fetch = require("isomorphic-fetch");
1685
1688
  var HttpClient = class {
1686
1689
  constructor(config) {
1687
1690
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
@@ -1710,7 +1713,7 @@ var HttpClient = class {
1710
1713
  };
1711
1714
 
1712
1715
  // pkg/nodejs.ts
1713
- var import_isomorphic_fetch2 = require("isomorphic-fetch");
1716
+ var import_isomorphic_fetch = require("isomorphic-fetch");
1714
1717
  var Redis2 = class extends Redis {
1715
1718
  constructor(config) {
1716
1719
  const client = new HttpClient({
package/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Redis
3
- } from "./chunk-FJSI5EBJ.mjs";
4
- import "./chunk-Y5TC4HX2.mjs";
5
- import "./chunk-ZIB6XPPC.mjs";
6
- import "./chunk-U7OXAQMQ.mjs";
3
+ } from "./chunk-AHCVU33N.mjs";
4
+ import "./chunk-T66TTHSV.mjs";
5
+ import "./chunk-HGM7M7CJ.mjs";
6
+ import "./chunk-HIDCSH5S.mjs";
7
7
  import {
8
8
  UpstashError
9
9
  } from "./chunk-7YUZYRJS.mjs";
package/nodejs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Redis$1 } from './redis-dd052782';
2
- import './zunionstore-dffa797d';
1
+ import { R as Redis$1 } from './redis-71fa1ee6';
2
+ import './zunionstore-b38007ba';
3
3
  import './http';
4
4
 
5
5
  /**
package/nodejs.js CHANGED
@@ -51,13 +51,17 @@ var UpstashError = class extends Error {
51
51
 
52
52
  // pkg/util.ts
53
53
  function parseRecursive(obj) {
54
- return Array.isArray(obj) ? obj.map((o) => {
54
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
55
55
  try {
56
56
  return parseRecursive(o);
57
57
  } catch {
58
58
  return o;
59
59
  }
60
60
  }) : JSON.parse(obj);
61
+ if (typeof parsed === "number" && parsed.toString() != obj) {
62
+ return obj;
63
+ }
64
+ return parsed;
61
65
  }
62
66
  function parseResponse(result) {
63
67
  try {
@@ -67,7 +71,7 @@ function parseResponse(result) {
67
71
  }
68
72
  }
69
73
 
70
- // pkg/command.ts
74
+ // pkg/commands/command.ts
71
75
  var Command = class {
72
76
  constructor(command, opts) {
73
77
  var _a;
@@ -347,8 +351,8 @@ var HScanCommand = class extends Command {
347
351
 
348
352
  // pkg/commands/hset.ts
349
353
  var HSetCommand = class extends Command {
350
- constructor(key, field, value) {
351
- super(["hset", key, field, value]);
354
+ constructor(key, kv) {
355
+ super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])]);
352
356
  }
353
357
  };
354
358
 
@@ -1109,8 +1113,8 @@ var Pipeline = class {
1109
1113
  hscan(...args) {
1110
1114
  return this.chain(new HScanCommand(...args));
1111
1115
  }
1112
- hset(key, field, value) {
1113
- return this.chain(new HSetCommand(key, field, value));
1116
+ hset(key, kv) {
1117
+ return this.chain(new HSetCommand(key, kv));
1114
1118
  }
1115
1119
  hsetnx(key, field, value) {
1116
1120
  return this.chain(new HSetNXCommand(key, field, value));
@@ -1440,8 +1444,8 @@ var Redis = class {
1440
1444
  hscan(...args) {
1441
1445
  return new HScanCommand(...args).exec(this.client);
1442
1446
  }
1443
- hset(key, field, value) {
1444
- return new HSetCommand(key, field, value).exec(this.client);
1447
+ hset(key, kv) {
1448
+ return new HSetCommand(key, kv).exec(this.client);
1445
1449
  }
1446
1450
  hsetnx(key, field, value) {
1447
1451
  return new HSetNXCommand(key, field, value).exec(this.client);
@@ -1680,7 +1684,6 @@ var Redis = class {
1680
1684
  };
1681
1685
 
1682
1686
  // pkg/http.ts
1683
- var import_isomorphic_fetch = require("isomorphic-fetch");
1684
1687
  var HttpClient = class {
1685
1688
  constructor(config) {
1686
1689
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
@@ -1709,7 +1712,7 @@ var HttpClient = class {
1709
1712
  };
1710
1713
 
1711
1714
  // pkg/nodejs.ts
1712
- var import_isomorphic_fetch2 = require("isomorphic-fetch");
1715
+ var import_isomorphic_fetch = require("isomorphic-fetch");
1713
1716
  var Redis2 = class extends Redis {
1714
1717
  constructor(config) {
1715
1718
  const client = new HttpClient({
package/nodejs.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Redis
3
- } from "./chunk-FJSI5EBJ.mjs";
4
- import "./chunk-Y5TC4HX2.mjs";
5
- import "./chunk-ZIB6XPPC.mjs";
6
- import "./chunk-U7OXAQMQ.mjs";
3
+ } from "./chunk-AHCVU33N.mjs";
4
+ import "./chunk-T66TTHSV.mjs";
5
+ import "./chunk-HGM7M7CJ.mjs";
6
+ import "./chunk-HIDCSH5S.mjs";
7
7
  import "./chunk-7YUZYRJS.mjs";
8
8
  export {
9
9
  Redis
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@upstash/redis", "version": "v1.0.0-alpha.3", "engines": { "node": ">=10" }, "description": "An HTTP/REST based Redis client built on top of Upstash REST API.", "main": "./index.js", "module": "./index.mjs", "types": "./index.d.ts", "scripts": { "test": "jest -i", "fmt": "pnpm lint && pnpm prettier --write .", "lint": "eslint --ext .ts --fix --ignore-path .gitignore .", "build": "tsup && cp package.json ./dist/ && pnpm size-limit" }, "repository": { "type": "git", "url": "git+https://github.com/upstash/upstash-redis.git" }, "keywords": [ "redis", "database", "serverless", "edge", "upstash" ], "author": "Andreas Thomas <andreas.thomas@chronark.com>", "license": "MIT", "bugs": { "url": "https://github.com/upstash/upstash-redis/issues" }, "homepage": "https://github.com/upstash/upstash-redis#readme", "directories": { "examples": "examples" }, "devDependencies": { "@jest/globals": "^27.4.6", "@size-limit/preset-small-lib": "^7.0.8", "@trivago/prettier-plugin-sort-imports": "^3.2.0", "@types/jest": "^27.4.0", "@types/node": "^17.0.8", "@typescript-eslint/eslint-plugin": "^5.9.1", "@typescript-eslint/parser": "^5.9.1", "dotenv": "^12.0.3", "eslint": "^8.6.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.4.7", "prettier": "^2.5.1", "size-limit": "^7.0.8", "ts-jest": "^27.1.3", "tsup": "^5.11.11", "typescript": "^4.5.5" }, "dependencies": { "isomorphic-fetch": "^3.0.0" }, "browser": { "isomorphic-fetch": false }, "size-limit": [ { "path": "dist/index.js", "limit": "5 KB" }, { "path": "dist/index.mjs", "limit": "5 KB" } ] }
1
+ { "name": "@upstash/redis", "version": "v1.0.0", "engines": { "node": ">=10" }, "description": "An HTTP/REST based Redis client built on top of Upstash REST API.", "main": "./index.js", "module": "./index.mjs", "types": "./index.d.ts", "scripts": { "test": "jest -i", "fmt": "pnpm lint && pnpm prettier --write .", "lint": "eslint --ext .ts --fix --ignore-path .gitignore .", "build": "tsup && cp package.json ./dist/ && pnpm size-limit" }, "repository": { "type": "git", "url": "git+https://github.com/upstash/upstash-redis.git" }, "keywords": [ "redis", "database", "serverless", "edge", "upstash" ], "author": "Andreas Thomas <andreas.thomas@chronark.com>", "license": "MIT", "bugs": { "url": "https://github.com/upstash/upstash-redis/issues" }, "homepage": "https://github.com/upstash/upstash-redis#readme", "directories": { "examples": "examples" }, "devDependencies": { "@jest/globals": "^27.4.6", "@size-limit/preset-small-lib": "^7.0.8", "@trivago/prettier-plugin-sort-imports": "^3.2.0", "@types/jest": "^27.4.0", "@types/node": "^17.0.8", "@typescript-eslint/eslint-plugin": "^5.9.1", "@typescript-eslint/parser": "^5.9.1", "dotenv": "^12.0.3", "eslint": "^8.6.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.4.7", "prettier": "^2.5.1", "size-limit": "^7.0.8", "ts-jest": "^27.1.3", "tsup": "^5.11.11", "typescript": "^4.5.5" }, "dependencies": { "isomorphic-fetch": "^3.0.0" }, "browser": { "isomorphic-fetch": false }, "size-limit": [ { "path": "dist/index.js", "limit": "5 KB" }, { "path": "dist/index.mjs", "limit": "5 KB" }, { "path": "dist/cloudflare.js", "limit": "5 KB" }, { "path": "dist/cloudflare.mjs", "limit": "5 KB" }, { "path": "dist/nodejs.js", "limit": "5 KB" }, { "path": "dist/nodejs.mjs", "limit": "5 KB" }, { "path": "dist/fastly.js", "limit": "5 KB" }, { "path": "dist/fastly.mjs", "limit": "5 KB" } ] }
@@ -1,4 +1,4 @@
1
- import { C as CommandArgs, A as AppendCommand, B as BitCountCommand, a as BitPosCommand, D as DecrCommand, b as DecrByCommand, c as DelCommand, E as EchoCommand, d as ExistsCommand, e as ExpireCommand, f as ExpireAtCommand, F as FlushAllCommand, g as FlushDBCommand, G as GetCommand, h as GetBitCommand, i as GetRangeCommand, H as HDelCommand, j as HExistsCommand, k as HGetCommand, l as HGetAllCommand, m as HIncrByCommand, n as HIncrByFloatCommand, o as HKeysCommand, p as HLenCommand, q as HMGetCommand, r as HScanCommand, s as HStrLenCommand, t as HValsCommand, I as IncrCommand, u as IncrByCommand, v as IncrByFloatCommand, K as KeysCommand, L as LIndexCommand, w as LLenCommand, x as LPopCommand, N as NonEmptyArray, y as LRangeCommand, z as LTrimCommand, M as MGetCommand, P as PersistCommand, J as PExpireCommand, O as PExpireAtCommand, Q as PingCommand, R as PTtlCommand, S as RenameCommand, T as RenameNXCommand, U as RPopCommand, V as ScanCommand, W as SCardCommand, X as SDiffCommand, Y as SDiffStoreCommand, Z as SetCommandOptions, _ as SetBitCommand, $ as SetRangeCommand, a0 as SInterCommand, a1 as SInterStoreCommand, a2 as SMembersCommand, a3 as SPopCommand, a4 as SRandMemberCommand, a5 as SScanCommand, a6 as StrLenCommand, a7 as SUnionCommand, a8 as SUnionStoreCommand, a9 as TouchCommand, aa as TtlCommand, ab as TypeCommand, ac as UnlinkCommand, ad as ScoreMember, ae as ZAddCommandOptions, af as ZAddCommandOptionsWithIncr, ag as ZCardCommand, ah as ZCountCommand, ai as ZInterStoreCommand, aj as ZLexCountCommand, ak as ZPopMaxCommand, al as ZPopMinCommand, am as ZRangeCommand, an as ZRemRangeByLexCommand, ao as ZRemRangeByRankCommand, ap as ZRemRangeByScoreCommand, aq as ZScanCommand, ar as ZUnionStoreCommand, as as Type } from './zunionstore-dffa797d';
1
+ import { C as CommandArgs, A as AppendCommand, B as BitCountCommand, a as BitPosCommand, D as DecrCommand, b as DecrByCommand, c as DelCommand, E as EchoCommand, d as ExistsCommand, e as ExpireCommand, f as ExpireAtCommand, F as FlushAllCommand, g as FlushDBCommand, G as GetCommand, h as GetBitCommand, i as GetRangeCommand, H as HDelCommand, j as HExistsCommand, k as HGetCommand, l as HGetAllCommand, m as HIncrByCommand, n as HIncrByFloatCommand, o as HKeysCommand, p as HLenCommand, q as HMGetCommand, r as HScanCommand, s as HStrLenCommand, t as HValsCommand, I as IncrCommand, u as IncrByCommand, v as IncrByFloatCommand, K as KeysCommand, L as LIndexCommand, w as LLenCommand, x as LPopCommand, N as NonEmptyArray, y as LRangeCommand, z as LTrimCommand, M as MGetCommand, P as PersistCommand, J as PExpireCommand, O as PExpireAtCommand, Q as PingCommand, R as PTtlCommand, S as RenameCommand, T as RenameNXCommand, U as RPopCommand, V as ScanCommand, W as SCardCommand, X as SDiffCommand, Y as SDiffStoreCommand, Z as SetCommandOptions, _ as SetBitCommand, $ as SetRangeCommand, a0 as SInterCommand, a1 as SInterStoreCommand, a2 as SMembersCommand, a3 as SPopCommand, a4 as SRandMemberCommand, a5 as SScanCommand, a6 as StrLenCommand, a7 as SUnionCommand, a8 as SUnionStoreCommand, a9 as TouchCommand, aa as TtlCommand, ab as TypeCommand, ac as UnlinkCommand, ad as ScoreMember, ae as ZAddCommandOptions, af as ZAddCommandOptionsWithIncr, ag as ZCardCommand, ah as ZCountCommand, ai as ZInterStoreCommand, aj as ZLexCountCommand, ak as ZPopMaxCommand, al as ZPopMinCommand, am as ZRangeCommand, an as ZRemRangeByLexCommand, ao as ZRemRangeByRankCommand, ap as ZRemRangeByScoreCommand, aq as ZScanCommand, ar as ZUnionStoreCommand, as as Type } from './zunionstore-b38007ba';
2
2
  import { HttpClient } from './http';
3
3
 
4
4
  /**
@@ -182,7 +182,9 @@ declare class Pipeline {
182
182
  /**
183
183
  * @see https://redis.io/commands/hset
184
184
  */
185
- hset<TData>(key: string, field: string, value: TData): this;
185
+ hset<TData>(key: string, kv: {
186
+ [field: string]: TData;
187
+ }): this;
186
188
  /**
187
189
  * @see https://redis.io/commands/hsetnx
188
190
  */
@@ -643,7 +645,9 @@ declare class Redis {
643
645
  /**
644
646
  * @see https://redis.io/commands/hset
645
647
  */
646
- hset<TData>(key: string, field: string, value: TData): Promise<number>;
648
+ hset<TData>(key: string, kv: {
649
+ [field: string]: TData;
650
+ }): Promise<number>;
647
651
  /**
648
652
  * @see https://redis.io/commands/hsetnx
649
653
  */
@@ -6,7 +6,7 @@ import { HttpClient } from './http';
6
6
  * TData represents what the user will enter or receive,
7
7
  * TResult is the raw data returned from upstash, which may need to be transformed or parsed.
8
8
  */
9
- declare abstract class Command<TData, TResult> {
9
+ declare class Command<TData, TResult> {
10
10
  readonly command: string[];
11
11
  deserialize: (result: TResult) => TData;
12
12
  /**