@vercel/queue 0.0.2 → 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 +78 -59
- package/dist/index.d.mts +122 -37
- package/dist/index.d.ts +122 -37
- package/dist/index.js +127 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +126 -79
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -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() {
|
|
@@ -1080,7 +1080,7 @@ var ApiClient = class _ApiClient {
|
|
|
1080
1080
|
}
|
|
1081
1081
|
console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
|
|
1082
1082
|
}
|
|
1083
|
-
init.headers.set("User-Agent", `@vercel/queue/${"0.0
|
|
1083
|
+
init.headers.set("User-Agent", `@vercel/queue/${"0.1.0"}`);
|
|
1084
1084
|
init.headers.set("Vqs-Client-Ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
1085
1085
|
const response = await fetch(url, init);
|
|
1086
1086
|
if (isDebugEnabled()) {
|
|
@@ -1416,23 +1416,37 @@ var ApiClient = class _ApiClient {
|
|
|
1416
1416
|
|
|
1417
1417
|
// src/client.ts
|
|
1418
1418
|
var apiClients = /* @__PURE__ */ new WeakMap();
|
|
1419
|
-
function
|
|
1419
|
+
function getApi(client) {
|
|
1420
1420
|
const api = apiClients.get(client);
|
|
1421
1421
|
if (!api) {
|
|
1422
|
-
throw new Error("
|
|
1422
|
+
throw new Error("Client not initialized");
|
|
1423
1423
|
}
|
|
1424
1424
|
return api;
|
|
1425
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
|
+
}
|
|
1426
1439
|
var QueueClient = class {
|
|
1427
|
-
constructor(options) {
|
|
1428
|
-
|
|
1440
|
+
constructor(options = {}) {
|
|
1441
|
+
const region = resolveRegion(options.region);
|
|
1442
|
+
apiClients.set(this, new ApiClient({ ...options, region }));
|
|
1429
1443
|
}
|
|
1430
1444
|
/**
|
|
1431
1445
|
* Send a message to a topic.
|
|
1432
1446
|
*
|
|
1433
1447
|
* This is an arrow function property so it can be destructured:
|
|
1434
1448
|
* ```typescript
|
|
1435
|
-
* const { send } = new QueueClient(
|
|
1449
|
+
* const { send } = new QueueClient();
|
|
1436
1450
|
* await send("my-topic", payload);
|
|
1437
1451
|
* ```
|
|
1438
1452
|
*
|
|
@@ -1443,7 +1457,7 @@ var QueueClient = class {
|
|
|
1443
1457
|
* the message for deferred processing (no ID available yet)
|
|
1444
1458
|
*/
|
|
1445
1459
|
send = async (topicName, payload, options) => {
|
|
1446
|
-
const api =
|
|
1460
|
+
const api = getApi(this);
|
|
1447
1461
|
const result = await api.sendMessage({
|
|
1448
1462
|
queueName: topicName,
|
|
1449
1463
|
payload,
|
|
@@ -1462,75 +1476,6 @@ var QueueClient = class {
|
|
|
1462
1476
|
}
|
|
1463
1477
|
return { messageId: result.messageId };
|
|
1464
1478
|
};
|
|
1465
|
-
/**
|
|
1466
|
-
* Receive and process messages from a topic.
|
|
1467
|
-
*
|
|
1468
|
-
* Each message is automatically locked, kept alive via periodic visibility
|
|
1469
|
-
* extensions during processing, and acknowledged upon successful handler completion.
|
|
1470
|
-
* The handler is not called when the queue is empty — check `result.ok` instead.
|
|
1471
|
-
*
|
|
1472
|
-
* This is an arrow function property so it can be destructured:
|
|
1473
|
-
* ```typescript
|
|
1474
|
-
* const { receive } = new QueueClient({ region: process.env.QUEUE_REGION! });
|
|
1475
|
-
* const result = await receive("my-topic", "my-group", handler);
|
|
1476
|
-
* if (!result.ok) console.log(result.reason);
|
|
1477
|
-
* ```
|
|
1478
|
-
*
|
|
1479
|
-
* @param topicName - Name of the topic (pattern: `[A-Za-z0-9_-]+`)
|
|
1480
|
-
* @param consumerGroup - Name of the consumer group (pattern: `[A-Za-z0-9_-]+`)
|
|
1481
|
-
* @param handler - Function to process each message payload and metadata.
|
|
1482
|
-
* Not called when the queue is empty.
|
|
1483
|
-
* @param options - Optional receive options (visibilityTimeoutSeconds, limit, or messageId)
|
|
1484
|
-
* @returns Discriminated result: `{ ok: true }` on success, `{ ok: false, reason }` otherwise
|
|
1485
|
-
*/
|
|
1486
|
-
receive = async (topicName, consumerGroup, handler, options) => {
|
|
1487
|
-
const api = getApiClient(this);
|
|
1488
|
-
const topic = new Topic(api, topicName);
|
|
1489
|
-
const visibilityTimeoutSeconds = options && "visibilityTimeoutSeconds" in options ? options.visibilityTimeoutSeconds : void 0;
|
|
1490
|
-
const consumer = topic.consumerGroup(
|
|
1491
|
-
consumerGroup,
|
|
1492
|
-
visibilityTimeoutSeconds !== void 0 ? { visibilityTimeoutSeconds } : {}
|
|
1493
|
-
);
|
|
1494
|
-
try {
|
|
1495
|
-
let count;
|
|
1496
|
-
const retry = options?.retry;
|
|
1497
|
-
if (options && "messageId" in options) {
|
|
1498
|
-
count = await consumer.consume(handler, {
|
|
1499
|
-
messageId: options.messageId,
|
|
1500
|
-
retry
|
|
1501
|
-
});
|
|
1502
|
-
} else {
|
|
1503
|
-
const limit = options && "limit" in options ? options.limit : void 0;
|
|
1504
|
-
count = await consumer.consume(handler, {
|
|
1505
|
-
...limit !== void 0 ? { limit } : {},
|
|
1506
|
-
retry
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
if (count === 0) {
|
|
1510
|
-
return { ok: false, reason: "empty" };
|
|
1511
|
-
}
|
|
1512
|
-
return { ok: true };
|
|
1513
|
-
} catch (error) {
|
|
1514
|
-
if (options && "messageId" in options && error instanceof MessageNotFoundError) {
|
|
1515
|
-
return { ok: false, reason: "not_found", messageId: options.messageId };
|
|
1516
|
-
}
|
|
1517
|
-
if (options && "messageId" in options && error instanceof MessageNotAvailableError) {
|
|
1518
|
-
return {
|
|
1519
|
-
ok: false,
|
|
1520
|
-
reason: "not_available",
|
|
1521
|
-
messageId: options.messageId
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
if (options && "messageId" in options && error instanceof MessageAlreadyProcessedError) {
|
|
1525
|
-
return {
|
|
1526
|
-
ok: false,
|
|
1527
|
-
reason: "already_processed",
|
|
1528
|
-
messageId: options.messageId
|
|
1529
|
-
};
|
|
1530
|
-
}
|
|
1531
|
-
throw error;
|
|
1532
|
-
}
|
|
1533
|
-
};
|
|
1534
1479
|
/**
|
|
1535
1480
|
* Create a Web API route handler for processing queue callback messages.
|
|
1536
1481
|
*
|
|
@@ -1539,7 +1484,7 @@ var QueueClient = class {
|
|
|
1539
1484
|
*
|
|
1540
1485
|
* This is an arrow function property so it can be destructured:
|
|
1541
1486
|
* ```typescript
|
|
1542
|
-
* const { handleCallback } = new QueueClient(
|
|
1487
|
+
* const { handleCallback } = new QueueClient();
|
|
1543
1488
|
* export const POST = handleCallback(handler);
|
|
1544
1489
|
* ```
|
|
1545
1490
|
*
|
|
@@ -1581,7 +1526,7 @@ var QueueClient = class {
|
|
|
1581
1526
|
*
|
|
1582
1527
|
* This is an arrow function property so it can be destructured:
|
|
1583
1528
|
* ```typescript
|
|
1584
|
-
* const { handleNodeCallback } = new QueueClient(
|
|
1529
|
+
* const { handleNodeCallback } = new QueueClient();
|
|
1585
1530
|
* app.post("/api/queue", handleNodeCallback(handler));
|
|
1586
1531
|
* ```
|
|
1587
1532
|
*
|
|
@@ -1617,6 +1562,107 @@ var QueueClient = class {
|
|
|
1617
1562
|
};
|
|
1618
1563
|
};
|
|
1619
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
|
+
};
|
|
1620
1666
|
export {
|
|
1621
1667
|
BadRequestError,
|
|
1622
1668
|
BufferTransport,
|
|
@@ -1634,6 +1680,7 @@ export {
|
|
|
1634
1680
|
MessageLockedError,
|
|
1635
1681
|
MessageNotAvailableError,
|
|
1636
1682
|
MessageNotFoundError,
|
|
1683
|
+
PollingQueueClient,
|
|
1637
1684
|
QueueClient,
|
|
1638
1685
|
QueueEmptyError,
|
|
1639
1686
|
StreamTransport,
|