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