@vercel/queue 0.0.1 → 0.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/README.md +91 -61
- package/dist/index.d.mts +148 -42
- package/dist/index.d.ts +148 -42
- package/dist/index.js +130 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +129 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -964,7 +964,7 @@ function parseQueueHeaders(headers) {
|
|
|
964
964
|
receiptHandle
|
|
965
965
|
};
|
|
966
966
|
}
|
|
967
|
-
var DEFAULT_BASE_URL_RESOLVER = (region) => `https://${region}.vercel-queue.com
|
|
967
|
+
var DEFAULT_BASE_URL_RESOLVER = (region) => new URL(`https://${region}.vercel-queue.com`);
|
|
968
968
|
function resolveBaseUrl(region, resolver) {
|
|
969
969
|
return (resolver ?? DEFAULT_BASE_URL_RESOLVER)(region);
|
|
970
970
|
}
|
|
@@ -1022,7 +1022,7 @@ var ApiClient = class _ApiClient {
|
|
|
1022
1022
|
return;
|
|
1023
1023
|
}
|
|
1024
1024
|
throw new Error(
|
|
1025
|
-
'No deployment ID available. VERCEL_DEPLOYMENT_ID is not set.\n\nThis usually means the code is running outside a Vercel deployment (e.g. during build or in a non-Vercel environment).\n\nTo fix this, create a
|
|
1025
|
+
'No deployment ID available. VERCEL_DEPLOYMENT_ID is not set.\n\nThis usually means the code is running outside a Vercel deployment (e.g. during build or in a non-Vercel environment).\n\nTo fix this, create a client with an explicit deploymentId:\n new QueueClient({ deploymentId: "dpl_xxx" })\nOr explicitly opt out of deployment pinning:\n new QueueClient({ deploymentId: null })'
|
|
1026
1026
|
);
|
|
1027
1027
|
}
|
|
1028
1028
|
getSendDeploymentId() {
|
|
@@ -1055,7 +1055,8 @@ var ApiClient = class _ApiClient {
|
|
|
1055
1055
|
const encodedQueue = encodeURIComponent(queueName);
|
|
1056
1056
|
const segments = pathSegments.map((s) => encodeURIComponent(s));
|
|
1057
1057
|
const path2 = segments.length > 0 ? "/" + segments.join("/") : "";
|
|
1058
|
-
|
|
1058
|
+
const basePath = this.baseUrl.pathname.replace(/\/+$/, "");
|
|
1059
|
+
return `${this.baseUrl.origin}${basePath}${BASE_PATH}/${encodedQueue}${path2}`;
|
|
1059
1060
|
}
|
|
1060
1061
|
async fetch(url, init) {
|
|
1061
1062
|
const method = init.method || "GET";
|
|
@@ -1079,7 +1080,7 @@ var ApiClient = class _ApiClient {
|
|
|
1079
1080
|
}
|
|
1080
1081
|
console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
|
|
1081
1082
|
}
|
|
1082
|
-
init.headers.set("User-Agent", `@vercel/queue/${"0.0
|
|
1083
|
+
init.headers.set("User-Agent", `@vercel/queue/${"0.1.0"}`);
|
|
1083
1084
|
init.headers.set("Vqs-Client-Ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
1084
1085
|
const response = await fetch(url, init);
|
|
1085
1086
|
if (isDebugEnabled()) {
|
|
@@ -1415,23 +1416,37 @@ var ApiClient = class _ApiClient {
|
|
|
1415
1416
|
|
|
1416
1417
|
// src/client.ts
|
|
1417
1418
|
var apiClients = /* @__PURE__ */ new WeakMap();
|
|
1418
|
-
function
|
|
1419
|
+
function getApi(client) {
|
|
1419
1420
|
const api = apiClients.get(client);
|
|
1420
1421
|
if (!api) {
|
|
1421
|
-
throw new Error("
|
|
1422
|
+
throw new Error("Client not initialized");
|
|
1422
1423
|
}
|
|
1423
1424
|
return api;
|
|
1424
1425
|
}
|
|
1426
|
+
function getApiClient(client) {
|
|
1427
|
+
return getApi(client);
|
|
1428
|
+
}
|
|
1429
|
+
var DEFAULT_REGION = "iad1";
|
|
1430
|
+
function resolveRegion(region) {
|
|
1431
|
+
if (region) return region;
|
|
1432
|
+
const fromEnv = process.env.VERCEL_REGION;
|
|
1433
|
+
if (fromEnv) return fromEnv;
|
|
1434
|
+
console.warn(
|
|
1435
|
+
`[QueueClient] Region not detected \u2014 defaulting to "${DEFAULT_REGION}". On Vercel this is set automatically via VERCEL_REGION. To silence this warning, pass region explicitly: new QueueClient({ region: "iad1" })`
|
|
1436
|
+
);
|
|
1437
|
+
return DEFAULT_REGION;
|
|
1438
|
+
}
|
|
1425
1439
|
var QueueClient = class {
|
|
1426
|
-
constructor(options) {
|
|
1427
|
-
|
|
1440
|
+
constructor(options = {}) {
|
|
1441
|
+
const region = resolveRegion(options.region);
|
|
1442
|
+
apiClients.set(this, new ApiClient({ ...options, region }));
|
|
1428
1443
|
}
|
|
1429
1444
|
/**
|
|
1430
1445
|
* Send a message to a topic.
|
|
1431
1446
|
*
|
|
1432
1447
|
* This is an arrow function property so it can be destructured:
|
|
1433
1448
|
* ```typescript
|
|
1434
|
-
* const { send } = new QueueClient(
|
|
1449
|
+
* const { send } = new QueueClient();
|
|
1435
1450
|
* await send("my-topic", payload);
|
|
1436
1451
|
* ```
|
|
1437
1452
|
*
|
|
@@ -1442,7 +1457,7 @@ var QueueClient = class {
|
|
|
1442
1457
|
* the message for deferred processing (no ID available yet)
|
|
1443
1458
|
*/
|
|
1444
1459
|
send = async (topicName, payload, options) => {
|
|
1445
|
-
const api =
|
|
1460
|
+
const api = getApi(this);
|
|
1446
1461
|
const result = await api.sendMessage({
|
|
1447
1462
|
queueName: topicName,
|
|
1448
1463
|
payload,
|
|
@@ -1461,75 +1476,6 @@ var QueueClient = class {
|
|
|
1461
1476
|
}
|
|
1462
1477
|
return { messageId: result.messageId };
|
|
1463
1478
|
};
|
|
1464
|
-
/**
|
|
1465
|
-
* Receive and process messages from a topic.
|
|
1466
|
-
*
|
|
1467
|
-
* Each message is automatically locked, kept alive via periodic visibility
|
|
1468
|
-
* extensions during processing, and acknowledged upon successful handler completion.
|
|
1469
|
-
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
1470
|
-
*
|
|
1471
|
-
* This is an arrow function property so it can be destructured:
|
|
1472
|
-
* ```typescript
|
|
1473
|
-
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
1474
|
-
* const result = await receive("my-topic", "my-group", handler);
|
|
1475
|
-
* if (!result.ok) console.log(result.reason);
|
|
1476
|
-
* ```
|
|
1477
|
-
*
|
|
1478
|
-
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1479
|
-
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1480
|
-
* @param handler - Function to process each message payload and metadata.
|
|
1481
|
-
* Not called when the queue is empty.
|
|
1482
|
-
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
1483
|
-
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
1484
|
-
*/
|
|
1485
|
-
receive = async (topicName, consumerGroup, handler, options) => {
|
|
1486
|
-
const api = getApiClient(this);
|
|
1487
|
-
const topic = new Topic(api, topicName);
|
|
1488
|
-
const visibilityTimeoutSeconds = options && "visibilityTimeoutSeconds" in options ? options.visibilityTimeoutSeconds : void 0;
|
|
1489
|
-
const consumer = topic.consumerGroup(
|
|
1490
|
-
consumerGroup,
|
|
1491
|
-
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : {}
|
|
1492
|
-
);
|
|
1493
|
-
try {
|
|
1494
|
-
let count;
|
|
1495
|
-
const retry = options?.retry;
|
|
1496
|
-
if (options && "messageId" in options) {
|
|
1497
|
-
count = await consumer.consume(handler, {
|
|
1498
|
-
messageId: options.messageId,
|
|
1499
|
-
retry
|
|
1500
|
-
});
|
|
1501
|
-
} else {
|
|
1502
|
-
const limit = options && "limit" in options ? options.limit : void 0;
|
|
1503
|
-
count = await consumer.consume(handler, {
|
|
1504
|
-
...limit !== void 0 ? { limit } : {},
|
|
1505
|
-
retry
|
|
1506
|
-
});
|
|
1507
|
-
}
|
|
1508
|
-
if (count === 0) {
|
|
1509
|
-
return { ok: false, reason: "empty" };
|
|
1510
|
-
}
|
|
1511
|
-
return { ok: true };
|
|
1512
|
-
} catch (error) {
|
|
1513
|
-
if (options && "messageId" in options && error instanceof MessageNotFoundError) {
|
|
1514
|
-
return { ok: false, reason: "not_found", messageId: options.messageId };
|
|
1515
|
-
}
|
|
1516
|
-
if (options && "messageId" in options && error instanceof MessageNotAvailableError) {
|
|
1517
|
-
return {
|
|
1518
|
-
ok: false,
|
|
1519
|
-
reason: "not_available",
|
|
1520
|
-
messageId: options.messageId
|
|
1521
|
-
};
|
|
1522
|
-
}
|
|
1523
|
-
if (options && "messageId" in options && error instanceof MessageAlreadyProcessedError) {
|
|
1524
|
-
return {
|
|
1525
|
-
ok: false,
|
|
1526
|
-
reason: "already_processed",
|
|
1527
|
-
messageId: options.messageId
|
|
1528
|
-
};
|
|
1529
|
-
}
|
|
1530
|
-
throw error;
|
|
1531
|
-
}
|
|
1532
|
-
};
|
|
1533
1479
|
/**
|
|
1534
1480
|
* Create a Web API route handler for processing queue callback messages.
|
|
1535
1481
|
*
|
|
@@ -1538,7 +1484,7 @@ var QueueClient = class {
|
|
|
1538
1484
|
*
|
|
1539
1485
|
* This is an arrow function property so it can be destructured:
|
|
1540
1486
|
* ```typescript
|
|
1541
|
-
* const { handleCallback } = new QueueClient(
|
|
1487
|
+
* const { handleCallback } = new QueueClient();
|
|
1542
1488
|
* export const POST = handleCallback(handler);
|
|
1543
1489
|
* ```
|
|
1544
1490
|
*
|
|
@@ -1580,7 +1526,7 @@ var QueueClient = class {
|
|
|
1580
1526
|
*
|
|
1581
1527
|
* This is an arrow function property so it can be destructured:
|
|
1582
1528
|
* ```typescript
|
|
1583
|
-
* const { handleNodeCallback } = new QueueClient(
|
|
1529
|
+
* const { handleNodeCallback } = new QueueClient();
|
|
1584
1530
|
* app.post("/api/queue", handleNodeCallback(handler));
|
|
1585
1531
|
* ```
|
|
1586
1532
|
*
|
|
@@ -1616,6 +1562,107 @@ var QueueClient = class {
|
|
|
1616
1562
|
};
|
|
1617
1563
|
};
|
|
1618
1564
|
};
|
|
1565
|
+
var PollingQueueClient = class {
|
|
1566
|
+
constructor(options) {
|
|
1567
|
+
apiClients.set(this, new ApiClient(options));
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Send a message to a topic.
|
|
1571
|
+
*
|
|
1572
|
+
* This is an arrow function property so it can be destructured:
|
|
1573
|
+
* ```typescript
|
|
1574
|
+
* const { send } = new PollingQueueClient({ region: "iad1" });
|
|
1575
|
+
* await send("my-topic", payload);
|
|
1576
|
+
* ```
|
|
1577
|
+
*
|
|
1578
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1579
|
+
* @param payload - The data to send (serialized via the configured transport)
|
|
1580
|
+
* @param options - Optional send options (idempotencyKey, retentionSeconds, delaySeconds, headers)
|
|
1581
|
+
* @returns `{ messageId }` — `messageId` is `null` when the server accepted
|
|
1582
|
+
* the message for deferred processing (no ID available yet)
|
|
1583
|
+
*/
|
|
1584
|
+
send = async (topicName, payload, options) => {
|
|
1585
|
+
const api = getApi(this);
|
|
1586
|
+
const result = await api.sendMessage({
|
|
1587
|
+
queueName: topicName,
|
|
1588
|
+
payload,
|
|
1589
|
+
idempotencyKey: options?.idempotencyKey,
|
|
1590
|
+
retentionSeconds: options?.retentionSeconds,
|
|
1591
|
+
delaySeconds: options?.delaySeconds,
|
|
1592
|
+
headers: options?.headers
|
|
1593
|
+
});
|
|
1594
|
+
return { messageId: result.messageId };
|
|
1595
|
+
};
|
|
1596
|
+
/**
|
|
1597
|
+
* Receive and process messages from a topic.
|
|
1598
|
+
*
|
|
1599
|
+
* Each message is automatically locked, kept alive via periodic visibility
|
|
1600
|
+
* extensions during processing, and acknowledged upon successful handler completion.
|
|
1601
|
+
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
1602
|
+
*
|
|
1603
|
+
* This is an arrow function property so it can be destructured:
|
|
1604
|
+
* ```typescript
|
|
1605
|
+
* const { receive } = new PollingQueueClient({ region: "iad1" });
|
|
1606
|
+
* const result = await receive("my-topic", "my-group", handler);
|
|
1607
|
+
* if (!result.ok) console.log(result.reason);
|
|
1608
|
+
* ```
|
|
1609
|
+
*
|
|
1610
|
+
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1611
|
+
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1612
|
+
* @param handler - Function to process each message payload and metadata.
|
|
1613
|
+
* Not called when the queue is empty.
|
|
1614
|
+
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
1615
|
+
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
1616
|
+
*/
|
|
1617
|
+
receive = async (topicName, consumerGroup, handler, options) => {
|
|
1618
|
+
const api = getApi(this);
|
|
1619
|
+
const topic = new Topic(api, topicName);
|
|
1620
|
+
const visibilityTimeoutSeconds = options && "visibilityTimeoutSeconds" in options ? options.visibilityTimeoutSeconds : void 0;
|
|
1621
|
+
const consumer = topic.consumerGroup(
|
|
1622
|
+
consumerGroup,
|
|
1623
|
+
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : {}
|
|
1624
|
+
);
|
|
1625
|
+
try {
|
|
1626
|
+
let count;
|
|
1627
|
+
const retry = options?.retry;
|
|
1628
|
+
if (options && "messageId" in options) {
|
|
1629
|
+
count = await consumer.consume(handler, {
|
|
1630
|
+
messageId: options.messageId,
|
|
1631
|
+
retry
|
|
1632
|
+
});
|
|
1633
|
+
} else {
|
|
1634
|
+
const limit = options && "limit" in options ? options.limit : void 0;
|
|
1635
|
+
count = await consumer.consume(handler, {
|
|
1636
|
+
...limit !== void 0 ? { limit } : {},
|
|
1637
|
+
retry
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
if (count === 0) {
|
|
1641
|
+
return { ok: false, reason: "empty" };
|
|
1642
|
+
}
|
|
1643
|
+
return { ok: true };
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
if (options && "messageId" in options && error instanceof MessageNotFoundError) {
|
|
1646
|
+
return { ok: false, reason: "not_found", messageId: options.messageId };
|
|
1647
|
+
}
|
|
1648
|
+
if (options && "messageId" in options && error instanceof MessageNotAvailableError) {
|
|
1649
|
+
return {
|
|
1650
|
+
ok: false,
|
|
1651
|
+
reason: "not_available",
|
|
1652
|
+
messageId: options.messageId
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
if (options && "messageId" in options && error instanceof MessageAlreadyProcessedError) {
|
|
1656
|
+
return {
|
|
1657
|
+
ok: false,
|
|
1658
|
+
reason: "already_processed",
|
|
1659
|
+
messageId: options.messageId
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
throw error;
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
};
|
|
1619
1666
|
export {
|
|
1620
1667
|
BadRequestError,
|
|
1621
1668
|
BufferTransport,
|
|
@@ -1633,6 +1680,7 @@ export {
|
|
|
1633
1680
|
MessageLockedError,
|
|
1634
1681
|
MessageNotAvailableError,
|
|
1635
1682
|
MessageNotFoundError,
|
|
1683
|
+
PollingQueueClient,
|
|
1636
1684
|
QueueClient,
|
|
1637
1685
|
QueueEmptyError,
|
|
1638
1686
|
StreamTransport,
|