@vercel/queue 0.0.0-alpha.32 → 0.0.0-alpha.33
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/index.d.mts +260 -73
- package/dist/index.d.ts +260 -73
- package/dist/index.js +308 -245
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -245
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs-pages.d.mts +1 -1
- package/dist/nextjs-pages.d.ts +1 -1
- package/dist/nextjs-pages.js +126 -118
- package/dist/nextjs-pages.js.map +1 -1
- package/dist/nextjs-pages.mjs +126 -118
- package/dist/nextjs-pages.mjs.map +1 -1
- package/dist/{types-JvOenjfT.d.mts → types-Dw29Fr9y.d.mts} +126 -2
- package/dist/{types-JvOenjfT.d.ts → types-Dw29Fr9y.d.ts} +126 -2
- package/package.json +1 -1
package/dist/nextjs-pages.mjs
CHANGED
|
@@ -74,6 +74,9 @@ var InvalidLimitError = class extends Error {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
// src/client.ts
|
|
77
|
+
function isDebugEnabled() {
|
|
78
|
+
return process.env.VERCEL_QUEUE_DEBUG === "1" || process.env.VERCEL_QUEUE_DEBUG === "true";
|
|
79
|
+
}
|
|
77
80
|
async function consumeStream(stream) {
|
|
78
81
|
const reader = stream.getReader();
|
|
79
82
|
try {
|
|
@@ -85,6 +88,31 @@ async function consumeStream(stream) {
|
|
|
85
88
|
reader.releaseLock();
|
|
86
89
|
}
|
|
87
90
|
}
|
|
91
|
+
function parseRetryAfter(headers) {
|
|
92
|
+
const retryAfterHeader = headers.get("Retry-After");
|
|
93
|
+
if (retryAfterHeader) {
|
|
94
|
+
const parsed = parseInt(retryAfterHeader, 10);
|
|
95
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
96
|
+
}
|
|
97
|
+
return void 0;
|
|
98
|
+
}
|
|
99
|
+
function throwCommonHttpError(status, statusText, errorText, operation, badRequestDefault = "Invalid parameters") {
|
|
100
|
+
if (status === 400) {
|
|
101
|
+
throw new BadRequestError(errorText || badRequestDefault);
|
|
102
|
+
}
|
|
103
|
+
if (status === 401) {
|
|
104
|
+
throw new UnauthorizedError(errorText || void 0);
|
|
105
|
+
}
|
|
106
|
+
if (status === 403) {
|
|
107
|
+
throw new ForbiddenError(errorText || void 0);
|
|
108
|
+
}
|
|
109
|
+
if (status >= 500) {
|
|
110
|
+
throw new InternalServerError(
|
|
111
|
+
errorText || `Server error: ${status} ${statusText}`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
throw new Error(`Failed to ${operation}: ${status} ${statusText}`);
|
|
115
|
+
}
|
|
88
116
|
function parseQueueHeaders(headers) {
|
|
89
117
|
const messageId = headers.get("Vqs-Message-Id");
|
|
90
118
|
const deliveryCountStr = headers.get("Vqs-Delivery-Count") || "0";
|
|
@@ -95,7 +123,7 @@ function parseQueueHeaders(headers) {
|
|
|
95
123
|
return null;
|
|
96
124
|
}
|
|
97
125
|
const deliveryCount = parseInt(deliveryCountStr, 10);
|
|
98
|
-
if (isNaN(deliveryCount)) {
|
|
126
|
+
if (Number.isNaN(deliveryCount)) {
|
|
99
127
|
return null;
|
|
100
128
|
}
|
|
101
129
|
return {
|
|
@@ -109,24 +137,22 @@ function parseQueueHeaders(headers) {
|
|
|
109
137
|
var QueueClient = class {
|
|
110
138
|
baseUrl;
|
|
111
139
|
basePath;
|
|
112
|
-
customHeaders
|
|
140
|
+
customHeaders;
|
|
141
|
+
providedToken;
|
|
113
142
|
/**
|
|
114
143
|
* Create a new Vercel Queue Service client
|
|
115
|
-
* @param options
|
|
144
|
+
* @param options QueueClient configuration options
|
|
116
145
|
*/
|
|
117
146
|
constructor(options = {}) {
|
|
118
147
|
this.baseUrl = options.baseUrl || process.env.VERCEL_QUEUE_BASE_URL || "https://vercel-queue.com";
|
|
119
148
|
this.basePath = options.basePath || process.env.VERCEL_QUEUE_BASE_PATH || "/api/v2/messages";
|
|
120
|
-
|
|
121
|
-
this.
|
|
122
|
-
Object.entries(process.env).filter(([key]) => key.startsWith(VERCEL_QUEUE_HEADER_PREFIX)).map(([key, value]) => [
|
|
123
|
-
// This allows headers to use dashes independent of shell used
|
|
124
|
-
key.replace(VERCEL_QUEUE_HEADER_PREFIX, "").replaceAll("__", "-"),
|
|
125
|
-
value || ""
|
|
126
|
-
])
|
|
127
|
-
);
|
|
149
|
+
this.customHeaders = options.headers || {};
|
|
150
|
+
this.providedToken = options.token;
|
|
128
151
|
}
|
|
129
152
|
async getToken() {
|
|
153
|
+
if (this.providedToken) {
|
|
154
|
+
return this.providedToken;
|
|
155
|
+
}
|
|
130
156
|
const token = await getVercelOidcToken();
|
|
131
157
|
if (!token) {
|
|
132
158
|
throw new Error(
|
|
@@ -135,6 +161,45 @@ var QueueClient = class {
|
|
|
135
161
|
}
|
|
136
162
|
return token;
|
|
137
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Internal fetch wrapper that automatically handles debug logging
|
|
166
|
+
* when VERCEL_QUEUE_DEBUG is enabled
|
|
167
|
+
*/
|
|
168
|
+
async fetch(url, init) {
|
|
169
|
+
const method = init.method || "GET";
|
|
170
|
+
if (isDebugEnabled()) {
|
|
171
|
+
const logData = {
|
|
172
|
+
method,
|
|
173
|
+
url,
|
|
174
|
+
headers: init.headers
|
|
175
|
+
};
|
|
176
|
+
const body = init.body;
|
|
177
|
+
if (body !== void 0 && body !== null) {
|
|
178
|
+
if (body instanceof ArrayBuffer) {
|
|
179
|
+
logData.bodySize = body.byteLength;
|
|
180
|
+
} else if (body instanceof Uint8Array) {
|
|
181
|
+
logData.bodySize = body.byteLength;
|
|
182
|
+
} else if (typeof body === "string") {
|
|
183
|
+
logData.bodySize = body.length;
|
|
184
|
+
} else {
|
|
185
|
+
logData.bodyType = typeof body;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
|
|
189
|
+
}
|
|
190
|
+
const response = await fetch(url, init);
|
|
191
|
+
if (isDebugEnabled()) {
|
|
192
|
+
const logData = {
|
|
193
|
+
method,
|
|
194
|
+
url,
|
|
195
|
+
status: response.status,
|
|
196
|
+
statusText: response.statusText,
|
|
197
|
+
headers: response.headers
|
|
198
|
+
};
|
|
199
|
+
console.debug("[VQS Debug] Response:", JSON.stringify(logData, null, 2));
|
|
200
|
+
}
|
|
201
|
+
return response;
|
|
202
|
+
}
|
|
138
203
|
/**
|
|
139
204
|
* Send a message to a queue
|
|
140
205
|
* @param options Send message options
|
|
@@ -164,32 +229,21 @@ var QueueClient = class {
|
|
|
164
229
|
headers.set("Vqs-Retention-Seconds", retentionSeconds.toString());
|
|
165
230
|
}
|
|
166
231
|
const body = transport.serialize(payload);
|
|
167
|
-
const response = await fetch(`${this.baseUrl}${this.basePath}`, {
|
|
232
|
+
const response = await this.fetch(`${this.baseUrl}${this.basePath}`, {
|
|
168
233
|
method: "POST",
|
|
169
234
|
body,
|
|
170
235
|
headers
|
|
171
236
|
});
|
|
172
237
|
if (!response.ok) {
|
|
173
|
-
|
|
174
|
-
const errorText = await response.text();
|
|
175
|
-
throw new BadRequestError(errorText || "Invalid parameters");
|
|
176
|
-
}
|
|
177
|
-
if (response.status === 401) {
|
|
178
|
-
throw new UnauthorizedError();
|
|
179
|
-
}
|
|
180
|
-
if (response.status === 403) {
|
|
181
|
-
throw new ForbiddenError();
|
|
182
|
-
}
|
|
238
|
+
const errorText = await response.text();
|
|
183
239
|
if (response.status === 409) {
|
|
184
240
|
throw new Error("Duplicate idempotency key detected");
|
|
185
241
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
throw new Error(
|
|
192
|
-
`Failed to send message: ${response.status} ${response.statusText}`
|
|
242
|
+
throwCommonHttpError(
|
|
243
|
+
response.status,
|
|
244
|
+
response.statusText,
|
|
245
|
+
errorText,
|
|
246
|
+
"send message"
|
|
193
247
|
);
|
|
194
248
|
}
|
|
195
249
|
const responseData = await response.json();
|
|
@@ -229,7 +283,7 @@ var QueueClient = class {
|
|
|
229
283
|
if (limit !== void 0) {
|
|
230
284
|
headers.set("Vqs-Limit", limit.toString());
|
|
231
285
|
}
|
|
232
|
-
const response = await fetch(`${this.baseUrl}${this.basePath}`, {
|
|
286
|
+
const response = await this.fetch(`${this.baseUrl}${this.basePath}`, {
|
|
233
287
|
method: "GET",
|
|
234
288
|
headers
|
|
235
289
|
});
|
|
@@ -237,32 +291,18 @@ var QueueClient = class {
|
|
|
237
291
|
throw new QueueEmptyError(queueName, consumerGroup);
|
|
238
292
|
}
|
|
239
293
|
if (!response.ok) {
|
|
240
|
-
|
|
241
|
-
const errorText = await response.text();
|
|
242
|
-
throw new BadRequestError(errorText || "Invalid parameters");
|
|
243
|
-
}
|
|
244
|
-
if (response.status === 401) {
|
|
245
|
-
throw new UnauthorizedError();
|
|
246
|
-
}
|
|
247
|
-
if (response.status === 403) {
|
|
248
|
-
throw new ForbiddenError();
|
|
249
|
-
}
|
|
294
|
+
const errorText = await response.text();
|
|
250
295
|
if (response.status === 423) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const parsed = parseInt(retryAfterHeader, 10);
|
|
255
|
-
retryAfter = isNaN(parsed) ? void 0 : parsed;
|
|
256
|
-
}
|
|
257
|
-
throw new MessageLockedError("next message", retryAfter);
|
|
258
|
-
}
|
|
259
|
-
if (response.status >= 500) {
|
|
260
|
-
throw new InternalServerError(
|
|
261
|
-
`Server error: ${response.status} ${response.statusText}`
|
|
296
|
+
throw new MessageLockedError(
|
|
297
|
+
"next message",
|
|
298
|
+
parseRetryAfter(response.headers)
|
|
262
299
|
);
|
|
263
300
|
}
|
|
264
|
-
|
|
265
|
-
|
|
301
|
+
throwCommonHttpError(
|
|
302
|
+
response.status,
|
|
303
|
+
response.statusText,
|
|
304
|
+
errorText,
|
|
305
|
+
"receive messages"
|
|
266
306
|
);
|
|
267
307
|
}
|
|
268
308
|
for await (const multipartMessage of parseMultipartStream(response)) {
|
|
@@ -311,7 +351,7 @@ var QueueClient = class {
|
|
|
311
351
|
if (skipPayload) {
|
|
312
352
|
headers.set("Vqs-Skip-Payload", "1");
|
|
313
353
|
}
|
|
314
|
-
const response = await fetch(
|
|
354
|
+
const response = await this.fetch(
|
|
315
355
|
`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`,
|
|
316
356
|
{
|
|
317
357
|
method: "GET",
|
|
@@ -319,38 +359,24 @@ var QueueClient = class {
|
|
|
319
359
|
}
|
|
320
360
|
);
|
|
321
361
|
if (!response.ok) {
|
|
322
|
-
|
|
323
|
-
const errorText = await response.text();
|
|
324
|
-
throw new BadRequestError(errorText || "Invalid parameters");
|
|
325
|
-
}
|
|
326
|
-
if (response.status === 401) {
|
|
327
|
-
throw new UnauthorizedError();
|
|
328
|
-
}
|
|
329
|
-
if (response.status === 403) {
|
|
330
|
-
throw new ForbiddenError();
|
|
331
|
-
}
|
|
362
|
+
const errorText = await response.text();
|
|
332
363
|
if (response.status === 404) {
|
|
333
364
|
throw new MessageNotFoundError(messageId);
|
|
334
365
|
}
|
|
335
|
-
if (response.status === 423) {
|
|
336
|
-
const retryAfterHeader = response.headers.get("Retry-After");
|
|
337
|
-
let retryAfter;
|
|
338
|
-
if (retryAfterHeader) {
|
|
339
|
-
const parsed = parseInt(retryAfterHeader, 10);
|
|
340
|
-
retryAfter = isNaN(parsed) ? void 0 : parsed;
|
|
341
|
-
}
|
|
342
|
-
throw new MessageLockedError(messageId, retryAfter);
|
|
343
|
-
}
|
|
344
366
|
if (response.status === 409) {
|
|
345
367
|
throw new MessageNotAvailableError(messageId);
|
|
346
368
|
}
|
|
347
|
-
if (response.status
|
|
348
|
-
throw new
|
|
349
|
-
|
|
369
|
+
if (response.status === 423) {
|
|
370
|
+
throw new MessageLockedError(
|
|
371
|
+
messageId,
|
|
372
|
+
parseRetryAfter(response.headers)
|
|
350
373
|
);
|
|
351
374
|
}
|
|
352
|
-
|
|
353
|
-
|
|
375
|
+
throwCommonHttpError(
|
|
376
|
+
response.status,
|
|
377
|
+
response.statusText,
|
|
378
|
+
errorText,
|
|
379
|
+
"receive message by ID"
|
|
354
380
|
);
|
|
355
381
|
}
|
|
356
382
|
if (skipPayload && response.status === 204) {
|
|
@@ -420,7 +446,7 @@ var QueueClient = class {
|
|
|
420
446
|
*/
|
|
421
447
|
async deleteMessage(options) {
|
|
422
448
|
const { queueName, consumerGroup, messageId, ticket } = options;
|
|
423
|
-
const response = await fetch(
|
|
449
|
+
const response = await this.fetch(
|
|
424
450
|
`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`,
|
|
425
451
|
{
|
|
426
452
|
method: "DELETE",
|
|
@@ -434,31 +460,22 @@ var QueueClient = class {
|
|
|
434
460
|
}
|
|
435
461
|
);
|
|
436
462
|
if (!response.ok) {
|
|
437
|
-
|
|
438
|
-
throw new BadRequestError("Missing or invalid ticket");
|
|
439
|
-
}
|
|
440
|
-
if (response.status === 401) {
|
|
441
|
-
throw new UnauthorizedError();
|
|
442
|
-
}
|
|
443
|
-
if (response.status === 403) {
|
|
444
|
-
throw new ForbiddenError();
|
|
445
|
-
}
|
|
463
|
+
const errorText = await response.text();
|
|
446
464
|
if (response.status === 404) {
|
|
447
465
|
throw new MessageNotFoundError(messageId);
|
|
448
466
|
}
|
|
449
467
|
if (response.status === 409) {
|
|
450
468
|
throw new MessageNotAvailableError(
|
|
451
469
|
messageId,
|
|
452
|
-
"Invalid ticket, message not in correct state, or already processed"
|
|
470
|
+
errorText || "Invalid ticket, message not in correct state, or already processed"
|
|
453
471
|
);
|
|
454
472
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
`Failed to delete message: ${response.status} ${response.statusText}`
|
|
473
|
+
throwCommonHttpError(
|
|
474
|
+
response.status,
|
|
475
|
+
response.statusText,
|
|
476
|
+
errorText,
|
|
477
|
+
"delete message",
|
|
478
|
+
"Missing or invalid ticket"
|
|
462
479
|
);
|
|
463
480
|
}
|
|
464
481
|
return { deleted: true };
|
|
@@ -482,7 +499,7 @@ var QueueClient = class {
|
|
|
482
499
|
ticket,
|
|
483
500
|
visibilityTimeoutSeconds
|
|
484
501
|
} = options;
|
|
485
|
-
const response = await fetch(
|
|
502
|
+
const response = await this.fetch(
|
|
486
503
|
`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`,
|
|
487
504
|
{
|
|
488
505
|
method: "PATCH",
|
|
@@ -497,33 +514,22 @@ var QueueClient = class {
|
|
|
497
514
|
}
|
|
498
515
|
);
|
|
499
516
|
if (!response.ok) {
|
|
500
|
-
|
|
501
|
-
throw new BadRequestError(
|
|
502
|
-
"Missing ticket or invalid visibility timeout"
|
|
503
|
-
);
|
|
504
|
-
}
|
|
505
|
-
if (response.status === 401) {
|
|
506
|
-
throw new UnauthorizedError();
|
|
507
|
-
}
|
|
508
|
-
if (response.status === 403) {
|
|
509
|
-
throw new ForbiddenError();
|
|
510
|
-
}
|
|
517
|
+
const errorText = await response.text();
|
|
511
518
|
if (response.status === 404) {
|
|
512
519
|
throw new MessageNotFoundError(messageId);
|
|
513
520
|
}
|
|
514
521
|
if (response.status === 409) {
|
|
515
522
|
throw new MessageNotAvailableError(
|
|
516
523
|
messageId,
|
|
517
|
-
"Invalid ticket, message not in correct state, or already processed"
|
|
524
|
+
errorText || "Invalid ticket, message not in correct state, or already processed"
|
|
518
525
|
);
|
|
519
526
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
`Failed to change visibility: ${response.status} ${response.statusText}`
|
|
527
|
+
throwCommonHttpError(
|
|
528
|
+
response.status,
|
|
529
|
+
response.statusText,
|
|
530
|
+
errorText,
|
|
531
|
+
"change visibility",
|
|
532
|
+
"Missing ticket or invalid visibility timeout"
|
|
527
533
|
);
|
|
528
534
|
}
|
|
529
535
|
return { updated: true };
|
|
@@ -1097,7 +1103,7 @@ async function parseCallback(request) {
|
|
|
1097
1103
|
messageId
|
|
1098
1104
|
};
|
|
1099
1105
|
}
|
|
1100
|
-
function
|
|
1106
|
+
function createCallbackHandler(handlers, client) {
|
|
1101
1107
|
for (const topicPattern in handlers) {
|
|
1102
1108
|
if (topicPattern.includes("*")) {
|
|
1103
1109
|
if (!validateWildcardPattern(topicPattern)) {
|
|
@@ -1132,7 +1138,6 @@ function handleCallback(handlers) {
|
|
|
1132
1138
|
{ status: 404 }
|
|
1133
1139
|
);
|
|
1134
1140
|
}
|
|
1135
|
-
const client = new QueueClient();
|
|
1136
1141
|
const topic = new Topic(client, queueName);
|
|
1137
1142
|
const cg = topic.consumerGroup(consumerGroup);
|
|
1138
1143
|
await cg.consume(consumerGroupHandler, { messageId });
|
|
@@ -1153,6 +1158,9 @@ function handleCallback(handlers) {
|
|
|
1153
1158
|
}
|
|
1154
1159
|
return routeHandler;
|
|
1155
1160
|
}
|
|
1161
|
+
function handleCallback(handlers, client) {
|
|
1162
|
+
return createCallbackHandler(handlers, client || new QueueClient());
|
|
1163
|
+
}
|
|
1156
1164
|
|
|
1157
1165
|
// src/nextjs-pages.ts
|
|
1158
1166
|
function getHeader(headers, name) {
|