@windrun-huaiin/backend-core 13.0.0 → 14.1.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/dist/_virtual/index.js +7 -3
- package/dist/_virtual/index.mjs +5 -3
- package/dist/_virtual/index2.js +2 -6
- package/dist/_virtual/index2.mjs +2 -6
- package/dist/index.js +3 -1
- package/dist/index.mjs +2 -2
- package/dist/lib/index.js +3 -1
- package/dist/lib/index.mjs +2 -2
- package/dist/lib/stripe-config.d.ts +1 -1
- package/dist/lib/stripe-config.d.ts.map +1 -1
- package/dist/lib/stripe-config.js +25 -16
- package/dist/lib/stripe-config.mjs +25 -16
- package/dist/lib/upstash/qstash.d.ts.map +1 -1
- package/dist/lib/upstash/qstash.js +66 -62
- package/dist/lib/upstash/qstash.mjs +67 -63
- package/dist/lib/upstash/redis-counter.d.ts.map +1 -1
- package/dist/lib/upstash/redis-counter.js +9 -24
- package/dist/lib/upstash/redis-counter.mjs +10 -25
- package/dist/lib/upstash/redis-favorite.d.ts.map +1 -1
- package/dist/lib/upstash/redis-favorite.js +22 -36
- package/dist/lib/upstash/redis-favorite.mjs +23 -37
- package/dist/lib/upstash/redis-like.d.ts.map +1 -1
- package/dist/lib/upstash/redis-like.js +22 -36
- package/dist/lib/upstash/redis-like.mjs +23 -37
- package/dist/lib/upstash/redis-lock.d.ts.map +1 -1
- package/dist/lib/upstash/redis-lock.js +22 -38
- package/dist/lib/upstash/redis-lock.mjs +23 -39
- package/dist/lib/upstash/redis-structures.d.ts.map +1 -1
- package/dist/lib/upstash/redis-structures.js +77 -113
- package/dist/lib/upstash/redis-structures.mjs +78 -114
- package/dist/lib/upstash-config.d.ts +9 -1
- package/dist/lib/upstash-config.d.ts.map +1 -1
- package/dist/lib/upstash-config.js +221 -27
- package/dist/lib/upstash-config.mjs +220 -28
- package/dist/node_modules/.pnpm/{@upstash_qstash@2.8.4/node_modules/@upstash/qstash/chunk-RQPZUJXG.js → @upstash_qstash@2.10.1/node_modules/@upstash/qstash/chunk-35B33QW3.js} +897 -468
- package/dist/node_modules/.pnpm/{@upstash_qstash@2.8.4/node_modules/@upstash/qstash/chunk-RQPZUJXG.mjs → @upstash_qstash@2.10.1/node_modules/@upstash/qstash/chunk-35B33QW3.mjs} +895 -468
- package/dist/node_modules/.pnpm/{@upstash_redis@1.36.1/node_modules/@upstash/redis/chunk-LLI2WIYN.js → @upstash_redis@1.37.0/node_modules/@upstash/redis/chunk-IH7W44G6.js} +657 -40
- package/dist/node_modules/.pnpm/{@upstash_redis@1.36.1/node_modules/@upstash/redis/chunk-LLI2WIYN.mjs → @upstash_redis@1.37.0/node_modules/@upstash/redis/chunk-IH7W44G6.mjs} +657 -41
- package/dist/node_modules/.pnpm/{@upstash_redis@1.36.1 → @upstash_redis@1.37.0}/node_modules/@upstash/redis/nodejs.js +6 -5
- package/dist/node_modules/.pnpm/{@upstash_redis@1.36.1 → @upstash_redis@1.37.0}/node_modules/@upstash/redis/nodejs.mjs +2 -2
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/index.js +1 -1
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/index.mjs +1 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jws/flattened/verify.js +6 -6
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jwt/verify.js +1 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/key/import.js +2 -2
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/epoch.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_disjoint.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_jwk.js +1 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_object.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/jwt_claims_set.js +7 -5
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/secs.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_algorithms.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_crit.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/check_key_length.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/dsa_digest.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_named_curve.js +4 -2
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_sign_verify_key.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/hmac_digest.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_like.js +1 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_object.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/jwk_to_key.js +3 -1
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/node_key.js +6 -4
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/sign.js +6 -4
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/verify.js +7 -5
- package/dist/services/stripe/webhook-handler.js +4 -2
- package/dist/services/stripe/webhook-handler.mjs +3 -1
- package/package.json +5 -5
- package/src/lib/stripe-config.ts +27 -15
- package/src/lib/upstash/qstash.ts +64 -62
- package/src/lib/upstash/redis-counter.ts +10 -26
- package/src/lib/upstash/redis-favorite.ts +23 -42
- package/src/lib/upstash/redis-like.ts +23 -42
- package/src/lib/upstash/redis-lock.ts +23 -49
- package/src/lib/upstash/redis-structures.ts +82 -131
- package/src/lib/upstash-config.ts +231 -24
- package/src/services/stripe/webhook-handler.ts +3 -1
- package/dist/_virtual/index3.js +0 -5
- package/dist/_virtual/index3.mjs +0 -3
- package/dist/node_modules/.pnpm/@upstash_lock@0.2.1_typescript@5.9.3/node_modules/@upstash/lock/dist/index.js +0 -191
- package/dist/node_modules/.pnpm/@upstash_lock@0.2.1_typescript@5.9.3/node_modules/@upstash/lock/dist/index.mjs +0 -189
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +0 -54
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +0 -51
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +0 -44
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +0 -35
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +0 -31
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +0 -18
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +0 -587
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +0 -527
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +0 -447
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +0 -399
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +0 -245
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +0 -232
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +0 -68
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +0 -62
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +0 -39
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +0 -37
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +0 -80
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +0 -75
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +0 -101
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +0 -86
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +0 -102
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +0 -76
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +0 -56
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +0 -52
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +0 -1205
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +0 -1157
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +0 -407
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +0 -374
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +0 -9
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +0 -7
|
@@ -1,9 +1,526 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('../../../../../../_virtual/
|
|
3
|
+
var index = require('../../../../../../_virtual/index.js');
|
|
4
4
|
require('../../../../neverthrow@7.2.0/node_modules/neverthrow/dist/index.es.js');
|
|
5
5
|
var verify = require('../../../../jose@5.10.0/node_modules/jose/dist/node/esm/jwt/verify.js');
|
|
6
6
|
|
|
7
|
+
// src/receiver.ts
|
|
8
|
+
|
|
9
|
+
// src/client/api/base.ts
|
|
10
|
+
var BaseProvider = class {
|
|
11
|
+
baseUrl;
|
|
12
|
+
token;
|
|
13
|
+
owner;
|
|
14
|
+
constructor(baseUrl, token, owner) {
|
|
15
|
+
this.baseUrl = baseUrl;
|
|
16
|
+
this.token = token;
|
|
17
|
+
this.owner = owner;
|
|
18
|
+
}
|
|
19
|
+
getUrl() {
|
|
20
|
+
return `${this.baseUrl}/${this.getRoute().join("/")}`;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/client/api/llm.ts
|
|
25
|
+
var LLMProvider = class extends BaseProvider {
|
|
26
|
+
apiKind = "llm";
|
|
27
|
+
organization;
|
|
28
|
+
method = "POST";
|
|
29
|
+
constructor(baseUrl, token, owner, organization) {
|
|
30
|
+
super(baseUrl, token, owner);
|
|
31
|
+
this.organization = organization;
|
|
32
|
+
}
|
|
33
|
+
getRoute() {
|
|
34
|
+
return this.owner === "anthropic" ? ["v1", "messages"] : ["v1", "chat", "completions"];
|
|
35
|
+
}
|
|
36
|
+
getHeaders(options) {
|
|
37
|
+
if (this.owner === "upstash" && !options.analytics) {
|
|
38
|
+
return { "content-type": "application/json" };
|
|
39
|
+
}
|
|
40
|
+
const header = this.owner === "anthropic" ? "x-api-key" : "authorization";
|
|
41
|
+
const headerValue = this.owner === "anthropic" ? this.token : `Bearer ${this.token}`;
|
|
42
|
+
const headers = {
|
|
43
|
+
[header]: headerValue,
|
|
44
|
+
"content-type": "application/json"
|
|
45
|
+
};
|
|
46
|
+
if (this.owner === "openai" && this.organization) {
|
|
47
|
+
headers["OpenAI-Organization"] = this.organization;
|
|
48
|
+
}
|
|
49
|
+
if (this.owner === "anthropic") {
|
|
50
|
+
headers["anthropic-version"] = "2023-06-01";
|
|
51
|
+
}
|
|
52
|
+
return headers;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Checks if callback exists and adds analytics in place if it's set.
|
|
56
|
+
*
|
|
57
|
+
* @param request
|
|
58
|
+
* @param options
|
|
59
|
+
*/
|
|
60
|
+
onFinish(providerInfo, options) {
|
|
61
|
+
if (options.analytics) {
|
|
62
|
+
return updateWithAnalytics(providerInfo, options.analytics);
|
|
63
|
+
}
|
|
64
|
+
return providerInfo;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var upstash = () => {
|
|
68
|
+
return new LLMProvider("https://qstash.upstash.io/llm", "", "upstash");
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/client/api/utils.ts
|
|
72
|
+
var getProviderInfo = (api, upstashToken) => {
|
|
73
|
+
const { name, provider, ...parameters } = api;
|
|
74
|
+
const finalProvider = provider ?? upstash();
|
|
75
|
+
if (finalProvider.owner === "upstash" && !finalProvider.token) {
|
|
76
|
+
finalProvider.token = upstashToken;
|
|
77
|
+
}
|
|
78
|
+
if (!finalProvider.baseUrl)
|
|
79
|
+
throw new TypeError("baseUrl cannot be empty or undefined!");
|
|
80
|
+
if (!finalProvider.token)
|
|
81
|
+
throw new TypeError("token cannot be empty or undefined!");
|
|
82
|
+
if (finalProvider.apiKind !== name) {
|
|
83
|
+
throw new TypeError(
|
|
84
|
+
`Unexpected api name. Expected '${finalProvider.apiKind}', received ${name}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
const providerInfo = {
|
|
88
|
+
url: finalProvider.getUrl(),
|
|
89
|
+
baseUrl: finalProvider.baseUrl,
|
|
90
|
+
route: finalProvider.getRoute(),
|
|
91
|
+
appendHeaders: finalProvider.getHeaders(parameters),
|
|
92
|
+
owner: finalProvider.owner,
|
|
93
|
+
method: finalProvider.method
|
|
94
|
+
};
|
|
95
|
+
return finalProvider.onFinish(providerInfo, parameters);
|
|
96
|
+
};
|
|
97
|
+
var safeJoinHeaders = (headers, record) => {
|
|
98
|
+
const joinedHeaders = new Headers(record);
|
|
99
|
+
for (const [header, value] of headers.entries()) {
|
|
100
|
+
joinedHeaders.set(header, value);
|
|
101
|
+
}
|
|
102
|
+
return joinedHeaders;
|
|
103
|
+
};
|
|
104
|
+
var processApi = (request, headers, upstashToken) => {
|
|
105
|
+
if (!request.api) {
|
|
106
|
+
request.headers = headers;
|
|
107
|
+
return request;
|
|
108
|
+
}
|
|
109
|
+
const { url, appendHeaders, owner, method } = getProviderInfo(request.api, upstashToken);
|
|
110
|
+
if (request.api.name === "llm") {
|
|
111
|
+
const callback = request.callback;
|
|
112
|
+
if (!callback) {
|
|
113
|
+
throw new TypeError("Callback cannot be undefined when using LLM api.");
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
...request,
|
|
117
|
+
method: request.method ?? method,
|
|
118
|
+
headers: safeJoinHeaders(headers, appendHeaders),
|
|
119
|
+
...owner === "upstash" && !request.api.analytics ? { api: { name: "llm" }, url: void 0, callback } : { url, api: void 0 }
|
|
120
|
+
};
|
|
121
|
+
} else {
|
|
122
|
+
return {
|
|
123
|
+
...request,
|
|
124
|
+
method: request.method ?? method,
|
|
125
|
+
headers: safeJoinHeaders(headers, appendHeaders),
|
|
126
|
+
url,
|
|
127
|
+
api: void 0
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
function updateWithAnalytics(providerInfo, analytics) {
|
|
132
|
+
switch (analytics.name) {
|
|
133
|
+
case "helicone": {
|
|
134
|
+
providerInfo.appendHeaders["Helicone-Auth"] = `Bearer ${analytics.token}`;
|
|
135
|
+
if (providerInfo.owner === "upstash") {
|
|
136
|
+
updateProviderInfo(providerInfo, "https://qstash.helicone.ai", [
|
|
137
|
+
"llm",
|
|
138
|
+
...providerInfo.route
|
|
139
|
+
]);
|
|
140
|
+
} else {
|
|
141
|
+
providerInfo.appendHeaders["Helicone-Target-Url"] = providerInfo.baseUrl;
|
|
142
|
+
updateProviderInfo(providerInfo, "https://gateway.helicone.ai", providerInfo.route);
|
|
143
|
+
}
|
|
144
|
+
return providerInfo;
|
|
145
|
+
}
|
|
146
|
+
default: {
|
|
147
|
+
throw new Error("Unknown analytics provider");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function updateProviderInfo(providerInfo, baseUrl, route) {
|
|
152
|
+
providerInfo.baseUrl = baseUrl;
|
|
153
|
+
providerInfo.route = route;
|
|
154
|
+
providerInfo.url = `${baseUrl}/${route.join("/")}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/client/error.ts
|
|
158
|
+
var RATELIMIT_STATUS = 429;
|
|
159
|
+
var QstashError = class extends Error {
|
|
160
|
+
status;
|
|
161
|
+
constructor(message, status) {
|
|
162
|
+
super(message);
|
|
163
|
+
this.name = "QstashError";
|
|
164
|
+
this.status = status;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var QstashRatelimitError = class extends QstashError {
|
|
168
|
+
limit;
|
|
169
|
+
remaining;
|
|
170
|
+
reset;
|
|
171
|
+
constructor(args) {
|
|
172
|
+
super(`Exceeded burst rate limit. ${JSON.stringify(args)}`, RATELIMIT_STATUS);
|
|
173
|
+
this.name = "QstashRatelimitError";
|
|
174
|
+
this.limit = args.limit;
|
|
175
|
+
this.remaining = args.remaining;
|
|
176
|
+
this.reset = args.reset;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
var QstashChatRatelimitError = class extends QstashError {
|
|
180
|
+
limitRequests;
|
|
181
|
+
limitTokens;
|
|
182
|
+
remainingRequests;
|
|
183
|
+
remainingTokens;
|
|
184
|
+
resetRequests;
|
|
185
|
+
resetTokens;
|
|
186
|
+
constructor(args) {
|
|
187
|
+
super(`Exceeded chat rate limit. ${JSON.stringify(args)}`, RATELIMIT_STATUS);
|
|
188
|
+
this.name = "QstashChatRatelimitError";
|
|
189
|
+
this.limitRequests = args["limit-requests"];
|
|
190
|
+
this.limitTokens = args["limit-tokens"];
|
|
191
|
+
this.remainingRequests = args["remaining-requests"];
|
|
192
|
+
this.remainingTokens = args["remaining-tokens"];
|
|
193
|
+
this.resetRequests = args["reset-requests"];
|
|
194
|
+
this.resetTokens = args["reset-tokens"];
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
var QstashDailyRatelimitError = class extends QstashError {
|
|
198
|
+
limit;
|
|
199
|
+
remaining;
|
|
200
|
+
reset;
|
|
201
|
+
constructor(args) {
|
|
202
|
+
super(`Exceeded daily rate limit. ${JSON.stringify(args)}`, RATELIMIT_STATUS);
|
|
203
|
+
this.name = "QstashDailyRatelimitError";
|
|
204
|
+
this.limit = args.limit;
|
|
205
|
+
this.remaining = args.remaining;
|
|
206
|
+
this.reset = args.reset;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
var QstashEmptyArrayError = class extends QstashError {
|
|
210
|
+
constructor(parameterName) {
|
|
211
|
+
super(
|
|
212
|
+
`Empty array provided for query parameter "${parameterName}". This would result in no filter being applied, which could affect all resources.`
|
|
213
|
+
);
|
|
214
|
+
this.name = "QstashEmptyArrayError";
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// src/client/utils.ts
|
|
219
|
+
var DEFAULT_BULK_COUNT = 100;
|
|
220
|
+
var isIgnoredHeader = (header) => {
|
|
221
|
+
const lowerCaseHeader = header.toLowerCase();
|
|
222
|
+
return lowerCaseHeader.startsWith("content-type") || lowerCaseHeader.startsWith("upstash-");
|
|
223
|
+
};
|
|
224
|
+
function prefixHeaders(headers) {
|
|
225
|
+
const keysToBePrefixed = [...headers.keys()].filter((key) => !isIgnoredHeader(key));
|
|
226
|
+
for (const key of keysToBePrefixed) {
|
|
227
|
+
const value = headers.get(key);
|
|
228
|
+
if (value !== null) {
|
|
229
|
+
headers.set(`Upstash-Forward-${key}`, value);
|
|
230
|
+
}
|
|
231
|
+
headers.delete(key);
|
|
232
|
+
}
|
|
233
|
+
return headers;
|
|
234
|
+
}
|
|
235
|
+
function wrapWithGlobalHeaders(headers, globalHeaders, telemetryHeaders) {
|
|
236
|
+
if (!globalHeaders) {
|
|
237
|
+
return headers;
|
|
238
|
+
}
|
|
239
|
+
const finalHeaders = new Headers(globalHeaders);
|
|
240
|
+
headers.forEach((value, key) => {
|
|
241
|
+
finalHeaders.set(key, value);
|
|
242
|
+
});
|
|
243
|
+
telemetryHeaders?.forEach((value, key) => {
|
|
244
|
+
if (!value)
|
|
245
|
+
return;
|
|
246
|
+
finalHeaders.append(key, value);
|
|
247
|
+
});
|
|
248
|
+
return finalHeaders;
|
|
249
|
+
}
|
|
250
|
+
function processHeaders(request) {
|
|
251
|
+
const headers = prefixHeaders(new Headers(request.headers));
|
|
252
|
+
headers.set("Upstash-Method", request.method ?? "POST");
|
|
253
|
+
if (request.delay !== void 0) {
|
|
254
|
+
if (typeof request.delay === "string") {
|
|
255
|
+
headers.set("Upstash-Delay", request.delay);
|
|
256
|
+
} else {
|
|
257
|
+
headers.set("Upstash-Delay", `${request.delay.toFixed(0)}s`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (request.notBefore !== void 0) {
|
|
261
|
+
headers.set("Upstash-Not-Before", request.notBefore.toFixed(0));
|
|
262
|
+
}
|
|
263
|
+
if (request.deduplicationId !== void 0) {
|
|
264
|
+
headers.set("Upstash-Deduplication-Id", request.deduplicationId);
|
|
265
|
+
}
|
|
266
|
+
if (request.contentBasedDeduplication) {
|
|
267
|
+
headers.set("Upstash-Content-Based-Deduplication", "true");
|
|
268
|
+
}
|
|
269
|
+
if (request.retries !== void 0) {
|
|
270
|
+
headers.set("Upstash-Retries", request.retries.toFixed(0));
|
|
271
|
+
}
|
|
272
|
+
if (request.retryDelay !== void 0) {
|
|
273
|
+
headers.set("Upstash-Retry-Delay", request.retryDelay);
|
|
274
|
+
}
|
|
275
|
+
if (request.callback !== void 0) {
|
|
276
|
+
headers.set("Upstash-Callback", request.callback);
|
|
277
|
+
}
|
|
278
|
+
if (request.failureCallback !== void 0) {
|
|
279
|
+
headers.set("Upstash-Failure-Callback", request.failureCallback);
|
|
280
|
+
}
|
|
281
|
+
if (request.timeout !== void 0) {
|
|
282
|
+
if (typeof request.timeout === "string") {
|
|
283
|
+
headers.set("Upstash-Timeout", request.timeout);
|
|
284
|
+
} else {
|
|
285
|
+
headers.set("Upstash-Timeout", `${request.timeout}s`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (request.flowControl?.key) {
|
|
289
|
+
const parallelism = request.flowControl.parallelism?.toString();
|
|
290
|
+
const rate = (request.flowControl.rate ?? request.flowControl.ratePerSecond)?.toString();
|
|
291
|
+
const period = typeof request.flowControl.period === "number" ? `${request.flowControl.period}s` : request.flowControl.period;
|
|
292
|
+
const controlValue = [
|
|
293
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
294
|
+
rate ? `rate=${rate}` : void 0,
|
|
295
|
+
period ? `period=${period}` : void 0
|
|
296
|
+
].filter(Boolean);
|
|
297
|
+
if (controlValue.length === 0) {
|
|
298
|
+
throw new QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
299
|
+
}
|
|
300
|
+
headers.set("Upstash-Flow-Control-Key", request.flowControl.key);
|
|
301
|
+
headers.set("Upstash-Flow-Control-Value", controlValue.join(", "));
|
|
302
|
+
}
|
|
303
|
+
if (request.label !== void 0) {
|
|
304
|
+
headers.set("Upstash-Label", request.label);
|
|
305
|
+
}
|
|
306
|
+
if (request.redact !== void 0) {
|
|
307
|
+
const redactParts = [];
|
|
308
|
+
if (request.redact.body) {
|
|
309
|
+
redactParts.push("body");
|
|
310
|
+
}
|
|
311
|
+
if (request.redact.header !== void 0) {
|
|
312
|
+
if (request.redact.header === true) {
|
|
313
|
+
redactParts.push("header");
|
|
314
|
+
} else if (Array.isArray(request.redact.header) && request.redact.header.length > 0) {
|
|
315
|
+
for (const headerName of request.redact.header) {
|
|
316
|
+
redactParts.push(`header[${headerName}]`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (redactParts.length > 0) {
|
|
321
|
+
headers.set("Upstash-Redact-Fields", redactParts.join(","));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return headers;
|
|
325
|
+
}
|
|
326
|
+
function getRequestPath(request) {
|
|
327
|
+
const nonApiPath = request.url ?? request.urlGroup ?? request.topic;
|
|
328
|
+
if (nonApiPath)
|
|
329
|
+
return nonApiPath;
|
|
330
|
+
if (request.api?.name === "llm")
|
|
331
|
+
return `api/llm`;
|
|
332
|
+
if (request.api?.name === "email") {
|
|
333
|
+
const providerInfo = getProviderInfo(request.api, "not-needed");
|
|
334
|
+
return providerInfo.baseUrl;
|
|
335
|
+
}
|
|
336
|
+
throw new QstashError(`Failed to infer request path for ${JSON.stringify(request)}`);
|
|
337
|
+
}
|
|
338
|
+
function buildBulkActionFilterPayload(request) {
|
|
339
|
+
const cursor = "cursor" in request ? request.cursor : void 0;
|
|
340
|
+
if ("all" in request) {
|
|
341
|
+
const count2 = "count" in request ? request.count ?? DEFAULT_BULK_COUNT : DEFAULT_BULK_COUNT;
|
|
342
|
+
return { count: count2, cursor };
|
|
343
|
+
}
|
|
344
|
+
if ("dlqIds" in request) {
|
|
345
|
+
const ids = request.dlqIds;
|
|
346
|
+
if (Array.isArray(ids) && ids.length === 0) {
|
|
347
|
+
throw new QstashError(
|
|
348
|
+
"Empty dlqIds array provided. If you intend to target all DLQ messages, use { all: true } explicitly."
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
return { dlqIds: ids, cursor };
|
|
352
|
+
}
|
|
353
|
+
if ("messageIds" in request && request.messageIds) {
|
|
354
|
+
if (request.messageIds.length === 0) {
|
|
355
|
+
throw new QstashError(
|
|
356
|
+
"Empty messageIds array provided. If you intend to target all messages, use { all: true } explicitly."
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return { messageIds: request.messageIds, cursor };
|
|
360
|
+
}
|
|
361
|
+
const count = "count" in request ? request.count ?? DEFAULT_BULK_COUNT : DEFAULT_BULK_COUNT;
|
|
362
|
+
return {
|
|
363
|
+
...renameUrlGroup(request.filter),
|
|
364
|
+
count,
|
|
365
|
+
cursor
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function renameUrlGroup(filter) {
|
|
369
|
+
const { urlGroup, api, ...rest } = filter;
|
|
370
|
+
return { ...rest, ...urlGroup === void 0 ? {} : { topicName: urlGroup } };
|
|
371
|
+
}
|
|
372
|
+
function normalizeCursor(response) {
|
|
373
|
+
const cursor = response.cursor;
|
|
374
|
+
return { ...response, cursor: cursor || void 0 };
|
|
375
|
+
}
|
|
376
|
+
function getRuntime() {
|
|
377
|
+
if (typeof process === "object" && typeof process.versions == "object" && process.versions.bun)
|
|
378
|
+
return `bun@${process.versions.bun}`;
|
|
379
|
+
if (typeof EdgeRuntime === "string")
|
|
380
|
+
return "edge-light";
|
|
381
|
+
else if (typeof process === "object" && typeof process.version === "string")
|
|
382
|
+
return `node@${process.version}`;
|
|
383
|
+
return "";
|
|
384
|
+
}
|
|
385
|
+
function getSafeEnvironment() {
|
|
386
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/client/multi-region/utils.ts
|
|
390
|
+
var VALID_REGIONS = ["EU_CENTRAL_1", "US_EAST_1"];
|
|
391
|
+
var DEFAULT_QSTASH_URL = "https://qstash.upstash.io";
|
|
392
|
+
var getRegionFromEnvironment = (environment) => {
|
|
393
|
+
const region = environment.QSTASH_REGION;
|
|
394
|
+
return normalizeRegionHeader(region);
|
|
395
|
+
};
|
|
396
|
+
function readEnvironmentVariables(environmentVariables, environment, region) {
|
|
397
|
+
const result = {};
|
|
398
|
+
for (const variable of environmentVariables) {
|
|
399
|
+
const key = region ? `${region}_${variable}` : variable;
|
|
400
|
+
result[variable] = environment[key];
|
|
401
|
+
}
|
|
402
|
+
return result;
|
|
403
|
+
}
|
|
404
|
+
function readClientEnvironmentVariables(environment, region) {
|
|
405
|
+
return readEnvironmentVariables(["QSTASH_URL", "QSTASH_TOKEN"], environment, region);
|
|
406
|
+
}
|
|
407
|
+
function readReceiverEnvironmentVariables(environment, region) {
|
|
408
|
+
return readEnvironmentVariables(
|
|
409
|
+
["QSTASH_CURRENT_SIGNING_KEY", "QSTASH_NEXT_SIGNING_KEY"],
|
|
410
|
+
environment,
|
|
411
|
+
region
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
function normalizeRegionHeader(region) {
|
|
415
|
+
if (!region) {
|
|
416
|
+
return void 0;
|
|
417
|
+
}
|
|
418
|
+
region = region.replaceAll("-", "_").toUpperCase();
|
|
419
|
+
if (VALID_REGIONS.includes(region)) {
|
|
420
|
+
return region;
|
|
421
|
+
}
|
|
422
|
+
console.warn(
|
|
423
|
+
`[Upstash QStash] Invalid UPSTASH_REGION header value: "${region}". Expected one of: ${VALID_REGIONS.join(
|
|
424
|
+
", "
|
|
425
|
+
)}.`
|
|
426
|
+
);
|
|
427
|
+
return void 0;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/client/multi-region/incoming.ts
|
|
431
|
+
var getReceiverSigningKeys = ({
|
|
432
|
+
environment,
|
|
433
|
+
regionFromHeader,
|
|
434
|
+
config
|
|
435
|
+
}) => {
|
|
436
|
+
if (config?.currentSigningKey && config.nextSigningKey) {
|
|
437
|
+
return {
|
|
438
|
+
currentSigningKey: config.currentSigningKey,
|
|
439
|
+
nextSigningKey: config.nextSigningKey
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const regionEnvironment = getRegionFromEnvironment(environment);
|
|
443
|
+
if (regionEnvironment) {
|
|
444
|
+
const regionHeader = normalizeRegionHeader(regionFromHeader);
|
|
445
|
+
if (regionHeader) {
|
|
446
|
+
const regionCreds = readReceiverEnvironmentVariables(environment, regionHeader);
|
|
447
|
+
if (regionCreds.QSTASH_CURRENT_SIGNING_KEY && regionCreds.QSTASH_NEXT_SIGNING_KEY) {
|
|
448
|
+
return {
|
|
449
|
+
currentSigningKey: regionCreds.QSTASH_CURRENT_SIGNING_KEY,
|
|
450
|
+
nextSigningKey: regionCreds.QSTASH_NEXT_SIGNING_KEY,
|
|
451
|
+
region: regionHeader
|
|
452
|
+
};
|
|
453
|
+
} else {
|
|
454
|
+
console.warn(
|
|
455
|
+
`[Upstash QStash] Signing keys not found for region "${regionHeader}". Falling back to default signing keys.`
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
console.warn(
|
|
460
|
+
`[Upstash QStash] Invalid UPSTASH_REGION header value: "${regionFromHeader}". Expected one of: EU-CENTRAL-1, US-EAST-1. Falling back to default signing keys.`
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
const defaultCreds = readReceiverEnvironmentVariables(environment);
|
|
465
|
+
if (defaultCreds.QSTASH_CURRENT_SIGNING_KEY && defaultCreds.QSTASH_NEXT_SIGNING_KEY) {
|
|
466
|
+
return {
|
|
467
|
+
currentSigningKey: defaultCreds.QSTASH_CURRENT_SIGNING_KEY,
|
|
468
|
+
nextSigningKey: defaultCreds.QSTASH_NEXT_SIGNING_KEY
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// src/client/multi-region/outgoing.ts
|
|
474
|
+
var getClientCredentials = (clientCredentialConfig) => {
|
|
475
|
+
const credentials = resolveCredentials(clientCredentialConfig);
|
|
476
|
+
return verifyCredentials(credentials);
|
|
477
|
+
};
|
|
478
|
+
var resolveCredentials = ({
|
|
479
|
+
environment,
|
|
480
|
+
config
|
|
481
|
+
}) => {
|
|
482
|
+
if (config?.baseUrl && config.token) {
|
|
483
|
+
return {
|
|
484
|
+
baseUrl: config.baseUrl,
|
|
485
|
+
token: config.token
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
const region = getRegionFromEnvironment(environment);
|
|
489
|
+
if (region) {
|
|
490
|
+
const regionCreds = readClientEnvironmentVariables(environment, region);
|
|
491
|
+
if (regionCreds.QSTASH_URL && regionCreds.QSTASH_TOKEN) {
|
|
492
|
+
return {
|
|
493
|
+
baseUrl: regionCreds.QSTASH_URL,
|
|
494
|
+
token: regionCreds.QSTASH_TOKEN,
|
|
495
|
+
region
|
|
496
|
+
};
|
|
497
|
+
} else {
|
|
498
|
+
console.warn(
|
|
499
|
+
`[Upstash QStash] QSTASH_REGION is set to "${region}" but credentials are missing. Expected ${region}_QSTASH_URL and ${region}_QSTASH_TOKEN. Falling back to default credentials.`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const defaultCreds = readClientEnvironmentVariables(environment);
|
|
504
|
+
return {
|
|
505
|
+
baseUrl: config?.baseUrl ?? defaultCreds.QSTASH_URL ?? DEFAULT_QSTASH_URL,
|
|
506
|
+
token: config?.token ?? defaultCreds.QSTASH_TOKEN ?? ""
|
|
507
|
+
};
|
|
508
|
+
};
|
|
509
|
+
var verifyCredentials = (credentials) => {
|
|
510
|
+
const token = credentials.token;
|
|
511
|
+
let baseUrl = credentials.baseUrl;
|
|
512
|
+
baseUrl = baseUrl.replace(/\/$/, "");
|
|
513
|
+
if (baseUrl === "https://qstash.upstash.io/v2/publish") {
|
|
514
|
+
baseUrl = DEFAULT_QSTASH_URL;
|
|
515
|
+
}
|
|
516
|
+
if (!token) {
|
|
517
|
+
console.warn(
|
|
518
|
+
"[Upstash QStash] client token is not set. Either pass a token or set QSTASH_TOKEN env variable."
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
return { baseUrl, token };
|
|
522
|
+
};
|
|
523
|
+
|
|
7
524
|
// src/receiver.ts
|
|
8
525
|
var SignatureError = class extends Error {
|
|
9
526
|
constructor(message) {
|
|
@@ -15,8 +532,8 @@ var Receiver = class {
|
|
|
15
532
|
currentSigningKey;
|
|
16
533
|
nextSigningKey;
|
|
17
534
|
constructor(config) {
|
|
18
|
-
this.currentSigningKey = config
|
|
19
|
-
this.nextSigningKey = config
|
|
535
|
+
this.currentSigningKey = config?.currentSigningKey;
|
|
536
|
+
this.nextSigningKey = config?.nextSigningKey;
|
|
20
537
|
}
|
|
21
538
|
/**
|
|
22
539
|
* Verify the signature of a request.
|
|
@@ -28,11 +545,25 @@ var Receiver = class {
|
|
|
28
545
|
* If that fails, the signature is invalid and a `SignatureError` is thrown.
|
|
29
546
|
*/
|
|
30
547
|
async verify(request) {
|
|
548
|
+
const environment = getSafeEnvironment();
|
|
549
|
+
const signingKeys = getReceiverSigningKeys({
|
|
550
|
+
environment,
|
|
551
|
+
regionFromHeader: request.upstashRegion,
|
|
552
|
+
config: {
|
|
553
|
+
currentSigningKey: this.currentSigningKey,
|
|
554
|
+
nextSigningKey: this.nextSigningKey
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
if (!signingKeys) {
|
|
558
|
+
throw new Error(
|
|
559
|
+
"[Upstash QStash] No signing keys available for verification. See the warning above for more details."
|
|
560
|
+
);
|
|
561
|
+
}
|
|
31
562
|
let payload;
|
|
32
563
|
try {
|
|
33
|
-
payload = await this.verifyWithKey(
|
|
564
|
+
payload = await this.verifyWithKey(signingKeys.currentSigningKey, request);
|
|
34
565
|
} catch {
|
|
35
|
-
payload = await this.verifyWithKey(
|
|
566
|
+
payload = await this.verifyWithKey(signingKeys.nextSigningKey, request);
|
|
36
567
|
}
|
|
37
568
|
this.verifyBodyAndUrl(payload, request);
|
|
38
569
|
return true;
|
|
@@ -54,7 +585,7 @@ var Receiver = class {
|
|
|
54
585
|
if (request.url !== void 0 && p.sub !== request.url) {
|
|
55
586
|
throw new SignatureError(`invalid subject: ${p.sub}, want: ${request.url}`);
|
|
56
587
|
}
|
|
57
|
-
const bodyHash = index.SHA256(request.body).toString(index.enc.Base64url);
|
|
588
|
+
const bodyHash = index.default.SHA256(request.body).toString(index.default.enc.Base64url);
|
|
58
589
|
const padding = new RegExp(/=+$/);
|
|
59
590
|
if (p.body.replace(padding, "") !== bodyHash.replace(padding, "")) {
|
|
60
591
|
throw new SignatureError(`body hash does not match, want: ${p.body}, got: ${bodyHash}`);
|
|
@@ -70,20 +601,21 @@ var DLQ = class {
|
|
|
70
601
|
}
|
|
71
602
|
/**
|
|
72
603
|
* List messages in the dlq
|
|
604
|
+
*
|
|
605
|
+
* Can be called with:
|
|
606
|
+
* - Filters: `listMessages({ filter: { url: "https://example.com" } })`
|
|
607
|
+
* - DLQ IDs: `listMessages({ dlqIds: ["id1", "id2"] })`
|
|
608
|
+
* - No filter (list all): `listMessages()`
|
|
73
609
|
*/
|
|
74
|
-
async listMessages(options) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
610
|
+
async listMessages(options = {}) {
|
|
611
|
+
const query = {
|
|
612
|
+
count: options.count,
|
|
613
|
+
..."dlqIds" in options ? { dlqIds: options.dlqIds } : { ...renameUrlGroup(options.filter ?? {}), cursor: options.cursor }
|
|
78
614
|
};
|
|
79
615
|
const messagesPayload = await this.http.request({
|
|
80
616
|
method: "GET",
|
|
81
617
|
path: ["v2", "dlq"],
|
|
82
|
-
query
|
|
83
|
-
cursor: options?.cursor,
|
|
84
|
-
count: options?.count,
|
|
85
|
-
...filterPayload
|
|
86
|
-
}
|
|
618
|
+
query
|
|
87
619
|
});
|
|
88
620
|
return {
|
|
89
621
|
messages: messagesPayload.messages.map((message) => {
|
|
@@ -97,79 +629,187 @@ var DLQ = class {
|
|
|
97
629
|
};
|
|
98
630
|
}
|
|
99
631
|
/**
|
|
100
|
-
* Remove
|
|
632
|
+
* Remove messages from the dlq.
|
|
633
|
+
*
|
|
634
|
+
* Can be called with:
|
|
635
|
+
* - A single dlqId: `delete("id")`
|
|
636
|
+
* - An array of dlqIds: `delete(["id1", "id2"])`
|
|
637
|
+
* - An object with dlqIds: `delete({ dlqIds: ["id1", "id2"] })`
|
|
638
|
+
* - A filter object: `delete({ filter: { url: "https://example.com", label: "label" } })`
|
|
639
|
+
* - All messages: `delete({ all: true })`
|
|
640
|
+
*
|
|
641
|
+
* Pass `count` to limit the number of messages processed per call (defaults to 100).
|
|
642
|
+
* Call in a loop until cursor is undefined:
|
|
643
|
+
*
|
|
644
|
+
* ```ts
|
|
645
|
+
* let cursor: string | undefined;
|
|
646
|
+
* do {
|
|
647
|
+
* const result = await dlq.delete({ all: true, count: 100, cursor });
|
|
648
|
+
* cursor = result.cursor;
|
|
649
|
+
* } while (cursor);
|
|
650
|
+
* ```
|
|
101
651
|
*/
|
|
102
|
-
async delete(
|
|
652
|
+
async delete(request) {
|
|
653
|
+
if (typeof request === "string") {
|
|
654
|
+
await this.http.request({
|
|
655
|
+
method: "DELETE",
|
|
656
|
+
path: ["v2", "dlq", request],
|
|
657
|
+
parseResponseAsJson: false
|
|
658
|
+
});
|
|
659
|
+
return { deleted: 1 };
|
|
660
|
+
}
|
|
661
|
+
if (Array.isArray(request) && request.length === 0)
|
|
662
|
+
return { deleted: 0 };
|
|
663
|
+
const filters = Array.isArray(request) ? { dlqIds: request } : request;
|
|
103
664
|
return await this.http.request({
|
|
104
665
|
method: "DELETE",
|
|
105
|
-
path: ["v2", "dlq"
|
|
106
|
-
|
|
107
|
-
// there is no response
|
|
666
|
+
path: ["v2", "dlq"],
|
|
667
|
+
query: buildBulkActionFilterPayload(filters)
|
|
108
668
|
});
|
|
109
669
|
}
|
|
110
670
|
/**
|
|
111
671
|
* Remove multiple messages from the dlq using their `dlqId`s
|
|
672
|
+
*
|
|
673
|
+
* @deprecated Use `delete` instead
|
|
112
674
|
*/
|
|
113
675
|
async deleteMany(request) {
|
|
114
|
-
return await this.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
676
|
+
return await this.delete(request);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Retry messages from the dlq.
|
|
680
|
+
*
|
|
681
|
+
* Can be called with:
|
|
682
|
+
* - A single dlqId: `retry("id")`
|
|
683
|
+
* - An array of dlqIds: `retry(["id1", "id2"])`
|
|
684
|
+
* - An object with dlqIds: `retry({ dlqIds: ["id1", "id2"] })`
|
|
685
|
+
* - A filter object: `retry({ filter: { url: "https://example.com", label: "label" } })`
|
|
686
|
+
* - All messages: `retry({ all: true })`
|
|
687
|
+
*
|
|
688
|
+
* Pass `count` to limit the number of messages processed per call (defaults to 100).
|
|
689
|
+
* Call in a loop until cursor is undefined:
|
|
690
|
+
*
|
|
691
|
+
* ```ts
|
|
692
|
+
* let cursor: string | undefined;
|
|
693
|
+
* do {
|
|
694
|
+
* const result = await dlq.retry({ all: true, count: 100, cursor });
|
|
695
|
+
* cursor = result.cursor;
|
|
696
|
+
* } while (cursor);
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
async retry(request) {
|
|
700
|
+
if (typeof request === "string")
|
|
701
|
+
request = [request];
|
|
702
|
+
if (Array.isArray(request) && request.length === 0)
|
|
703
|
+
return { responses: [] };
|
|
704
|
+
const filters = Array.isArray(request) ? { dlqIds: request } : request;
|
|
705
|
+
return normalizeCursor(
|
|
706
|
+
await this.http.request({
|
|
707
|
+
method: "POST",
|
|
708
|
+
path: ["v2", "dlq", "retry"],
|
|
709
|
+
query: buildBulkActionFilterPayload(filters)
|
|
710
|
+
})
|
|
711
|
+
);
|
|
120
712
|
}
|
|
121
713
|
};
|
|
122
714
|
|
|
123
|
-
// src/client/
|
|
124
|
-
var
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
super(message);
|
|
129
|
-
this.name = "QstashError";
|
|
130
|
-
this.status = status;
|
|
715
|
+
// src/client/flow-control.ts
|
|
716
|
+
var FlowControlApi = class {
|
|
717
|
+
http;
|
|
718
|
+
constructor(http) {
|
|
719
|
+
this.http = http;
|
|
131
720
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.limit = args.limit;
|
|
141
|
-
this.remaining = args.remaining;
|
|
142
|
-
this.reset = args.reset;
|
|
721
|
+
/**
|
|
722
|
+
* Get a single flow control by key.
|
|
723
|
+
*/
|
|
724
|
+
async get(flowControlKey) {
|
|
725
|
+
return await this.http.request({
|
|
726
|
+
method: "GET",
|
|
727
|
+
path: ["v2", "flowControl", flowControlKey]
|
|
728
|
+
});
|
|
143
729
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
730
|
+
/**
|
|
731
|
+
* Get the global parallelism info.
|
|
732
|
+
*/
|
|
733
|
+
async getGlobalParallelism() {
|
|
734
|
+
const response = await this.http.request({
|
|
735
|
+
method: "GET",
|
|
736
|
+
path: ["v2", "globalParallelism"]
|
|
737
|
+
});
|
|
738
|
+
return {
|
|
739
|
+
parallelismMax: response.parallelismMax ?? 0,
|
|
740
|
+
parallelismCount: response.parallelismCount ?? 0
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Pause message delivery for a flow-control key.
|
|
745
|
+
*
|
|
746
|
+
* Messages already in the waitlist will remain there.
|
|
747
|
+
* New incoming messages will be added directly to the waitlist.
|
|
748
|
+
*/
|
|
749
|
+
async pause(flowControlKey) {
|
|
750
|
+
await this.http.request({
|
|
751
|
+
method: "POST",
|
|
752
|
+
path: ["v2", "flowControl", flowControlKey, "pause"],
|
|
753
|
+
parseResponseAsJson: false
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Resume message delivery for a flow-control key.
|
|
758
|
+
*/
|
|
759
|
+
async resume(flowControlKey) {
|
|
760
|
+
await this.http.request({
|
|
761
|
+
method: "POST",
|
|
762
|
+
path: ["v2", "flowControl", flowControlKey, "resume"],
|
|
763
|
+
parseResponseAsJson: false
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Pin a processing configuration for a flow-control key.
|
|
768
|
+
*
|
|
769
|
+
* While pinned, the system ignores configurations provided by incoming
|
|
770
|
+
* messages and uses the pinned configuration instead.
|
|
771
|
+
*/
|
|
772
|
+
async pin(flowControlKey, options) {
|
|
773
|
+
await this.http.request({
|
|
774
|
+
method: "POST",
|
|
775
|
+
path: ["v2", "flowControl", flowControlKey, "pin"],
|
|
776
|
+
query: {
|
|
777
|
+
parallelism: options.parallelism,
|
|
778
|
+
rate: options.rate,
|
|
779
|
+
period: options.period
|
|
780
|
+
},
|
|
781
|
+
parseResponseAsJson: false
|
|
782
|
+
});
|
|
161
783
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
this.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
784
|
+
/**
|
|
785
|
+
* Remove the pinned configuration for a flow-control key.
|
|
786
|
+
*
|
|
787
|
+
* After unpinning, the system resumes updating the configuration
|
|
788
|
+
* based on incoming messages.
|
|
789
|
+
*/
|
|
790
|
+
async unpin(flowControlKey, options) {
|
|
791
|
+
await this.http.request({
|
|
792
|
+
method: "POST",
|
|
793
|
+
path: ["v2", "flowControl", flowControlKey, "unpin"],
|
|
794
|
+
query: {
|
|
795
|
+
parallelism: options.parallelism,
|
|
796
|
+
rate: options.rate
|
|
797
|
+
},
|
|
798
|
+
parseResponseAsJson: false
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Reset the rate configuration state for a flow-control key.
|
|
803
|
+
*
|
|
804
|
+
* Clears the current rate count and immediately ends the current period.
|
|
805
|
+
* The current timestamp becomes the start of the new rate period.
|
|
806
|
+
*/
|
|
807
|
+
async resetRate(flowControlKey) {
|
|
808
|
+
await this.http.request({
|
|
809
|
+
method: "POST",
|
|
810
|
+
path: ["v2", "flowControl", flowControlKey, "resetRate"],
|
|
811
|
+
parseResponseAsJson: false
|
|
812
|
+
});
|
|
173
813
|
}
|
|
174
814
|
};
|
|
175
815
|
|
|
@@ -270,7 +910,18 @@ var HttpClient = class {
|
|
|
270
910
|
const url = new URL([request.baseUrl ?? this.baseUrl, ...request.path].join("/"));
|
|
271
911
|
if (request.query) {
|
|
272
912
|
for (const [key, value] of Object.entries(request.query)) {
|
|
273
|
-
if (value
|
|
913
|
+
if (value === void 0)
|
|
914
|
+
continue;
|
|
915
|
+
if (Array.isArray(value)) {
|
|
916
|
+
if (value.length === 0) {
|
|
917
|
+
throw new QstashEmptyArrayError(key);
|
|
918
|
+
}
|
|
919
|
+
for (const item of value) {
|
|
920
|
+
url.searchParams.append(key, item);
|
|
921
|
+
}
|
|
922
|
+
} else if (value instanceof Date) {
|
|
923
|
+
url.searchParams.set(key, value.getTime().toString());
|
|
924
|
+
} else {
|
|
274
925
|
url.searchParams.set(key, value.toString());
|
|
275
926
|
}
|
|
276
927
|
}
|
|
@@ -421,371 +1072,151 @@ var Chat = class _Chat {
|
|
|
421
1072
|
*/
|
|
422
1073
|
createThirdParty = async (request) => {
|
|
423
1074
|
const { baseUrl, token, owner, organization } = request.provider;
|
|
424
|
-
if (owner === "upstash")
|
|
425
|
-
throw new Error("Upstash is not 3rd party provider!");
|
|
426
|
-
delete request.provider;
|
|
427
|
-
delete request.system;
|
|
428
|
-
const analytics = request.analytics;
|
|
429
|
-
delete request.analytics;
|
|
430
|
-
const body = JSON.stringify(request);
|
|
431
|
-
const isAnalyticsEnabled = analytics?.name && analytics.token;
|
|
432
|
-
const analyticsConfig = analytics?.name && analytics.token ? setupAnalytics({ name: analytics.name, token: analytics.token }, token, baseUrl, owner) : { defaultHeaders: void 0, baseURL: baseUrl };
|
|
433
|
-
const isStream = "stream" in request && request.stream;
|
|
434
|
-
const headers = {
|
|
435
|
-
"Content-Type": "application/json",
|
|
436
|
-
Authorization: `Bearer ${token}`,
|
|
437
|
-
...organization ? {
|
|
438
|
-
"OpenAI-Organization": organization
|
|
439
|
-
} : {},
|
|
440
|
-
...isStream ? {
|
|
441
|
-
Connection: "keep-alive",
|
|
442
|
-
Accept: "text/event-stream",
|
|
443
|
-
"Cache-Control": "no-cache"
|
|
444
|
-
} : {},
|
|
445
|
-
...analyticsConfig.defaultHeaders
|
|
446
|
-
};
|
|
447
|
-
const response = await this.http[isStream ? "requestStream" : "request"]({
|
|
448
|
-
path: isAnalyticsEnabled ? [] : ["v1", "chat", "completions"],
|
|
449
|
-
method: "POST",
|
|
450
|
-
headers,
|
|
451
|
-
body,
|
|
452
|
-
baseUrl: analyticsConfig.baseURL
|
|
453
|
-
});
|
|
454
|
-
return response;
|
|
455
|
-
};
|
|
456
|
-
// Helper method to get the authorization token
|
|
457
|
-
getAuthorizationToken() {
|
|
458
|
-
const authHeader = String(this.http.authorization);
|
|
459
|
-
const match = /Bearer (.+)/.exec(authHeader);
|
|
460
|
-
if (!match) {
|
|
461
|
-
throw new Error("Invalid authorization header format");
|
|
462
|
-
}
|
|
463
|
-
return match[1];
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Calls the Upstash completions api given a PromptRequest.
|
|
467
|
-
*
|
|
468
|
-
* Returns a ChatCompletion or a stream of ChatCompletionChunks
|
|
469
|
-
* if stream is enabled.
|
|
470
|
-
*
|
|
471
|
-
* @param request PromptRequest with system and user messages.
|
|
472
|
-
* Note that system parameter shouldn't be passed in the case of
|
|
473
|
-
* mistralai/Mistral-7B-Instruct-v0.2 model.
|
|
474
|
-
* @returns Chat completion or stream
|
|
475
|
-
*/
|
|
476
|
-
prompt = async (request) => {
|
|
477
|
-
const chatRequest = _Chat.toChatRequest(request);
|
|
478
|
-
return this.create(chatRequest);
|
|
479
|
-
};
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
// src/client/messages.ts
|
|
483
|
-
var Messages = class {
|
|
484
|
-
http;
|
|
485
|
-
constructor(http) {
|
|
486
|
-
this.http = http;
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Get a message
|
|
490
|
-
*/
|
|
491
|
-
async get(messageId) {
|
|
492
|
-
const messagePayload = await this.http.request({
|
|
493
|
-
method: "GET",
|
|
494
|
-
path: ["v2", "messages", messageId]
|
|
495
|
-
});
|
|
496
|
-
const message = {
|
|
497
|
-
...messagePayload,
|
|
498
|
-
urlGroup: messagePayload.topicName,
|
|
499
|
-
ratePerSecond: "rate" in messagePayload ? messagePayload.rate : void 0
|
|
500
|
-
};
|
|
501
|
-
return message;
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* Cancel a message
|
|
505
|
-
*/
|
|
506
|
-
async delete(messageId) {
|
|
507
|
-
return await this.http.request({
|
|
508
|
-
method: "DELETE",
|
|
509
|
-
path: ["v2", "messages", messageId],
|
|
510
|
-
parseResponseAsJson: false
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
|
-
async deleteMany(messageIds) {
|
|
514
|
-
const result = await this.http.request({
|
|
515
|
-
method: "DELETE",
|
|
516
|
-
path: ["v2", "messages"],
|
|
517
|
-
headers: { "Content-Type": "application/json" },
|
|
518
|
-
body: JSON.stringify({ messageIds })
|
|
519
|
-
});
|
|
520
|
-
return result.cancelled;
|
|
521
|
-
}
|
|
522
|
-
async deleteAll() {
|
|
523
|
-
const result = await this.http.request({
|
|
524
|
-
method: "DELETE",
|
|
525
|
-
path: ["v2", "messages"]
|
|
526
|
-
});
|
|
527
|
-
return result.cancelled;
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
// src/client/api/base.ts
|
|
532
|
-
var BaseProvider = class {
|
|
533
|
-
baseUrl;
|
|
534
|
-
token;
|
|
535
|
-
owner;
|
|
536
|
-
constructor(baseUrl, token, owner) {
|
|
537
|
-
this.baseUrl = baseUrl;
|
|
538
|
-
this.token = token;
|
|
539
|
-
this.owner = owner;
|
|
540
|
-
}
|
|
541
|
-
getUrl() {
|
|
542
|
-
return `${this.baseUrl}/${this.getRoute().join("/")}`;
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
// src/client/api/llm.ts
|
|
547
|
-
var LLMProvider = class extends BaseProvider {
|
|
548
|
-
apiKind = "llm";
|
|
549
|
-
organization;
|
|
550
|
-
method = "POST";
|
|
551
|
-
constructor(baseUrl, token, owner, organization) {
|
|
552
|
-
super(baseUrl, token, owner);
|
|
553
|
-
this.organization = organization;
|
|
554
|
-
}
|
|
555
|
-
getRoute() {
|
|
556
|
-
return this.owner === "anthropic" ? ["v1", "messages"] : ["v1", "chat", "completions"];
|
|
557
|
-
}
|
|
558
|
-
getHeaders(options) {
|
|
559
|
-
if (this.owner === "upstash" && !options.analytics) {
|
|
560
|
-
return { "content-type": "application/json" };
|
|
561
|
-
}
|
|
562
|
-
const header = this.owner === "anthropic" ? "x-api-key" : "authorization";
|
|
563
|
-
const headerValue = this.owner === "anthropic" ? this.token : `Bearer ${this.token}`;
|
|
564
|
-
const headers = {
|
|
565
|
-
[header]: headerValue,
|
|
566
|
-
"content-type": "application/json"
|
|
567
|
-
};
|
|
568
|
-
if (this.owner === "openai" && this.organization) {
|
|
569
|
-
headers["OpenAI-Organization"] = this.organization;
|
|
570
|
-
}
|
|
571
|
-
if (this.owner === "anthropic") {
|
|
572
|
-
headers["anthropic-version"] = "2023-06-01";
|
|
573
|
-
}
|
|
574
|
-
return headers;
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Checks if callback exists and adds analytics in place if it's set.
|
|
578
|
-
*
|
|
579
|
-
* @param request
|
|
580
|
-
* @param options
|
|
581
|
-
*/
|
|
582
|
-
onFinish(providerInfo, options) {
|
|
583
|
-
if (options.analytics) {
|
|
584
|
-
return updateWithAnalytics(providerInfo, options.analytics);
|
|
585
|
-
}
|
|
586
|
-
return providerInfo;
|
|
587
|
-
}
|
|
588
|
-
};
|
|
589
|
-
var upstash = () => {
|
|
590
|
-
return new LLMProvider("https://qstash.upstash.io/llm", "", "upstash");
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
// src/client/api/utils.ts
|
|
594
|
-
var getProviderInfo = (api, upstashToken) => {
|
|
595
|
-
const { name, provider, ...parameters } = api;
|
|
596
|
-
const finalProvider = provider ?? upstash();
|
|
597
|
-
if (finalProvider.owner === "upstash" && !finalProvider.token) {
|
|
598
|
-
finalProvider.token = upstashToken;
|
|
599
|
-
}
|
|
600
|
-
if (!finalProvider.baseUrl)
|
|
601
|
-
throw new TypeError("baseUrl cannot be empty or undefined!");
|
|
602
|
-
if (!finalProvider.token)
|
|
603
|
-
throw new TypeError("token cannot be empty or undefined!");
|
|
604
|
-
if (finalProvider.apiKind !== name) {
|
|
605
|
-
throw new TypeError(
|
|
606
|
-
`Unexpected api name. Expected '${finalProvider.apiKind}', received ${name}`
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
|
-
const providerInfo = {
|
|
610
|
-
url: finalProvider.getUrl(),
|
|
611
|
-
baseUrl: finalProvider.baseUrl,
|
|
612
|
-
route: finalProvider.getRoute(),
|
|
613
|
-
appendHeaders: finalProvider.getHeaders(parameters),
|
|
614
|
-
owner: finalProvider.owner,
|
|
615
|
-
method: finalProvider.method
|
|
616
|
-
};
|
|
617
|
-
return finalProvider.onFinish(providerInfo, parameters);
|
|
618
|
-
};
|
|
619
|
-
var safeJoinHeaders = (headers, record) => {
|
|
620
|
-
const joinedHeaders = new Headers(record);
|
|
621
|
-
for (const [header, value] of headers.entries()) {
|
|
622
|
-
joinedHeaders.set(header, value);
|
|
623
|
-
}
|
|
624
|
-
return joinedHeaders;
|
|
625
|
-
};
|
|
626
|
-
var processApi = (request, headers, upstashToken) => {
|
|
627
|
-
if (!request.api) {
|
|
628
|
-
request.headers = headers;
|
|
629
|
-
return request;
|
|
630
|
-
}
|
|
631
|
-
const { url, appendHeaders, owner, method } = getProviderInfo(request.api, upstashToken);
|
|
632
|
-
if (request.api.name === "llm") {
|
|
633
|
-
const callback = request.callback;
|
|
634
|
-
if (!callback) {
|
|
635
|
-
throw new TypeError("Callback cannot be undefined when using LLM api.");
|
|
636
|
-
}
|
|
637
|
-
return {
|
|
638
|
-
...request,
|
|
639
|
-
method: request.method ?? method,
|
|
640
|
-
headers: safeJoinHeaders(headers, appendHeaders),
|
|
641
|
-
...owner === "upstash" && !request.api.analytics ? { api: { name: "llm" }, url: void 0, callback } : { url, api: void 0 }
|
|
642
|
-
};
|
|
643
|
-
} else {
|
|
644
|
-
return {
|
|
645
|
-
...request,
|
|
646
|
-
method: request.method ?? method,
|
|
647
|
-
headers: safeJoinHeaders(headers, appendHeaders),
|
|
648
|
-
url,
|
|
649
|
-
api: void 0
|
|
1075
|
+
if (owner === "upstash")
|
|
1076
|
+
throw new Error("Upstash is not 3rd party provider!");
|
|
1077
|
+
delete request.provider;
|
|
1078
|
+
delete request.system;
|
|
1079
|
+
const analytics = request.analytics;
|
|
1080
|
+
delete request.analytics;
|
|
1081
|
+
const body = JSON.stringify(request);
|
|
1082
|
+
const isAnalyticsEnabled = analytics?.name && analytics.token;
|
|
1083
|
+
const analyticsConfig = analytics?.name && analytics.token ? setupAnalytics({ name: analytics.name, token: analytics.token }, token, baseUrl, owner) : { defaultHeaders: void 0, baseURL: baseUrl };
|
|
1084
|
+
const isStream = "stream" in request && request.stream;
|
|
1085
|
+
const headers = {
|
|
1086
|
+
"Content-Type": "application/json",
|
|
1087
|
+
Authorization: `Bearer ${token}`,
|
|
1088
|
+
...organization ? {
|
|
1089
|
+
"OpenAI-Organization": organization
|
|
1090
|
+
} : {},
|
|
1091
|
+
...isStream ? {
|
|
1092
|
+
Connection: "keep-alive",
|
|
1093
|
+
Accept: "text/event-stream",
|
|
1094
|
+
"Cache-Control": "no-cache"
|
|
1095
|
+
} : {},
|
|
1096
|
+
...analyticsConfig.defaultHeaders
|
|
650
1097
|
};
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
return providerInfo;
|
|
667
|
-
}
|
|
668
|
-
default: {
|
|
669
|
-
throw new Error("Unknown analytics provider");
|
|
1098
|
+
const response = await this.http[isStream ? "requestStream" : "request"]({
|
|
1099
|
+
path: isAnalyticsEnabled ? [] : ["v1", "chat", "completions"],
|
|
1100
|
+
method: "POST",
|
|
1101
|
+
headers,
|
|
1102
|
+
body,
|
|
1103
|
+
baseUrl: analyticsConfig.baseURL
|
|
1104
|
+
});
|
|
1105
|
+
return response;
|
|
1106
|
+
};
|
|
1107
|
+
// Helper method to get the authorization token
|
|
1108
|
+
getAuthorizationToken() {
|
|
1109
|
+
const authHeader = String(this.http.authorization);
|
|
1110
|
+
const match = /Bearer (.+)/.exec(authHeader);
|
|
1111
|
+
if (!match) {
|
|
1112
|
+
throw new Error("Invalid authorization header format");
|
|
670
1113
|
}
|
|
1114
|
+
return match[1];
|
|
671
1115
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
1116
|
+
/**
|
|
1117
|
+
* Calls the Upstash completions api given a PromptRequest.
|
|
1118
|
+
*
|
|
1119
|
+
* Returns a ChatCompletion or a stream of ChatCompletionChunks
|
|
1120
|
+
* if stream is enabled.
|
|
1121
|
+
*
|
|
1122
|
+
* @param request PromptRequest with system and user messages.
|
|
1123
|
+
* Note that system parameter shouldn't be passed in the case of
|
|
1124
|
+
* mistralai/Mistral-7B-Instruct-v0.2 model.
|
|
1125
|
+
* @returns Chat completion or stream
|
|
1126
|
+
*/
|
|
1127
|
+
prompt = async (request) => {
|
|
1128
|
+
const chatRequest = _Chat.toChatRequest(request);
|
|
1129
|
+
return this.create(chatRequest);
|
|
1130
|
+
};
|
|
683
1131
|
};
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
}
|
|
691
|
-
headers.delete(key);
|
|
692
|
-
}
|
|
693
|
-
return headers;
|
|
694
|
-
}
|
|
695
|
-
function wrapWithGlobalHeaders(headers, globalHeaders, telemetryHeaders) {
|
|
696
|
-
if (!globalHeaders) {
|
|
697
|
-
return headers;
|
|
698
|
-
}
|
|
699
|
-
const finalHeaders = new Headers(globalHeaders);
|
|
700
|
-
headers.forEach((value, key) => {
|
|
701
|
-
finalHeaders.set(key, value);
|
|
702
|
-
});
|
|
703
|
-
telemetryHeaders?.forEach((value, key) => {
|
|
704
|
-
if (!value)
|
|
705
|
-
return;
|
|
706
|
-
finalHeaders.append(key, value);
|
|
707
|
-
});
|
|
708
|
-
return finalHeaders;
|
|
709
|
-
}
|
|
710
|
-
function processHeaders(request) {
|
|
711
|
-
const headers = prefixHeaders(new Headers(request.headers));
|
|
712
|
-
headers.set("Upstash-Method", request.method ?? "POST");
|
|
713
|
-
if (request.delay !== void 0) {
|
|
714
|
-
if (typeof request.delay === "string") {
|
|
715
|
-
headers.set("Upstash-Delay", request.delay);
|
|
716
|
-
} else {
|
|
717
|
-
headers.set("Upstash-Delay", `${request.delay.toFixed(0)}s`);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
if (request.notBefore !== void 0) {
|
|
721
|
-
headers.set("Upstash-Not-Before", request.notBefore.toFixed(0));
|
|
722
|
-
}
|
|
723
|
-
if (request.deduplicationId !== void 0) {
|
|
724
|
-
headers.set("Upstash-Deduplication-Id", request.deduplicationId);
|
|
725
|
-
}
|
|
726
|
-
if (request.contentBasedDeduplication) {
|
|
727
|
-
headers.set("Upstash-Content-Based-Deduplication", "true");
|
|
728
|
-
}
|
|
729
|
-
if (request.retries !== void 0) {
|
|
730
|
-
headers.set("Upstash-Retries", request.retries.toFixed(0));
|
|
731
|
-
}
|
|
732
|
-
if (request.retryDelay !== void 0) {
|
|
733
|
-
headers.set("Upstash-Retry-Delay", request.retryDelay);
|
|
734
|
-
}
|
|
735
|
-
if (request.callback !== void 0) {
|
|
736
|
-
headers.set("Upstash-Callback", request.callback);
|
|
1132
|
+
|
|
1133
|
+
// src/client/messages.ts
|
|
1134
|
+
var Messages = class {
|
|
1135
|
+
http;
|
|
1136
|
+
constructor(http) {
|
|
1137
|
+
this.http = http;
|
|
737
1138
|
}
|
|
738
|
-
|
|
739
|
-
|
|
1139
|
+
/**
|
|
1140
|
+
* Get a message
|
|
1141
|
+
*/
|
|
1142
|
+
async get(messageId) {
|
|
1143
|
+
const messagePayload = await this.http.request({
|
|
1144
|
+
method: "GET",
|
|
1145
|
+
path: ["v2", "messages", messageId]
|
|
1146
|
+
});
|
|
1147
|
+
const message = {
|
|
1148
|
+
...messagePayload,
|
|
1149
|
+
urlGroup: messagePayload.topicName,
|
|
1150
|
+
ratePerSecond: "rate" in messagePayload ? messagePayload.rate : void 0
|
|
1151
|
+
};
|
|
1152
|
+
return message;
|
|
740
1153
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1154
|
+
/**
|
|
1155
|
+
* Cancel messages.
|
|
1156
|
+
*
|
|
1157
|
+
* Can be called with:
|
|
1158
|
+
* - A single messageId: `cancel("id")`
|
|
1159
|
+
* - An array of messageIds: `cancel(["id1", "id2"])`
|
|
1160
|
+
* - A filter object: `cancel({ filter: { flowControlKey: "key", label: "label" } })`
|
|
1161
|
+
* - All messages: `cancel({ all: true })`
|
|
1162
|
+
*
|
|
1163
|
+
* Pass `count` to limit the number of messages processed per call (defaults to 100).
|
|
1164
|
+
* Call in a loop until `cancelled` is 0:
|
|
1165
|
+
*
|
|
1166
|
+
* ```ts
|
|
1167
|
+
* let cancelled: number;
|
|
1168
|
+
* do {
|
|
1169
|
+
* const result = await messages.cancel({ all: true, count: 100 });
|
|
1170
|
+
* cancelled = result.cancelled;
|
|
1171
|
+
* } while (cancelled > 0);
|
|
1172
|
+
* ```
|
|
1173
|
+
*/
|
|
1174
|
+
async cancel(request) {
|
|
1175
|
+
if (typeof request === "string") {
|
|
1176
|
+
return await this.http.request({
|
|
1177
|
+
method: "DELETE",
|
|
1178
|
+
path: ["v2", "messages", request]
|
|
1179
|
+
});
|
|
746
1180
|
}
|
|
1181
|
+
if (Array.isArray(request) && request.length === 0)
|
|
1182
|
+
return { cancelled: 0 };
|
|
1183
|
+
const filters = Array.isArray(request) ? { messageIds: request } : request;
|
|
1184
|
+
return await this.http.request({
|
|
1185
|
+
method: "DELETE",
|
|
1186
|
+
path: ["v2", "messages"],
|
|
1187
|
+
query: buildBulkActionFilterPayload(filters)
|
|
1188
|
+
});
|
|
747
1189
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
headers.set("Upstash-Flow-Control-Key", request.flowControl.key);
|
|
761
|
-
headers.set("Upstash-Flow-Control-Value", controlValue.join(", "));
|
|
1190
|
+
/**
|
|
1191
|
+
* Delete a message.
|
|
1192
|
+
*
|
|
1193
|
+
* @deprecated Use `cancel(messageId: string)` instead
|
|
1194
|
+
*/
|
|
1195
|
+
async delete(messageId) {
|
|
1196
|
+
await this.http.request({
|
|
1197
|
+
method: "DELETE",
|
|
1198
|
+
path: ["v2", "messages", messageId],
|
|
1199
|
+
parseResponseAsJson: false
|
|
1200
|
+
});
|
|
762
1201
|
}
|
|
763
|
-
|
|
764
|
-
|
|
1202
|
+
/**
|
|
1203
|
+
* Cancel multiple messages by their messageIds.
|
|
1204
|
+
*
|
|
1205
|
+
* @deprecated Use `cancel(messageIds: string[])` instead
|
|
1206
|
+
*/
|
|
1207
|
+
async deleteMany(messageIds) {
|
|
1208
|
+
const result = await this.cancel(messageIds);
|
|
1209
|
+
return result.cancelled;
|
|
765
1210
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
return `api/llm`;
|
|
774
|
-
if (request.api?.name === "email") {
|
|
775
|
-
const providerInfo = getProviderInfo(request.api, "not-needed");
|
|
776
|
-
return providerInfo.baseUrl;
|
|
1211
|
+
/**
|
|
1212
|
+
* Cancel all messages
|
|
1213
|
+
* @deprecated Use `cancel({all: true})` to cancel all
|
|
1214
|
+
*/
|
|
1215
|
+
async deleteAll() {
|
|
1216
|
+
const result = await this.cancel({ all: true });
|
|
1217
|
+
return result.cancelled;
|
|
777
1218
|
}
|
|
778
|
-
|
|
779
|
-
}
|
|
780
|
-
function getRuntime() {
|
|
781
|
-
if (typeof process === "object" && typeof process.versions == "object" && process.versions.bun)
|
|
782
|
-
return `bun@${process.versions.bun}`;
|
|
783
|
-
if (typeof EdgeRuntime === "string")
|
|
784
|
-
return "edge-light";
|
|
785
|
-
else if (typeof process === "object" && typeof process.version === "string")
|
|
786
|
-
return `node@${process.version}`;
|
|
787
|
-
return "";
|
|
788
|
-
}
|
|
1219
|
+
};
|
|
789
1220
|
|
|
790
1221
|
// src/client/queue.ts
|
|
791
1222
|
var Queue = class {
|
|
@@ -987,6 +1418,24 @@ var Schedules = class {
|
|
|
987
1418
|
if (request.label !== void 0) {
|
|
988
1419
|
headers.set("Upstash-Label", request.label);
|
|
989
1420
|
}
|
|
1421
|
+
if (request.redact !== void 0) {
|
|
1422
|
+
const redactParts = [];
|
|
1423
|
+
if (request.redact.body) {
|
|
1424
|
+
redactParts.push("body");
|
|
1425
|
+
}
|
|
1426
|
+
if (request.redact.header !== void 0) {
|
|
1427
|
+
if (request.redact.header === true) {
|
|
1428
|
+
redactParts.push("header");
|
|
1429
|
+
} else if (Array.isArray(request.redact.header) && request.redact.header.length > 0) {
|
|
1430
|
+
for (const headerName of request.redact.header) {
|
|
1431
|
+
redactParts.push(`header[${headerName}]`);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (redactParts.length > 0) {
|
|
1436
|
+
headers.set("Upstash-Redact-Fields", redactParts.join(","));
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
990
1439
|
return await this.http.request({
|
|
991
1440
|
method: "POST",
|
|
992
1441
|
headers: wrapWithGlobalHeaders(headers, this.http.headers, this.http.telemetryHeaders),
|
|
@@ -1116,19 +1565,15 @@ var UrlGroups = class {
|
|
|
1116
1565
|
};
|
|
1117
1566
|
|
|
1118
1567
|
// version.ts
|
|
1119
|
-
var VERSION = "
|
|
1568
|
+
var VERSION = "2.10.1";
|
|
1120
1569
|
|
|
1121
1570
|
// src/client/client.ts
|
|
1122
1571
|
var Client = class {
|
|
1123
1572
|
http;
|
|
1124
1573
|
token;
|
|
1125
1574
|
constructor(config) {
|
|
1126
|
-
const environment =
|
|
1127
|
-
|
|
1128
|
-
if (baseUrl === "https://qstash.upstash.io/v2/publish") {
|
|
1129
|
-
baseUrl = "https://qstash.upstash.io";
|
|
1130
|
-
}
|
|
1131
|
-
const token = config?.token ?? environment.QSTASH_TOKEN;
|
|
1575
|
+
const environment = getSafeEnvironment();
|
|
1576
|
+
const { baseUrl, token } = getClientCredentials({ environment, config });
|
|
1132
1577
|
const enableTelemetry = environment.UPSTASH_DISABLE_TELEMETRY ? false : config?.enableTelemetry ?? true;
|
|
1133
1578
|
const isCloudflare = typeof caches !== "undefined" && "default" in caches;
|
|
1134
1579
|
const telemetryHeaders = new Headers(
|
|
@@ -1147,11 +1592,6 @@ var Client = class {
|
|
|
1147
1592
|
//@ts-expect-error caused by undici and bunjs type overlap
|
|
1148
1593
|
telemetryHeaders
|
|
1149
1594
|
});
|
|
1150
|
-
if (!token) {
|
|
1151
|
-
console.warn(
|
|
1152
|
-
"[Upstash QStash] client token is not set. Either pass a token or set QSTASH_TOKEN env variable."
|
|
1153
|
-
);
|
|
1154
|
-
}
|
|
1155
1595
|
this.token = token;
|
|
1156
1596
|
}
|
|
1157
1597
|
/**
|
|
@@ -1196,6 +1636,14 @@ var Client = class {
|
|
|
1196
1636
|
get schedules() {
|
|
1197
1637
|
return new Schedules(this.http);
|
|
1198
1638
|
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Access the flow control API.
|
|
1641
|
+
*
|
|
1642
|
+
* List, get, or reset flow controls.
|
|
1643
|
+
*/
|
|
1644
|
+
get flowControl() {
|
|
1645
|
+
return new FlowControlApi(this.http);
|
|
1646
|
+
}
|
|
1199
1647
|
/**
|
|
1200
1648
|
* Access the workflow API.
|
|
1201
1649
|
*
|
|
@@ -1320,39 +1768,18 @@ var Client = class {
|
|
|
1320
1768
|
* }
|
|
1321
1769
|
* ```
|
|
1322
1770
|
*/
|
|
1323
|
-
async logs(request) {
|
|
1324
|
-
const query = {
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
}
|
|
1328
|
-
query.cursor = request.cursor;
|
|
1329
|
-
}
|
|
1330
|
-
for (const [key, value] of Object.entries(request?.filter ?? {})) {
|
|
1331
|
-
if (typeof value === "number" && value < 0) {
|
|
1332
|
-
continue;
|
|
1333
|
-
}
|
|
1334
|
-
if (key === "urlGroup") {
|
|
1335
|
-
query.topicName = value.toString();
|
|
1336
|
-
} else if (typeof value !== "undefined") {
|
|
1337
|
-
query[key] = value.toString();
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1771
|
+
async logs(request = {}) {
|
|
1772
|
+
const query = {
|
|
1773
|
+
count: request.count,
|
|
1774
|
+
..."messageIds" in request ? { messageIds: request.messageIds } : { ...renameUrlGroup(request.filter ?? {}), cursor: request.cursor }
|
|
1775
|
+
};
|
|
1340
1776
|
const responsePayload = await this.http.request({
|
|
1341
1777
|
path: ["v2", "events"],
|
|
1342
1778
|
method: "GET",
|
|
1343
1779
|
query
|
|
1344
1780
|
});
|
|
1345
|
-
const logs = responsePayload.events.map((event) => {
|
|
1346
|
-
|
|
1347
|
-
...event,
|
|
1348
|
-
urlGroup: event.topicName
|
|
1349
|
-
};
|
|
1350
|
-
});
|
|
1351
|
-
return {
|
|
1352
|
-
cursor: responsePayload.cursor,
|
|
1353
|
-
logs,
|
|
1354
|
-
events: logs
|
|
1355
|
-
};
|
|
1781
|
+
const logs = responsePayload.events.map((event) => ({ ...event, urlGroup: event.topicName }));
|
|
1782
|
+
return { cursor: responsePayload.cursor, logs, events: logs };
|
|
1356
1783
|
}
|
|
1357
1784
|
/**
|
|
1358
1785
|
* @deprecated Will be removed in the next major release. Use the `logs` method instead.
|
|
@@ -1405,9 +1832,11 @@ var Workflow = class {
|
|
|
1405
1832
|
exports.BaseProvider = BaseProvider;
|
|
1406
1833
|
exports.Chat = Chat;
|
|
1407
1834
|
exports.Client = Client;
|
|
1835
|
+
exports.FlowControlApi = FlowControlApi;
|
|
1408
1836
|
exports.Messages = Messages;
|
|
1409
1837
|
exports.QstashChatRatelimitError = QstashChatRatelimitError;
|
|
1410
1838
|
exports.QstashDailyRatelimitError = QstashDailyRatelimitError;
|
|
1839
|
+
exports.QstashEmptyArrayError = QstashEmptyArrayError;
|
|
1411
1840
|
exports.QstashError = QstashError;
|
|
1412
1841
|
exports.QstashRatelimitError = QstashRatelimitError;
|
|
1413
1842
|
exports.Receiver = Receiver;
|