@vercel/queue 0.0.0-alpha.11 → 0.0.0-alpha.13
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 +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +75 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +74 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,12 @@ interface Transport<T = unknown> {
|
|
|
27
27
|
*/
|
|
28
28
|
declare class JsonTransport<T = unknown> implements Transport<T> {
|
|
29
29
|
readonly contentType = "application/json";
|
|
30
|
+
readonly replacer?: Parameters<typeof JSON.parse>[1];
|
|
31
|
+
readonly reviver?: Parameters<typeof JSON.parse>[1];
|
|
32
|
+
constructor(options?: {
|
|
33
|
+
replacer?: Parameters<typeof JSON.parse>[1];
|
|
34
|
+
reviver?: Parameters<typeof JSON.parse>[1];
|
|
35
|
+
});
|
|
30
36
|
serialize(value: T): Buffer;
|
|
31
37
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;
|
|
32
38
|
}
|
|
@@ -152,6 +158,8 @@ interface MessageMetadata {
|
|
|
152
158
|
messageId: string;
|
|
153
159
|
deliveryCount: number;
|
|
154
160
|
createdAt: Date;
|
|
161
|
+
topicName: string;
|
|
162
|
+
consumerGroup: string;
|
|
155
163
|
}
|
|
156
164
|
/**
|
|
157
165
|
* Message handler function type
|
|
@@ -325,6 +333,42 @@ type CallbackHandlers = {
|
|
|
325
333
|
[consumerGroup: string]: MessageHandler;
|
|
326
334
|
};
|
|
327
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* Parsed callback request information
|
|
338
|
+
*/
|
|
339
|
+
type ParsedCallbackRequest = {
|
|
340
|
+
queueName: string;
|
|
341
|
+
consumerGroup: string;
|
|
342
|
+
messageId: string;
|
|
343
|
+
};
|
|
344
|
+
/**
|
|
345
|
+
* Parse and validate callback request using CloudEvent specification
|
|
346
|
+
*
|
|
347
|
+
* Extracts queue information from CloudEvent format and validates
|
|
348
|
+
* that all required fields are present.
|
|
349
|
+
*
|
|
350
|
+
* @param request The incoming webhook request
|
|
351
|
+
* @returns Parsed queue information
|
|
352
|
+
* @throws Error if required fields are missing
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```typescript
|
|
356
|
+
* // In Next.js API route
|
|
357
|
+
* export async function POST(request: Request) {
|
|
358
|
+
* try {
|
|
359
|
+
* const { queueName, consumerGroup, messageId } = parseCallback(request);
|
|
360
|
+
*
|
|
361
|
+
* // Use the parsed information...
|
|
362
|
+
* await myWorkflow.handleWebhook(queueName, consumerGroup, messageId);
|
|
363
|
+
*
|
|
364
|
+
* return Response.json({ status: "success" });
|
|
365
|
+
* } catch (error) {
|
|
366
|
+
* return Response.json({ error: error.message }, { status: 400 });
|
|
367
|
+
* }
|
|
368
|
+
* }
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
|
|
328
372
|
/**
|
|
329
373
|
* Simplified queue callback handler for Next.js route handlers
|
|
330
374
|
*
|
|
@@ -359,4 +403,4 @@ type CallbackHandlers = {
|
|
|
359
403
|
*/
|
|
360
404
|
declare function handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
|
|
361
405
|
|
|
362
|
-
export { BadRequestError, BufferTransport, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, type PublishOptions, QueueEmptyError, type ReceiveOptions, type SendMessageOptions, type SendMessageResponse, type SendOptions, StreamTransport, type Transport, UnauthorizedError, handleCallback, receive, send };
|
|
406
|
+
export { BadRequestError, BufferTransport, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, type ParsedCallbackRequest, type PublishOptions, QueueEmptyError, type ReceiveOptions, type SendMessageOptions, type SendMessageResponse, type SendOptions, StreamTransport, type Transport, UnauthorizedError, handleCallback, parseCallback, receive, send };
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,12 @@ interface Transport<T = unknown> {
|
|
|
27
27
|
*/
|
|
28
28
|
declare class JsonTransport<T = unknown> implements Transport<T> {
|
|
29
29
|
readonly contentType = "application/json";
|
|
30
|
+
readonly replacer?: Parameters<typeof JSON.parse>[1];
|
|
31
|
+
readonly reviver?: Parameters<typeof JSON.parse>[1];
|
|
32
|
+
constructor(options?: {
|
|
33
|
+
replacer?: Parameters<typeof JSON.parse>[1];
|
|
34
|
+
reviver?: Parameters<typeof JSON.parse>[1];
|
|
35
|
+
});
|
|
30
36
|
serialize(value: T): Buffer;
|
|
31
37
|
deserialize(stream: ReadableStream<Uint8Array>): Promise<T>;
|
|
32
38
|
}
|
|
@@ -152,6 +158,8 @@ interface MessageMetadata {
|
|
|
152
158
|
messageId: string;
|
|
153
159
|
deliveryCount: number;
|
|
154
160
|
createdAt: Date;
|
|
161
|
+
topicName: string;
|
|
162
|
+
consumerGroup: string;
|
|
155
163
|
}
|
|
156
164
|
/**
|
|
157
165
|
* Message handler function type
|
|
@@ -325,6 +333,42 @@ type CallbackHandlers = {
|
|
|
325
333
|
[consumerGroup: string]: MessageHandler;
|
|
326
334
|
};
|
|
327
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* Parsed callback request information
|
|
338
|
+
*/
|
|
339
|
+
type ParsedCallbackRequest = {
|
|
340
|
+
queueName: string;
|
|
341
|
+
consumerGroup: string;
|
|
342
|
+
messageId: string;
|
|
343
|
+
};
|
|
344
|
+
/**
|
|
345
|
+
* Parse and validate callback request using CloudEvent specification
|
|
346
|
+
*
|
|
347
|
+
* Extracts queue information from CloudEvent format and validates
|
|
348
|
+
* that all required fields are present.
|
|
349
|
+
*
|
|
350
|
+
* @param request The incoming webhook request
|
|
351
|
+
* @returns Parsed queue information
|
|
352
|
+
* @throws Error if required fields are missing
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```typescript
|
|
356
|
+
* // In Next.js API route
|
|
357
|
+
* export async function POST(request: Request) {
|
|
358
|
+
* try {
|
|
359
|
+
* const { queueName, consumerGroup, messageId } = parseCallback(request);
|
|
360
|
+
*
|
|
361
|
+
* // Use the parsed information...
|
|
362
|
+
* await myWorkflow.handleWebhook(queueName, consumerGroup, messageId);
|
|
363
|
+
*
|
|
364
|
+
* return Response.json({ status: "success" });
|
|
365
|
+
* } catch (error) {
|
|
366
|
+
* return Response.json({ error: error.message }, { status: 400 });
|
|
367
|
+
* }
|
|
368
|
+
* }
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
declare function parseCallback(request: Request): Promise<ParsedCallbackRequest>;
|
|
328
372
|
/**
|
|
329
373
|
* Simplified queue callback handler for Next.js route handlers
|
|
330
374
|
*
|
|
@@ -359,4 +403,4 @@ type CallbackHandlers = {
|
|
|
359
403
|
*/
|
|
360
404
|
declare function handleCallback(handlers: CallbackHandlers): (request: Request) => Promise<Response>;
|
|
361
405
|
|
|
362
|
-
export { BadRequestError, BufferTransport, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, type PublishOptions, QueueEmptyError, type ReceiveOptions, type SendMessageOptions, type SendMessageResponse, type SendOptions, StreamTransport, type Transport, UnauthorizedError, handleCallback, receive, send };
|
|
406
|
+
export { BadRequestError, BufferTransport, ForbiddenError, InternalServerError, InvalidLimitError, JsonTransport, type Message, MessageCorruptedError, type MessageHandler, type MessageHandlerResult, MessageLockedError, type MessageMetadata, MessageNotAvailableError, MessageNotFoundError, type MessageTimeoutResult, type ParsedCallbackRequest, type PublishOptions, QueueEmptyError, type ReceiveOptions, type SendMessageOptions, type SendMessageResponse, type SendOptions, StreamTransport, type Transport, UnauthorizedError, handleCallback, parseCallback, receive, send };
|
package/dist/index.js
CHANGED
|
@@ -34,33 +34,43 @@ __export(index_exports, {
|
|
|
34
34
|
StreamTransport: () => StreamTransport,
|
|
35
35
|
UnauthorizedError: () => UnauthorizedError,
|
|
36
36
|
handleCallback: () => handleCallback,
|
|
37
|
+
parseCallback: () => parseCallback,
|
|
37
38
|
receive: () => receive,
|
|
38
39
|
send: () => send
|
|
39
40
|
});
|
|
40
41
|
module.exports = __toCommonJS(index_exports);
|
|
41
42
|
|
|
42
43
|
// src/transports.ts
|
|
44
|
+
async function streamToBuffer(stream) {
|
|
45
|
+
let totalLength = 0;
|
|
46
|
+
const reader = stream.getReader();
|
|
47
|
+
const chunks = [];
|
|
48
|
+
try {
|
|
49
|
+
while (true) {
|
|
50
|
+
const { done, value } = await reader.read();
|
|
51
|
+
if (done) break;
|
|
52
|
+
chunks.push(value);
|
|
53
|
+
totalLength += value.length;
|
|
54
|
+
}
|
|
55
|
+
} finally {
|
|
56
|
+
reader.releaseLock();
|
|
57
|
+
}
|
|
58
|
+
return Buffer.concat(chunks, totalLength);
|
|
59
|
+
}
|
|
43
60
|
var JsonTransport = class {
|
|
44
61
|
contentType = "application/json";
|
|
62
|
+
replacer;
|
|
63
|
+
reviver;
|
|
64
|
+
constructor(options = {}) {
|
|
65
|
+
this.replacer = options.replacer;
|
|
66
|
+
this.reviver = options.reviver;
|
|
67
|
+
}
|
|
45
68
|
serialize(value) {
|
|
46
|
-
return Buffer.from(JSON.stringify(value), "utf8");
|
|
69
|
+
return Buffer.from(JSON.stringify(value, this.replacer), "utf8");
|
|
47
70
|
}
|
|
48
71
|
async deserialize(stream) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const chunks = [];
|
|
52
|
-
try {
|
|
53
|
-
while (true) {
|
|
54
|
-
const { done, value } = await reader.read();
|
|
55
|
-
if (done) break;
|
|
56
|
-
chunks.push(value);
|
|
57
|
-
totalLength += value.length;
|
|
58
|
-
}
|
|
59
|
-
} finally {
|
|
60
|
-
reader.releaseLock();
|
|
61
|
-
}
|
|
62
|
-
const buffer = Buffer.concat(chunks, totalLength);
|
|
63
|
-
return JSON.parse(buffer.toString("utf8"));
|
|
72
|
+
const buffer = await streamToBuffer(stream);
|
|
73
|
+
return JSON.parse(buffer.toString("utf8"), this.reviver);
|
|
64
74
|
}
|
|
65
75
|
};
|
|
66
76
|
var BufferTransport = class {
|
|
@@ -69,25 +79,7 @@ var BufferTransport = class {
|
|
|
69
79
|
return value;
|
|
70
80
|
}
|
|
71
81
|
async deserialize(stream) {
|
|
72
|
-
|
|
73
|
-
const chunks = [];
|
|
74
|
-
try {
|
|
75
|
-
while (true) {
|
|
76
|
-
const { done, value } = await reader.read();
|
|
77
|
-
if (done) break;
|
|
78
|
-
chunks.push(value);
|
|
79
|
-
}
|
|
80
|
-
} finally {
|
|
81
|
-
reader.releaseLock();
|
|
82
|
-
}
|
|
83
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
84
|
-
const buffer = new Uint8Array(totalLength);
|
|
85
|
-
let offset = 0;
|
|
86
|
-
for (const chunk of chunks) {
|
|
87
|
-
buffer.set(chunk, offset);
|
|
88
|
-
offset += chunk.length;
|
|
89
|
-
}
|
|
90
|
-
return Buffer.from(buffer);
|
|
82
|
+
return await streamToBuffer(stream);
|
|
91
83
|
}
|
|
92
84
|
};
|
|
93
85
|
var StreamTransport = class {
|
|
@@ -237,8 +229,8 @@ var QueueClient = class {
|
|
|
237
229
|
* @param options Client configuration options (optional - will auto-detect Vercel Function environment)
|
|
238
230
|
*/
|
|
239
231
|
constructor(options = {}) {
|
|
240
|
-
this.baseUrl = options.baseUrl || "https://
|
|
241
|
-
this.basePath = options.basePath || "/
|
|
232
|
+
this.baseUrl = options.baseUrl || "https://vercel-queue.com";
|
|
233
|
+
this.basePath = options.basePath || "/api/v2/messages";
|
|
242
234
|
if (options.token) {
|
|
243
235
|
this.token = options.token;
|
|
244
236
|
} else {
|
|
@@ -742,7 +734,9 @@ var ConsumerGroup = class {
|
|
|
742
734
|
const result = await handler(message.payload, {
|
|
743
735
|
messageId: message.messageId,
|
|
744
736
|
deliveryCount: message.deliveryCount,
|
|
745
|
-
createdAt: message.createdAt
|
|
737
|
+
createdAt: message.createdAt,
|
|
738
|
+
topicName: this.topicName,
|
|
739
|
+
consumerGroup: this.consumerGroupName
|
|
746
740
|
});
|
|
747
741
|
await stopExtension();
|
|
748
742
|
if (result && "timeoutSeconds" in result) {
|
|
@@ -945,7 +939,37 @@ async function receive(topicName, consumerGroup, handler, options) {
|
|
|
945
939
|
}
|
|
946
940
|
|
|
947
941
|
// src/callback.ts
|
|
948
|
-
|
|
942
|
+
function validateWildcardPattern(pattern) {
|
|
943
|
+
const firstIndex = pattern.indexOf("*");
|
|
944
|
+
const lastIndex = pattern.lastIndexOf("*");
|
|
945
|
+
if (firstIndex !== lastIndex) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
if (firstIndex === -1) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
if (firstIndex !== pattern.length - 1) {
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
function matchesWildcardPattern(topicName, pattern) {
|
|
957
|
+
const prefix = pattern.slice(0, -1);
|
|
958
|
+
return topicName.startsWith(prefix);
|
|
959
|
+
}
|
|
960
|
+
function findTopicHandler(queueName, handlers) {
|
|
961
|
+
const exactHandler = handlers[queueName];
|
|
962
|
+
if (exactHandler) {
|
|
963
|
+
return exactHandler;
|
|
964
|
+
}
|
|
965
|
+
for (const pattern in handlers) {
|
|
966
|
+
if (pattern.includes("*") && matchesWildcardPattern(queueName, pattern)) {
|
|
967
|
+
return handlers[pattern];
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
async function parseCallback(request) {
|
|
949
973
|
const contentType = request.headers.get("content-type");
|
|
950
974
|
if (!contentType || !contentType.includes("application/cloudevents+json")) {
|
|
951
975
|
throw new Error(
|
|
@@ -984,10 +1008,19 @@ async function parseCallbackRequest(request) {
|
|
|
984
1008
|
};
|
|
985
1009
|
}
|
|
986
1010
|
function handleCallback(handlers) {
|
|
1011
|
+
for (const topicPattern in handlers) {
|
|
1012
|
+
if (topicPattern.includes("*")) {
|
|
1013
|
+
if (!validateWildcardPattern(topicPattern)) {
|
|
1014
|
+
throw new Error(
|
|
1015
|
+
`Invalid wildcard pattern "${topicPattern}": * may only appear once and must be at the end of the topic name`
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
987
1020
|
return async (request) => {
|
|
988
1021
|
try {
|
|
989
|
-
const { queueName, consumerGroup, messageId } = await
|
|
990
|
-
const topicHandler = handlers
|
|
1022
|
+
const { queueName, consumerGroup, messageId } = await parseCallback(request);
|
|
1023
|
+
const topicHandler = findTopicHandler(queueName, handlers);
|
|
991
1024
|
if (!topicHandler) {
|
|
992
1025
|
const availableTopics = Object.keys(handlers).join(", ");
|
|
993
1026
|
return Response.json(
|
|
@@ -1042,6 +1075,7 @@ function handleCallback(handlers) {
|
|
|
1042
1075
|
StreamTransport,
|
|
1043
1076
|
UnauthorizedError,
|
|
1044
1077
|
handleCallback,
|
|
1078
|
+
parseCallback,
|
|
1045
1079
|
receive,
|
|
1046
1080
|
send
|
|
1047
1081
|
});
|