@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/dist/index.mjs CHANGED
@@ -1,3 +1,75 @@
1
+ // src/transports.ts
2
+ var JsonTransport = class {
3
+ contentType = "application/json";
4
+ serialize(value) {
5
+ return Buffer.from(JSON.stringify(value), "utf8");
6
+ }
7
+ async deserialize(stream) {
8
+ const reader = stream.getReader();
9
+ let totalLength = 0;
10
+ const chunks = [];
11
+ try {
12
+ while (true) {
13
+ const { done, value } = await reader.read();
14
+ if (done) break;
15
+ chunks.push(value);
16
+ totalLength += value.length;
17
+ }
18
+ } finally {
19
+ reader.releaseLock();
20
+ }
21
+ const buffer = Buffer.concat(chunks, totalLength);
22
+ return JSON.parse(buffer.toString("utf8"));
23
+ }
24
+ };
25
+ var BufferTransport = class {
26
+ contentType = "application/octet-stream";
27
+ serialize(value) {
28
+ return value;
29
+ }
30
+ async deserialize(stream) {
31
+ const reader = stream.getReader();
32
+ const chunks = [];
33
+ try {
34
+ while (true) {
35
+ const { done, value } = await reader.read();
36
+ if (done) break;
37
+ chunks.push(value);
38
+ }
39
+ } finally {
40
+ reader.releaseLock();
41
+ }
42
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
43
+ const buffer = new Uint8Array(totalLength);
44
+ let offset = 0;
45
+ for (const chunk of chunks) {
46
+ buffer.set(chunk, offset);
47
+ offset += chunk.length;
48
+ }
49
+ return Buffer.from(buffer);
50
+ }
51
+ };
52
+ var StreamTransport = class {
53
+ contentType = "application/octet-stream";
54
+ serialize(value) {
55
+ return value;
56
+ }
57
+ async deserialize(stream) {
58
+ return stream;
59
+ }
60
+ async finalize(payload) {
61
+ const reader = payload.getReader();
62
+ try {
63
+ while (true) {
64
+ const { done } = await reader.read();
65
+ if (done) break;
66
+ }
67
+ } finally {
68
+ reader.releaseLock();
69
+ }
70
+ }
71
+ };
72
+
1
73
  // src/client.ts
2
74
  import { parseMultipartStream } from "mixpart";
3
75
 
@@ -107,7 +179,7 @@ var QueueClient = class _QueueClient {
107
179
  baseUrl;
108
180
  token;
109
181
  /**
110
- * Internal default instance for use by createTopic and other convenience functions
182
+ * Internal default instance for use by convenience functions
111
183
  * @internal
112
184
  */
113
185
  static _defaultInstance = null;
@@ -543,78 +615,6 @@ var QueueClient = class _QueueClient {
543
615
  }
544
616
  };
545
617
 
546
- // src/transports.ts
547
- var JsonTransport = class {
548
- contentType = "application/json";
549
- serialize(value) {
550
- return Buffer.from(JSON.stringify(value), "utf8");
551
- }
552
- async deserialize(stream) {
553
- const reader = stream.getReader();
554
- let totalLength = 0;
555
- const chunks = [];
556
- try {
557
- while (true) {
558
- const { done, value } = await reader.read();
559
- if (done) break;
560
- chunks.push(value);
561
- totalLength += value.length;
562
- }
563
- } finally {
564
- reader.releaseLock();
565
- }
566
- const buffer = Buffer.concat(chunks, totalLength);
567
- return JSON.parse(buffer.toString("utf8"));
568
- }
569
- };
570
- var BufferTransport = class {
571
- contentType = "application/octet-stream";
572
- serialize(value) {
573
- return value;
574
- }
575
- async deserialize(stream) {
576
- const reader = stream.getReader();
577
- const chunks = [];
578
- try {
579
- while (true) {
580
- const { done, value } = await reader.read();
581
- if (done) break;
582
- chunks.push(value);
583
- }
584
- } finally {
585
- reader.releaseLock();
586
- }
587
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
588
- const buffer = new Uint8Array(totalLength);
589
- let offset = 0;
590
- for (const chunk of chunks) {
591
- buffer.set(chunk, offset);
592
- offset += chunk.length;
593
- }
594
- return Buffer.from(buffer);
595
- }
596
- };
597
- var StreamTransport = class {
598
- contentType = "application/octet-stream";
599
- serialize(value) {
600
- return value;
601
- }
602
- async deserialize(stream) {
603
- return stream;
604
- }
605
- async finalize(payload) {
606
- const reader = payload.getReader();
607
- try {
608
- while (true) {
609
- const { done } = await reader.read();
610
- if (done) break;
611
- }
612
- } finally {
613
- reader.releaseLock();
614
- }
615
- }
616
- };
617
-
618
618
  // src/consumer-group.ts
619
619
  var ConsumerGroup = class {
620
620
  client;
@@ -885,10 +885,6 @@ var Topic = class {
885
885
  };
886
886
 
887
887
  // src/factory.ts
888
- function createTopic(topicName, transport) {
889
- const client = QueueClient._getDefaultInstance();
890
- return new Topic(client, topicName, transport);
891
- }
892
888
  async function send(topicName, payload, options) {
893
889
  const transport = options?.transport || new JsonTransport();
894
890
  const client = QueueClient._getDefaultInstance();
@@ -905,7 +901,8 @@ async function send(topicName, payload, options) {
905
901
  }
906
902
  async function receive(topicName, consumerGroup, handler, options) {
907
903
  const transport = options?.transport || new JsonTransport();
908
- const topic = createTopic(topicName, transport);
904
+ const client = QueueClient._getDefaultInstance();
905
+ const topic = new Topic(client, topicName, transport);
909
906
  const { messageId, skipPayload, ...consumerGroupOptions } = options || {};
910
907
  const consumer = topic.consumerGroup(consumerGroup, consumerGroupOptions);
911
908
  if (messageId) {
@@ -923,19 +920,38 @@ async function receive(topicName, consumerGroup, handler, options) {
923
920
  }
924
921
 
925
922
  // src/callback.ts
926
- function parseCallbackRequest(request) {
927
- const queueName = request.headers.get("Vqs-Queue-Name");
928
- const consumerGroup = request.headers.get("Vqs-Consumer-Group");
929
- const messageId = request.headers.get("Vqs-Message-Id");
930
- if (!queueName || !consumerGroup || !messageId) {
931
- const missingHeaders = [];
932
- if (!queueName) missingHeaders.push("Vqs-Queue-Name");
933
- if (!consumerGroup) missingHeaders.push("Vqs-Consumer-Group");
934
- if (!messageId) missingHeaders.push("Vqs-Message-Id");
923
+ async function parseCallbackRequest(request) {
924
+ const contentType = request.headers.get("content-type");
925
+ if (!contentType || !contentType.includes("application/cloudevents+json")) {
926
+ throw new Error(
927
+ "Invalid content type: expected 'application/cloudevents+json'"
928
+ );
929
+ }
930
+ let cloudEvent;
931
+ try {
932
+ cloudEvent = await request.json();
933
+ } catch (error) {
934
+ throw new Error("Failed to parse CloudEvent from request body");
935
+ }
936
+ if (!cloudEvent.type || !cloudEvent.source || !cloudEvent.id || typeof cloudEvent.data !== "object" || cloudEvent.data == null) {
937
+ throw new Error("Invalid CloudEvent: missing required fields");
938
+ }
939
+ if (cloudEvent.type !== "com.vercel.queue.v1beta") {
940
+ throw new Error(
941
+ `Invalid CloudEvent type: expected 'com.vercel.queue.v1beta', got '${cloudEvent.type}'`
942
+ );
943
+ }
944
+ const missingFields = [];
945
+ if (!("queueName" in cloudEvent.data)) missingFields.push("queueName");
946
+ if (!("consumerGroup" in cloudEvent.data))
947
+ missingFields.push("consumerGroup");
948
+ if (!("messageId" in cloudEvent.data)) missingFields.push("messageId");
949
+ if (missingFields.length > 0) {
935
950
  throw new Error(
936
- `Missing required queue headers: ${missingHeaders.join(", ")}`
951
+ `Missing required CloudEvent data fields: ${missingFields.join(", ")}`
937
952
  );
938
953
  }
954
+ const { messageId, queueName, consumerGroup } = cloudEvent.data;
939
955
  return {
940
956
  queueName,
941
957
  consumerGroup,
@@ -945,7 +961,7 @@ function parseCallbackRequest(request) {
945
961
  function handleCallback(handlers) {
946
962
  return async (request) => {
947
963
  try {
948
- const { queueName, consumerGroup, messageId } = parseCallbackRequest(request);
964
+ const { queueName, consumerGroup, messageId } = await parseCallbackRequest(request);
949
965
  const topicHandler = handlers[queueName];
950
966
  if (!topicHandler) {
951
967
  const availableTopics = Object.keys(handlers).join(", ");
@@ -975,7 +991,7 @@ function handleCallback(handlers) {
975
991
  return Response.json({ status: "success" });
976
992
  } catch (error) {
977
993
  console.error("Queue callback error:", error);
978
- if (error instanceof Error && error.message.includes("Missing required queue headers")) {
994
+ 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"))) {
979
995
  return Response.json({ error: error.message }, { status: 400 });
980
996
  }
981
997
  return Response.json(
@@ -988,7 +1004,6 @@ function handleCallback(handlers) {
988
1004
  export {
989
1005
  BadRequestError,
990
1006
  BufferTransport,
991
- ConsumerGroup,
992
1007
  ForbiddenError,
993
1008
  InternalServerError,
994
1009
  InvalidLimitError,
@@ -997,14 +1012,10 @@ export {
997
1012
  MessageLockedError,
998
1013
  MessageNotAvailableError,
999
1014
  MessageNotFoundError,
1000
- QueueClient,
1001
1015
  QueueEmptyError,
1002
1016
  StreamTransport,
1003
- Topic,
1004
1017
  UnauthorizedError,
1005
- createTopic,
1006
1018
  handleCallback,
1007
- parseCallbackRequest,
1008
1019
  receive,
1009
1020
  send
1010
1021
  };