@vercel/queue 0.0.0-alpha.6 → 0.0.0-alpha.8
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/README.md +130 -192
- package/dist/index.d.mts +2 -386
- package/dist/index.d.ts +2 -386
- package/dist/index.js +106 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +106 -95
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,6 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
BadRequestError: () => BadRequestError,
|
|
24
24
|
BufferTransport: () => BufferTransport,
|
|
25
|
-
ConsumerGroup: () => ConsumerGroup,
|
|
26
25
|
ForbiddenError: () => ForbiddenError,
|
|
27
26
|
InternalServerError: () => InternalServerError,
|
|
28
27
|
InvalidLimitError: () => InvalidLimitError,
|
|
@@ -31,19 +30,87 @@ __export(index_exports, {
|
|
|
31
30
|
MessageLockedError: () => MessageLockedError,
|
|
32
31
|
MessageNotAvailableError: () => MessageNotAvailableError,
|
|
33
32
|
MessageNotFoundError: () => MessageNotFoundError,
|
|
34
|
-
QueueClient: () => QueueClient,
|
|
35
33
|
QueueEmptyError: () => QueueEmptyError,
|
|
36
34
|
StreamTransport: () => StreamTransport,
|
|
37
|
-
Topic: () => Topic,
|
|
38
35
|
UnauthorizedError: () => UnauthorizedError,
|
|
39
|
-
createTopic: () => createTopic,
|
|
40
36
|
handleCallback: () => handleCallback,
|
|
41
|
-
parseCallbackRequest: () => parseCallbackRequest,
|
|
42
37
|
receive: () => receive,
|
|
43
38
|
send: () => send
|
|
44
39
|
});
|
|
45
40
|
module.exports = __toCommonJS(index_exports);
|
|
46
41
|
|
|
42
|
+
// src/transports.ts
|
|
43
|
+
var JsonTransport = class {
|
|
44
|
+
contentType = "application/json";
|
|
45
|
+
serialize(value) {
|
|
46
|
+
return Buffer.from(JSON.stringify(value), "utf8");
|
|
47
|
+
}
|
|
48
|
+
async deserialize(stream) {
|
|
49
|
+
const reader = stream.getReader();
|
|
50
|
+
let totalLength = 0;
|
|
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"));
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var BufferTransport = class {
|
|
67
|
+
contentType = "application/octet-stream";
|
|
68
|
+
serialize(value) {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
async deserialize(stream) {
|
|
72
|
+
const reader = stream.getReader();
|
|
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);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
var StreamTransport = class {
|
|
94
|
+
contentType = "application/octet-stream";
|
|
95
|
+
serialize(value) {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
async deserialize(stream) {
|
|
99
|
+
return stream;
|
|
100
|
+
}
|
|
101
|
+
async finalize(payload) {
|
|
102
|
+
const reader = payload.getReader();
|
|
103
|
+
try {
|
|
104
|
+
while (true) {
|
|
105
|
+
const { done } = await reader.read();
|
|
106
|
+
if (done) break;
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
reader.releaseLock();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
47
114
|
// src/client.ts
|
|
48
115
|
var import_mixpart = require("mixpart");
|
|
49
116
|
|
|
@@ -153,7 +220,7 @@ var QueueClient = class _QueueClient {
|
|
|
153
220
|
baseUrl;
|
|
154
221
|
token;
|
|
155
222
|
/**
|
|
156
|
-
* Internal default instance for use by
|
|
223
|
+
* Internal default instance for use by convenience functions
|
|
157
224
|
* @internal
|
|
158
225
|
*/
|
|
159
226
|
static _defaultInstance = null;
|
|
@@ -589,78 +656,6 @@ var QueueClient = class _QueueClient {
|
|
|
589
656
|
}
|
|
590
657
|
};
|
|
591
658
|
|
|
592
|
-
// src/transports.ts
|
|
593
|
-
var JsonTransport = class {
|
|
594
|
-
contentType = "application/json";
|
|
595
|
-
serialize(value) {
|
|
596
|
-
return Buffer.from(JSON.stringify(value), "utf8");
|
|
597
|
-
}
|
|
598
|
-
async deserialize(stream) {
|
|
599
|
-
const reader = stream.getReader();
|
|
600
|
-
let totalLength = 0;
|
|
601
|
-
const chunks = [];
|
|
602
|
-
try {
|
|
603
|
-
while (true) {
|
|
604
|
-
const { done, value } = await reader.read();
|
|
605
|
-
if (done) break;
|
|
606
|
-
chunks.push(value);
|
|
607
|
-
totalLength += value.length;
|
|
608
|
-
}
|
|
609
|
-
} finally {
|
|
610
|
-
reader.releaseLock();
|
|
611
|
-
}
|
|
612
|
-
const buffer = Buffer.concat(chunks, totalLength);
|
|
613
|
-
return JSON.parse(buffer.toString("utf8"));
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
var BufferTransport = class {
|
|
617
|
-
contentType = "application/octet-stream";
|
|
618
|
-
serialize(value) {
|
|
619
|
-
return value;
|
|
620
|
-
}
|
|
621
|
-
async deserialize(stream) {
|
|
622
|
-
const reader = stream.getReader();
|
|
623
|
-
const chunks = [];
|
|
624
|
-
try {
|
|
625
|
-
while (true) {
|
|
626
|
-
const { done, value } = await reader.read();
|
|
627
|
-
if (done) break;
|
|
628
|
-
chunks.push(value);
|
|
629
|
-
}
|
|
630
|
-
} finally {
|
|
631
|
-
reader.releaseLock();
|
|
632
|
-
}
|
|
633
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
634
|
-
const buffer = new Uint8Array(totalLength);
|
|
635
|
-
let offset = 0;
|
|
636
|
-
for (const chunk of chunks) {
|
|
637
|
-
buffer.set(chunk, offset);
|
|
638
|
-
offset += chunk.length;
|
|
639
|
-
}
|
|
640
|
-
return Buffer.from(buffer);
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
var StreamTransport = class {
|
|
644
|
-
contentType = "application/octet-stream";
|
|
645
|
-
serialize(value) {
|
|
646
|
-
return value;
|
|
647
|
-
}
|
|
648
|
-
async deserialize(stream) {
|
|
649
|
-
return stream;
|
|
650
|
-
}
|
|
651
|
-
async finalize(payload) {
|
|
652
|
-
const reader = payload.getReader();
|
|
653
|
-
try {
|
|
654
|
-
while (true) {
|
|
655
|
-
const { done } = await reader.read();
|
|
656
|
-
if (done) break;
|
|
657
|
-
}
|
|
658
|
-
} finally {
|
|
659
|
-
reader.releaseLock();
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
659
|
// src/consumer-group.ts
|
|
665
660
|
var ConsumerGroup = class {
|
|
666
661
|
client;
|
|
@@ -931,10 +926,6 @@ var Topic = class {
|
|
|
931
926
|
};
|
|
932
927
|
|
|
933
928
|
// src/factory.ts
|
|
934
|
-
function createTopic(topicName, transport) {
|
|
935
|
-
const client = QueueClient._getDefaultInstance();
|
|
936
|
-
return new Topic(client, topicName, transport);
|
|
937
|
-
}
|
|
938
929
|
async function send(topicName, payload, options) {
|
|
939
930
|
const transport = options?.transport || new JsonTransport();
|
|
940
931
|
const client = QueueClient._getDefaultInstance();
|
|
@@ -951,7 +942,8 @@ async function send(topicName, payload, options) {
|
|
|
951
942
|
}
|
|
952
943
|
async function receive(topicName, consumerGroup, handler, options) {
|
|
953
944
|
const transport = options?.transport || new JsonTransport();
|
|
954
|
-
const
|
|
945
|
+
const client = QueueClient._getDefaultInstance();
|
|
946
|
+
const topic = new Topic(client, topicName, transport);
|
|
955
947
|
const { messageId, skipPayload, ...consumerGroupOptions } = options || {};
|
|
956
948
|
const consumer = topic.consumerGroup(consumerGroup, consumerGroupOptions);
|
|
957
949
|
if (messageId) {
|
|
@@ -969,19 +961,38 @@ async function receive(topicName, consumerGroup, handler, options) {
|
|
|
969
961
|
}
|
|
970
962
|
|
|
971
963
|
// src/callback.ts
|
|
972
|
-
function parseCallbackRequest(request) {
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
964
|
+
async function parseCallbackRequest(request) {
|
|
965
|
+
const contentType = request.headers.get("content-type");
|
|
966
|
+
if (!contentType || !contentType.includes("application/cloudevents+json")) {
|
|
967
|
+
throw new Error(
|
|
968
|
+
"Invalid content type: expected 'application/cloudevents+json'"
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
let cloudEvent;
|
|
972
|
+
try {
|
|
973
|
+
cloudEvent = await request.json();
|
|
974
|
+
} catch (error) {
|
|
975
|
+
throw new Error("Failed to parse CloudEvent from request body");
|
|
976
|
+
}
|
|
977
|
+
if (!cloudEvent.type || !cloudEvent.source || !cloudEvent.id || typeof cloudEvent.data !== "object" || cloudEvent.data == null) {
|
|
978
|
+
throw new Error("Invalid CloudEvent: missing required fields");
|
|
979
|
+
}
|
|
980
|
+
if (cloudEvent.type !== "com.vercel.queue.v1beta") {
|
|
981
|
+
throw new Error(
|
|
982
|
+
`Invalid CloudEvent type: expected 'com.vercel.queue.v1beta', got '${cloudEvent.type}'`
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
const missingFields = [];
|
|
986
|
+
if (!("queueName" in cloudEvent.data)) missingFields.push("queueName");
|
|
987
|
+
if (!("consumerGroup" in cloudEvent.data))
|
|
988
|
+
missingFields.push("consumerGroup");
|
|
989
|
+
if (!("messageId" in cloudEvent.data)) missingFields.push("messageId");
|
|
990
|
+
if (missingFields.length > 0) {
|
|
981
991
|
throw new Error(
|
|
982
|
-
`Missing required
|
|
992
|
+
`Missing required CloudEvent data fields: ${missingFields.join(", ")}`
|
|
983
993
|
);
|
|
984
994
|
}
|
|
995
|
+
const { messageId, queueName, consumerGroup } = cloudEvent.data;
|
|
985
996
|
return {
|
|
986
997
|
queueName,
|
|
987
998
|
consumerGroup,
|
|
@@ -991,7 +1002,7 @@ function parseCallbackRequest(request) {
|
|
|
991
1002
|
function handleCallback(handlers) {
|
|
992
1003
|
return async (request) => {
|
|
993
1004
|
try {
|
|
994
|
-
const { queueName, consumerGroup, messageId } = parseCallbackRequest(request);
|
|
1005
|
+
const { queueName, consumerGroup, messageId } = await parseCallbackRequest(request);
|
|
995
1006
|
const topicHandler = handlers[queueName];
|
|
996
1007
|
if (!topicHandler) {
|
|
997
1008
|
const availableTopics = Object.keys(handlers).join(", ");
|
|
@@ -1021,7 +1032,7 @@ function handleCallback(handlers) {
|
|
|
1021
1032
|
return Response.json({ status: "success" });
|
|
1022
1033
|
} catch (error) {
|
|
1023
1034
|
console.error("Queue callback error:", error);
|
|
1024
|
-
if (error instanceof Error && error.message.includes("Missing required
|
|
1035
|
+
if (error instanceof Error && (error.message.includes("Missing required CloudEvent data fields") || error.message.includes("Invalid CloudEvent") || error.message.includes("Invalid CloudEvent type") || error.message.includes("Invalid content type") || error.message.includes("Failed to parse CloudEvent"))) {
|
|
1025
1036
|
return Response.json({ error: error.message }, { status: 400 });
|
|
1026
1037
|
}
|
|
1027
1038
|
return Response.json(
|
|
@@ -1035,7 +1046,6 @@ function handleCallback(handlers) {
|
|
|
1035
1046
|
0 && (module.exports = {
|
|
1036
1047
|
BadRequestError,
|
|
1037
1048
|
BufferTransport,
|
|
1038
|
-
ConsumerGroup,
|
|
1039
1049
|
ForbiddenError,
|
|
1040
1050
|
InternalServerError,
|
|
1041
1051
|
InvalidLimitError,
|
|
@@ -1044,14 +1054,10 @@ function handleCallback(handlers) {
|
|
|
1044
1054
|
MessageLockedError,
|
|
1045
1055
|
MessageNotAvailableError,
|
|
1046
1056
|
MessageNotFoundError,
|
|
1047
|
-
QueueClient,
|
|
1048
1057
|
QueueEmptyError,
|
|
1049
1058
|
StreamTransport,
|
|
1050
|
-
Topic,
|
|
1051
1059
|
UnauthorizedError,
|
|
1052
|
-
createTopic,
|
|
1053
1060
|
handleCallback,
|
|
1054
|
-
parseCallbackRequest,
|
|
1055
1061
|
receive,
|
|
1056
1062
|
send
|
|
1057
1063
|
});
|