@upstash/redis 0.0.0-ci.9190cbfb-20230208 → 0.0.0-ci.97cb5577-20231010

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.
@@ -4,6 +4,6 @@ import { Command } from "./command.js";
4
4
  */
5
5
  export class JsonForgetCommand extends Command {
6
6
  constructor(cmd, opts) {
7
- super(["JSON.DEL", ...cmd], opts);
7
+ super(["JSON.FORGET", ...cmd], opts);
8
8
  }
9
9
  }
@@ -120,6 +120,7 @@ export * from "./touch.js";
120
120
  export * from "./ttl.js";
121
121
  export * from "./type.js";
122
122
  export * from "./unlink.js";
123
+ export * from "./xadd.js";
123
124
  export * from "./zadd.js";
124
125
  export * from "./zcard.js";
125
126
  export * from "./zcount.js";
@@ -28,7 +28,7 @@ export class SetCommand extends Command {
28
28
  command.push("pxat", opts.pxat);
29
29
  }
30
30
  else if ("keepTtl" in opts && opts.keepTtl) {
31
- command.push("keepTtl", opts.keepTtl);
31
+ command.push("keepTtl");
32
32
  }
33
33
  }
34
34
  super(command, cmdOpts);
@@ -0,0 +1,26 @@
1
+ import { Command } from "./command.js";
2
+ /**
3
+ * @see https://redis.io/commands/xadd
4
+ */
5
+ export class XAddCommand extends Command {
6
+ constructor([key, id, entries, opts], commandOptions) {
7
+ const command = ["XADD", key];
8
+ if (opts) {
9
+ if (opts.nomkStream) {
10
+ command.push("NOMKSTREAM");
11
+ }
12
+ if (opts.trim) {
13
+ command.push(opts.trim.type, opts.trim.comparison, opts.trim.threshold);
14
+ if (typeof opts.trim.limit !== "undefined") {
15
+ command.push("LIMIT", opts.trim.limit);
16
+ }
17
+ }
18
+ }
19
+ command.push(id);
20
+ // entries
21
+ Object.entries(entries).forEach(([k, v]) => {
22
+ command.push(k, v);
23
+ });
24
+ super(command, commandOptions);
25
+ }
26
+ }
package/esm/pkg/http.js CHANGED
@@ -28,7 +28,8 @@ export class HttpClient {
28
28
  this.options = {
29
29
  backend: config.options?.backend,
30
30
  agent: config.agent,
31
- responseEncoding: config.responseEncoding ?? "base64", // default to base64
31
+ responseEncoding: config.responseEncoding ?? "base64",
32
+ cache: config.cache,
32
33
  };
33
34
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
34
35
  this.headers = {
@@ -71,6 +72,7 @@ export class HttpClient {
71
72
  }
72
73
  async request(req) {
73
74
  const requestOptions = {
75
+ cache: this.options.cache,
74
76
  method: "POST",
75
77
  headers: this.headers,
76
78
  body: JSON.stringify(req.body),
@@ -98,10 +100,17 @@ export class HttpClient {
98
100
  }
99
101
  const body = (await res.json());
100
102
  if (!res.ok) {
101
- throw new UpstashError(body.error);
103
+ throw new UpstashError(`${body.error}, command was: ${JSON.stringify(req.body)}`);
102
104
  }
103
105
  if (this.options?.responseEncoding === "base64") {
104
- return Array.isArray(body) ? body.map(decode) : decode(body);
106
+ if (Array.isArray(body)) {
107
+ return body.map(({ result, error }) => ({
108
+ result: decode(result),
109
+ error,
110
+ }));
111
+ }
112
+ const result = decode(body.result);
113
+ return { result, error: body.error };
105
114
  }
106
115
  return body;
107
116
  }
@@ -132,19 +141,19 @@ function base64decode(b64) {
132
141
  }
133
142
  function decode(raw) {
134
143
  let result = undefined;
135
- switch (typeof raw.result) {
144
+ switch (typeof raw) {
136
145
  case "undefined":
137
146
  return raw;
138
147
  case "number": {
139
- result = raw.result;
148
+ result = raw;
140
149
  break;
141
150
  }
142
151
  case "object": {
143
- if (Array.isArray(raw.result)) {
144
- result = raw.result.map((v) => typeof v === "string"
152
+ if (Array.isArray(raw)) {
153
+ result = raw.map((v) => typeof v === "string"
145
154
  ? base64decode(v)
146
155
  : Array.isArray(v)
147
- ? v.map(base64decode)
156
+ ? v.map(decode)
148
157
  : v);
149
158
  }
150
159
  else {
@@ -155,11 +164,11 @@ function decode(raw) {
155
164
  break;
156
165
  }
157
166
  case "string": {
158
- result = raw.result === "OK" ? "OK" : base64decode(raw.result);
167
+ result = raw === "OK" ? "OK" : base64decode(raw);
159
168
  break;
160
169
  }
161
170
  default:
162
171
  break;
163
172
  }
164
- return { result, error: raw.error };
173
+ return result;
165
174
  }
@@ -31,7 +31,7 @@ import { ZDiffStoreCommand } from "./commands/zdiffstore.js";
31
31
  * const res = await p.set("key","value").get("key").exec()
32
32
  * ```
33
33
  *
34
- * It's not possible to infer correct types with a dynamic pipeline, so you can
34
+ * Return types are inferred if all commands are chained, but you can still
35
35
  * override the response type manually:
36
36
  * ```ts
37
37
  * redis.pipeline()
@@ -72,9 +72,11 @@ export class Pipeline {
72
72
  *
73
73
  * Returns an array with the results of all pipelined commands.
74
74
  *
75
- * You can define a return type manually to make working in typescript easier
75
+ * If all commands are statically chained from start to finish, types are inferred. You can still define a return type manually if necessary though:
76
76
  * ```ts
77
- * redis.pipeline().get("key").exec<[{ greeting: string }]>()
77
+ * const p = redis.pipeline()
78
+ * p.get("key")
79
+ * const result = p.exec<[{ greeting: string }]>()
78
80
  * ```
79
81
  */
80
82
  Object.defineProperty(this, "exec", {
@@ -90,6 +92,7 @@ export class Pipeline {
90
92
  path,
91
93
  body: Object.values(this.commands).map((c) => c.command),
92
94
  }));
95
+ console.log("after req", { res });
93
96
  return res.map(({ error, result }, i) => {
94
97
  if (error) {
95
98
  throw new UpstashError(`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`);
@@ -1184,23 +1187,22 @@ export class Pipeline {
1184
1187
  value: (...args) => this.chain(new ZUnionStoreCommand(args, this.commandOptions))
1185
1188
  });
1186
1189
  this.client = opts.client;
1187
- this.commands = [];
1190
+ this.commands = []; // the TCommands generic in the class definition is only used for carrying through chained command types and should never be explicitly set when instantiating the class
1188
1191
  this.commandOptions = opts.commandOptions;
1189
1192
  this.multiExec = opts.multiExec ?? false;
1190
1193
  }
1191
1194
  /**
1192
- * Pushes a command into the pipelien and returns a chainable instance of the
1195
+ * Pushes a command into the pipeline and returns a chainable instance of the
1193
1196
  * pipeline
1194
1197
  */
1195
1198
  chain(command) {
1196
1199
  this.commands.push(command);
1197
- return this;
1200
+ return this; // TS thinks we're returning Pipeline<[]> here, because we're not creating a new instance of the class, hence the cast
1198
1201
  }
1199
1202
  /**
1200
1203
  * @see https://redis.io/commands/?group=json
1201
1204
  */
1202
1205
  get json() {
1203
- // For some reason we needed to define the types manually, otherwise Deno wouldn't build it
1204
1206
  return {
1205
1207
  /**
1206
1208
  * @see https://redis.io/commands/json.arrappend
package/esm/pkg/redis.js CHANGED
@@ -1005,6 +1005,10 @@ export class Redis {
1005
1005
  writable: true,
1006
1006
  value: (...args) => new UnlinkCommand(args, this.opts).exec(this.client)
1007
1007
  });
1008
+ // /**
1009
+ // * @see https://redis.io/commands/xadd
1010
+ // */
1011
+ // xadd =
1008
1012
  /**
1009
1013
  * @see https://redis.io/commands/zadd
1010
1014
  */
@@ -35,13 +35,16 @@ export class Redis extends core.Redis {
35
35
  headers: { authorization: `Bearer ${configOrRequester.token}` },
36
36
  agent: configOrRequester.agent,
37
37
  responseEncoding: configOrRequester.responseEncoding,
38
+ cache: configOrRequester.cache || "no-store",
38
39
  });
39
40
  super(client, {
40
41
  automaticDeserialization: configOrRequester.automaticDeserialization,
41
42
  enableTelemetry: !process.env.UPSTASH_DISABLE_TELEMETRY,
42
43
  });
43
44
  this.addTelemetry({
44
- runtime: `node@${process.version}`,
45
+ runtime: typeof EdgeRuntime === "string"
46
+ ? "edge-light"
47
+ : `node@${process.version}`,
45
48
  platform: process.env.VERCEL
46
49
  ? "vercel"
47
50
  : process.env.AWS_REGION
package/esm/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "v0.0.0-ci.9190cbfb-20230208";
1
+ export const VERSION = "v0.0.0-ci.97cb5577-20231010";
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "main": "./script/platforms/nodejs.js",
4
4
  "types": "./types/platforms/nodejs.d.ts",
5
5
  "name": "@upstash/redis",
6
- "version": "v0.0.0-ci.9190cbfb-20230208",
6
+ "version": "v0.0.0-ci.97cb5577-20231010",
7
7
  "description": "An HTTP/REST based Redis client built on top of Upstash REST API.",
8
8
  "repository": {
9
9
  "type": "git",
@@ -27,10 +27,18 @@
27
27
  },
28
28
  "typesVersions": {
29
29
  "*": {
30
- "nodejs": "./types/platforms/nodejs.d.ts",
31
- "cloudflare": "./types/platforms/cloudflare.d.ts",
32
- "fastly": "./types/platforms/fastly.d.ts",
33
- "with-fetch": "./types/platforms/node_with_fetch.d.ts"
30
+ "nodejs": [
31
+ "./types/platforms/nodejs.d.ts"
32
+ ],
33
+ "cloudflare": [
34
+ "./types/platforms/cloudflare.d.ts"
35
+ ],
36
+ "fastly": [
37
+ "./types/platforms/fastly.d.ts"
38
+ ],
39
+ "with-fetch": [
40
+ "./types/platforms/node_with_fetch.d.ts"
41
+ ]
34
42
  }
35
43
  },
36
44
  "exports": {
@@ -7,7 +7,7 @@ const command_js_1 = require("./command.js");
7
7
  */
8
8
  class JsonForgetCommand extends command_js_1.Command {
9
9
  constructor(cmd, opts) {
10
- super(["JSON.DEL", ...cmd], opts);
10
+ super(["JSON.FORGET", ...cmd], opts);
11
11
  }
12
12
  }
13
13
  exports.JsonForgetCommand = JsonForgetCommand;
@@ -136,6 +136,7 @@ __exportStar(require("./touch.js"), exports);
136
136
  __exportStar(require("./ttl.js"), exports);
137
137
  __exportStar(require("./type.js"), exports);
138
138
  __exportStar(require("./unlink.js"), exports);
139
+ __exportStar(require("./xadd.js"), exports);
139
140
  __exportStar(require("./zadd.js"), exports);
140
141
  __exportStar(require("./zcard.js"), exports);
141
142
  __exportStar(require("./zcount.js"), exports);
@@ -31,7 +31,7 @@ class SetCommand extends command_js_1.Command {
31
31
  command.push("pxat", opts.pxat);
32
32
  }
33
33
  else if ("keepTtl" in opts && opts.keepTtl) {
34
- command.push("keepTtl", opts.keepTtl);
34
+ command.push("keepTtl");
35
35
  }
36
36
  }
37
37
  super(command, cmdOpts);
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.XAddCommand = void 0;
4
+ const command_js_1 = require("./command.js");
5
+ /**
6
+ * @see https://redis.io/commands/xadd
7
+ */
8
+ class XAddCommand extends command_js_1.Command {
9
+ constructor([key, id, entries, opts], commandOptions) {
10
+ const command = ["XADD", key];
11
+ if (opts) {
12
+ if (opts.nomkStream) {
13
+ command.push("NOMKSTREAM");
14
+ }
15
+ if (opts.trim) {
16
+ command.push(opts.trim.type, opts.trim.comparison, opts.trim.threshold);
17
+ if (typeof opts.trim.limit !== "undefined") {
18
+ command.push("LIMIT", opts.trim.limit);
19
+ }
20
+ }
21
+ }
22
+ command.push(id);
23
+ // entries
24
+ Object.entries(entries).forEach(([k, v]) => {
25
+ command.push(k, v);
26
+ });
27
+ super(command, commandOptions);
28
+ }
29
+ }
30
+ exports.XAddCommand = XAddCommand;
@@ -31,7 +31,8 @@ class HttpClient {
31
31
  this.options = {
32
32
  backend: config.options?.backend,
33
33
  agent: config.agent,
34
- responseEncoding: config.responseEncoding ?? "base64", // default to base64
34
+ responseEncoding: config.responseEncoding ?? "base64",
35
+ cache: config.cache,
35
36
  };
36
37
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
37
38
  this.headers = {
@@ -74,6 +75,7 @@ class HttpClient {
74
75
  }
75
76
  async request(req) {
76
77
  const requestOptions = {
78
+ cache: this.options.cache,
77
79
  method: "POST",
78
80
  headers: this.headers,
79
81
  body: JSON.stringify(req.body),
@@ -101,10 +103,17 @@ class HttpClient {
101
103
  }
102
104
  const body = (await res.json());
103
105
  if (!res.ok) {
104
- throw new error_js_1.UpstashError(body.error);
106
+ throw new error_js_1.UpstashError(`${body.error}, command was: ${JSON.stringify(req.body)}`);
105
107
  }
106
108
  if (this.options?.responseEncoding === "base64") {
107
- return Array.isArray(body) ? body.map(decode) : decode(body);
109
+ if (Array.isArray(body)) {
110
+ return body.map(({ result, error }) => ({
111
+ result: decode(result),
112
+ error,
113
+ }));
114
+ }
115
+ const result = decode(body.result);
116
+ return { result, error: body.error };
108
117
  }
109
118
  return body;
110
119
  }
@@ -136,19 +145,19 @@ function base64decode(b64) {
136
145
  }
137
146
  function decode(raw) {
138
147
  let result = undefined;
139
- switch (typeof raw.result) {
148
+ switch (typeof raw) {
140
149
  case "undefined":
141
150
  return raw;
142
151
  case "number": {
143
- result = raw.result;
152
+ result = raw;
144
153
  break;
145
154
  }
146
155
  case "object": {
147
- if (Array.isArray(raw.result)) {
148
- result = raw.result.map((v) => typeof v === "string"
156
+ if (Array.isArray(raw)) {
157
+ result = raw.map((v) => typeof v === "string"
149
158
  ? base64decode(v)
150
159
  : Array.isArray(v)
151
- ? v.map(base64decode)
160
+ ? v.map(decode)
152
161
  : v);
153
162
  }
154
163
  else {
@@ -159,11 +168,11 @@ function decode(raw) {
159
168
  break;
160
169
  }
161
170
  case "string": {
162
- result = raw.result === "OK" ? "OK" : base64decode(raw.result);
171
+ result = raw === "OK" ? "OK" : base64decode(raw);
163
172
  break;
164
173
  }
165
174
  default:
166
175
  break;
167
176
  }
168
- return { result, error: raw.error };
177
+ return result;
169
178
  }
@@ -34,7 +34,7 @@ const zdiffstore_js_1 = require("./commands/zdiffstore.js");
34
34
  * const res = await p.set("key","value").get("key").exec()
35
35
  * ```
36
36
  *
37
- * It's not possible to infer correct types with a dynamic pipeline, so you can
37
+ * Return types are inferred if all commands are chained, but you can still
38
38
  * override the response type manually:
39
39
  * ```ts
40
40
  * redis.pipeline()
@@ -75,9 +75,11 @@ class Pipeline {
75
75
  *
76
76
  * Returns an array with the results of all pipelined commands.
77
77
  *
78
- * You can define a return type manually to make working in typescript easier
78
+ * If all commands are statically chained from start to finish, types are inferred. You can still define a return type manually if necessary though:
79
79
  * ```ts
80
- * redis.pipeline().get("key").exec<[{ greeting: string }]>()
80
+ * const p = redis.pipeline()
81
+ * p.get("key")
82
+ * const result = p.exec<[{ greeting: string }]>()
81
83
  * ```
82
84
  */
83
85
  Object.defineProperty(this, "exec", {
@@ -93,6 +95,7 @@ class Pipeline {
93
95
  path,
94
96
  body: Object.values(this.commands).map((c) => c.command),
95
97
  }));
98
+ console.log("after req", { res });
96
99
  return res.map(({ error, result }, i) => {
97
100
  if (error) {
98
101
  throw new error_js_1.UpstashError(`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`);
@@ -1187,23 +1190,22 @@ class Pipeline {
1187
1190
  value: (...args) => this.chain(new mod_js_1.ZUnionStoreCommand(args, this.commandOptions))
1188
1191
  });
1189
1192
  this.client = opts.client;
1190
- this.commands = [];
1193
+ this.commands = []; // the TCommands generic in the class definition is only used for carrying through chained command types and should never be explicitly set when instantiating the class
1191
1194
  this.commandOptions = opts.commandOptions;
1192
1195
  this.multiExec = opts.multiExec ?? false;
1193
1196
  }
1194
1197
  /**
1195
- * Pushes a command into the pipelien and returns a chainable instance of the
1198
+ * Pushes a command into the pipeline and returns a chainable instance of the
1196
1199
  * pipeline
1197
1200
  */
1198
1201
  chain(command) {
1199
1202
  this.commands.push(command);
1200
- return this;
1203
+ return this; // TS thinks we're returning Pipeline<[]> here, because we're not creating a new instance of the class, hence the cast
1201
1204
  }
1202
1205
  /**
1203
1206
  * @see https://redis.io/commands/?group=json
1204
1207
  */
1205
1208
  get json() {
1206
- // For some reason we needed to define the types manually, otherwise Deno wouldn't build it
1207
1209
  return {
1208
1210
  /**
1209
1211
  * @see https://redis.io/commands/json.arrappend
@@ -1008,6 +1008,10 @@ class Redis {
1008
1008
  writable: true,
1009
1009
  value: (...args) => new mod_js_1.UnlinkCommand(args, this.opts).exec(this.client)
1010
1010
  });
1011
+ // /**
1012
+ // * @see https://redis.io/commands/xadd
1013
+ // */
1014
+ // xadd =
1011
1015
  /**
1012
1016
  * @see https://redis.io/commands/zadd
1013
1017
  */
@@ -61,13 +61,16 @@ class Redis extends core.Redis {
61
61
  headers: { authorization: `Bearer ${configOrRequester.token}` },
62
62
  agent: configOrRequester.agent,
63
63
  responseEncoding: configOrRequester.responseEncoding,
64
+ cache: configOrRequester.cache || "no-store",
64
65
  });
65
66
  super(client, {
66
67
  automaticDeserialization: configOrRequester.automaticDeserialization,
67
68
  enableTelemetry: !process.env.UPSTASH_DISABLE_TELEMETRY,
68
69
  });
69
70
  this.addTelemetry({
70
- runtime: `node@${process.version}`,
71
+ runtime: typeof EdgeRuntime === "string"
72
+ ? "edge-light"
73
+ : `node@${process.version}`,
71
74
  platform: process.env.VERCEL
72
75
  ? "vercel"
73
76
  : process.env.AWS_REGION
package/script/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = "v0.0.0-ci.9190cbfb-20230208";
4
+ exports.VERSION = "v0.0.0-ci.97cb5577-20231010";
@@ -3,5 +3,5 @@ import { Command, CommandOptions } from "./command.js";
3
3
  * @see https://redis.io/commands/hdel
4
4
  */
5
5
  export declare class HDelCommand extends Command<"0" | "1", 0 | 1> {
6
- constructor(cmd: [key: string, field: string], opts?: CommandOptions<"0" | "1", 0 | 1>);
6
+ constructor(cmd: [key: string, ...fields: string[]], opts?: CommandOptions<"0" | "1", 0 | 1>);
7
7
  }
@@ -120,6 +120,7 @@ export * from "./touch.js";
120
120
  export * from "./ttl.js";
121
121
  export * from "./type.js";
122
122
  export * from "./unlink.js";
123
+ export * from "./xadd.js";
123
124
  export * from "./zadd.js";
124
125
  export * from "./zcard.js";
125
126
  export * from "./zcount.js";
@@ -1,7 +1,7 @@
1
1
  import { Command, CommandOptions } from "./command.js";
2
2
  export type SetCommandOptions = {
3
- get: boolean;
4
- } | ({
3
+ get?: boolean;
4
+ } & ({
5
5
  ex: number;
6
6
  px?: never;
7
7
  exat?: never;
@@ -0,0 +1,31 @@
1
+ import { Command, CommandOptions } from "./command.js";
2
+ type XAddCommandOptions = {
3
+ nomkStream?: boolean;
4
+ trim?: ({
5
+ type: "MAXLEN" | "maxlen";
6
+ threshold: number;
7
+ } | {
8
+ type: "MINID" | "minid";
9
+ threshold: string;
10
+ }) & ({
11
+ comparison: "~";
12
+ limit?: number;
13
+ } | {
14
+ comparison: "=";
15
+ limit?: never;
16
+ });
17
+ };
18
+ /**
19
+ * @see https://redis.io/commands/xadd
20
+ */
21
+ export declare class XAddCommand extends Command<string, string> {
22
+ constructor([key, id, entries, opts]: [
23
+ key: string,
24
+ id: "*" | string,
25
+ entries: {
26
+ [field: string]: unknown;
27
+ },
28
+ opts?: XAddCommandOptions
29
+ ], commandOptions?: CommandOptions<string, string>);
30
+ }
31
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { Telemetry } from "./types.js";
2
+ type CacheSetting = "default" | "force-cache" | "no-cache" | "no-store" | "only-if-cached" | "reload";
2
3
  export type UpstashRequest = {
3
4
  path?: string[];
4
5
  /**
@@ -61,6 +62,11 @@ export type RequesterConfig = {
61
62
  * @default "base64"
62
63
  */
63
64
  responseEncoding?: false | "base64";
65
+ /**
66
+ * Configure the cache behaviour
67
+ * @default "no-store"
68
+ */
69
+ cache?: CacheSetting;
64
70
  };
65
71
  export type HttpClientConfig = {
66
72
  headers?: Record<string, string>;
@@ -76,6 +82,7 @@ export declare class HttpClient implements Requester {
76
82
  backend?: string;
77
83
  agent: any;
78
84
  responseEncoding?: false | "base64";
85
+ cache?: CacheSetting;
79
86
  };
80
87
  readonly retry: {
81
88
  attempts: number;
@@ -85,3 +92,4 @@ export declare class HttpClient implements Requester {
85
92
  mergeTelemetry(telemetry: Telemetry): void;
86
93
  request<TResult>(req: UpstashRequest): Promise<UpstashResponse<TResult>>;
87
94
  }
95
+ export {};