@vercel/queue 0.1.2 → 0.1.4

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
@@ -79,6 +79,7 @@ import * as fs from "fs";
79
79
  import * as net from "net";
80
80
  import * as path from "path";
81
81
  import { minimatch } from "minimatch";
82
+ import pc from "picocolors";
82
83
 
83
84
  // src/types.ts
84
85
  var MessageNotFoundError = class extends Error {
@@ -708,6 +709,10 @@ async function handleCallback(handler, request, options) {
708
709
  }
709
710
 
710
711
  // src/dev.ts
712
+ var PREFIX = pc.cyan("[queue]");
713
+ var OK = pc.green("\u2713");
714
+ var FAIL = pc.red("\u2717");
715
+ var RETRY = pc.yellow("\u21BB");
711
716
  function isDevMode() {
712
717
  return process.env.NODE_ENV === "development";
713
718
  }
@@ -752,7 +757,7 @@ function getDevRouteMappings() {
752
757
  if (!trigger.type?.startsWith("queue/") || !trigger.topic) continue;
753
758
  if (trigger.type !== "queue/v2beta") {
754
759
  console.warn(
755
- `[Dev Mode] Unsupported trigger type "${trigger.type}" for topic "${trigger.topic}" in ${filePath}. Use "queue/v2beta" instead.`
760
+ `${PREFIX} Unsupported trigger type "${trigger.type}" for topic "${trigger.topic}" in ${filePath}. Use "queue/v2beta" instead.`
756
761
  );
757
762
  continue;
758
763
  }
@@ -767,7 +772,7 @@ function getDevRouteMappings() {
767
772
  g[ROUTE_MAPPINGS_KEY] = mappings.length > 0 ? mappings : null;
768
773
  return g[ROUTE_MAPPINGS_KEY];
769
774
  } catch (error) {
770
- console.warn("[Dev Mode] Failed to read vercel.json:", error);
775
+ console.warn(`${PREFIX} Failed to read vercel.json:`, error);
771
776
  g[ROUTE_MAPPINGS_KEY] = null;
772
777
  return null;
773
778
  }
@@ -904,7 +909,7 @@ function registerDevHandler(handler, client, options, _testCallerPath) {
904
909
  const callerPath = _testCallerPath ?? extractCallerFilePath();
905
910
  if (!callerPath) {
906
911
  console.warn(
907
- "[Dev Mode] Could not determine caller file path for handler registration."
912
+ `${PREFIX} Could not determine caller file path for handler registration.`
908
913
  );
909
914
  return;
910
915
  }
@@ -927,7 +932,7 @@ function registerDevHandler(handler, client, options, _testCallerPath) {
927
932
  relative2 = callerPath;
928
933
  }
929
934
  console.warn(
930
- `[Dev Mode] handleCallback() in ${relative2} has no matching experimentalTriggers in vercel.json. This handler won't receive messages.
935
+ `${PREFIX} handleCallback() in ${relative2} has no matching experimentalTriggers in vercel.json. This handler won't receive messages.
931
936
 
932
937
  Add a trigger to vercel.json:
933
938
  "${relative2}": {
@@ -1144,7 +1149,7 @@ function buildNoHandlerWarning(topicName, routes, diagnostics) {
1144
1149
  Import failures: ` + diagnostics.importFailures.slice(0, 2).map((f) => `${f.filePath} (${f.reason})`).join("; ") : "";
1145
1150
  const primeSummary = diagnostics.primeFailures.length > 0 ? `
1146
1151
  Prime failures: ` + diagnostics.primeFailures.slice(0, 3).map((f) => `${f.url} (${f.reason})`).join("; ") : "";
1147
- return `[Dev Mode] No registered handler for topic "${topicName}". vercel.json maps this topic to [${files.join(", ")}] but auto-loading failed.
1152
+ return `${PREFIX} No registered handler for topic "${topicName}". vercel.json maps this topic to [${files.join(", ")}] but auto-loading failed.
1148
1153
  ${portSummary}${importSummary}${primeSummary}
1149
1154
  Ensure your dev server is running, set PORT if needed, and confirm mapped route files call handleCallback()/handleNodeCallback() at module scope.
1150
1155
  ` + (suggestedUrls.length > 0 ? `Try opening: ${suggestedUrls.join(" or ")}` : "Set PORT (or NEXT_PORT/NUXT_PORT/VITE_PORT) and try sending again.");
@@ -1161,7 +1166,7 @@ var DEFAULT_RETENTION_S = 86400;
1161
1166
  function scheduleDevRedelivery(ctx, delayS) {
1162
1167
  const cappedDelay = Math.min(Math.max(delayS, 0), DEV_REDELIVERY_MAX_DELAY_S);
1163
1168
  console.log(
1164
- `[Dev Mode] \u21BB Scheduling re-delivery in ${cappedDelay}s: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1169
+ `${PREFIX} ${RETRY} Scheduling re-delivery in ${cappedDelay}s: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1165
1170
  );
1166
1171
  setTimeout(async () => {
1167
1172
  const nextDeliveryCount = ctx.deliveryCount + 1;
@@ -1170,13 +1175,13 @@ function scheduleDevRedelivery(ctx, delayS) {
1170
1175
  );
1171
1176
  if (Date.now() >= expiresAt.getTime()) {
1172
1177
  console.log(
1173
- `[Dev Mode] Message expired, stopping retries: topic="${ctx.topicName}" messageId="${ctx.messageId}"`
1178
+ `${PREFIX} Message expired, stopping retries: topic="${ctx.topicName}" messageId="${ctx.messageId}"`
1174
1179
  );
1175
1180
  return;
1176
1181
  }
1177
1182
  if (nextDeliveryCount > DEV_REDELIVERY_MAX_ATTEMPTS) {
1178
1183
  console.log(
1179
- `[Dev Mode] Max re-deliveries (${DEV_REDELIVERY_MAX_ATTEMPTS}) reached: topic="${ctx.topicName}" messageId="${ctx.messageId}"`
1184
+ `${PREFIX} Max re-deliveries (${DEV_REDELIVERY_MAX_ATTEMPTS}) reached: topic="${ctx.topicName}" messageId="${ctx.messageId}"`
1180
1185
  );
1181
1186
  return;
1182
1187
  }
@@ -1190,7 +1195,7 @@ function scheduleDevRedelivery(ctx, delayS) {
1190
1195
  region: ctx.region
1191
1196
  };
1192
1197
  console.log(
1193
- `[Dev Mode] Re-delivering: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}" deliveryCount=${nextDeliveryCount}`
1198
+ `${PREFIX} Re-delivering: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}" deliveryCount=${nextDeliveryCount}`
1194
1199
  );
1195
1200
  let succeeded = true;
1196
1201
  let nextRetryAfterS = null;
@@ -1204,7 +1209,7 @@ function scheduleDevRedelivery(ctx, delayS) {
1204
1209
  try {
1205
1210
  directive = ctx.retry(error, metadata);
1206
1211
  } catch (retryErr) {
1207
- console.warn("[Dev Mode] retry handler threw:", retryErr);
1212
+ console.warn(`${PREFIX} retry handler threw:`, retryErr);
1208
1213
  }
1209
1214
  if (directive && "afterSeconds" in directive) {
1210
1215
  nextRetryAfterS = directive.afterSeconds;
@@ -1214,18 +1219,18 @@ function scheduleDevRedelivery(ctx, delayS) {
1214
1219
  }
1215
1220
  if (!nextAcknowledged) {
1216
1221
  console.error(
1217
- `[Dev Mode] \u2717 Handler error on re-delivery: topic="${ctx.topicName}" messageId="${ctx.messageId}"`,
1222
+ `${PREFIX} ${FAIL} Handler error on re-delivery: topic="${ctx.topicName}" messageId="${ctx.messageId}"`,
1218
1223
  error
1219
1224
  );
1220
1225
  }
1221
1226
  }
1222
1227
  if (succeeded) {
1223
1228
  console.log(
1224
- `[Dev Mode] \u2713 Message processed on re-delivery: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1229
+ `${PREFIX} ${OK} Message processed on re-delivery: topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1225
1230
  );
1226
1231
  } else if (nextAcknowledged) {
1227
1232
  console.log(
1228
- `[Dev Mode] \u2713 Message acknowledged (will not retry): topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1233
+ `${PREFIX} ${OK} Message acknowledged (will not retry): topic="${ctx.topicName}" consumer="${ctx.consumerGroup}" messageId="${ctx.messageId}"`
1229
1234
  );
1230
1235
  } else {
1231
1236
  const nextDelay = nextRetryAfterS ?? ctx.defaultRetryDelayS;
@@ -1239,7 +1244,7 @@ function scheduleDevRedelivery(ctx, delayS) {
1239
1244
  function invokeDevHandlers(topicName, messageId, region, delaySeconds, retentionSeconds) {
1240
1245
  if (delaySeconds && delaySeconds > 0) {
1241
1246
  console.log(
1242
- `[Dev Mode] Message sent with delay: topic="${topicName}" messageId="${messageId}" delay=${delaySeconds}s`
1247
+ `${PREFIX} Message sent with delay: topic="${topicName}" messageId="${messageId}" delay=${delaySeconds}s`
1243
1248
  );
1244
1249
  setTimeout(() => {
1245
1250
  invokeDevHandlers(
@@ -1253,7 +1258,7 @@ function invokeDevHandlers(topicName, messageId, region, delaySeconds, retention
1253
1258
  return;
1254
1259
  }
1255
1260
  console.log(
1256
- `[Dev Mode] Message sent: topic="${topicName}" messageId="${messageId}"`
1261
+ `${PREFIX} Message sent: topic="${topicName}" messageId="${messageId}"`
1257
1262
  );
1258
1263
  (async () => {
1259
1264
  let handlers = lookupHandlers(topicName);
@@ -1280,7 +1285,7 @@ function invokeDevHandlers(topicName, messageId, region, delaySeconds, retention
1280
1285
  );
1281
1286
  } else {
1282
1287
  console.warn(
1283
- `[Dev Mode] No registered handler for topic "${topicName}".
1288
+ `${PREFIX} No registered handler for topic "${topicName}".
1284
1289
  Ensure vercel.json has a matching experimentalTriggers entry and the route file calls handleCallback().`
1285
1290
  );
1286
1291
  }
@@ -1288,7 +1293,7 @@ Ensure vercel.json has a matching experimentalTriggers entry and the route file
1288
1293
  }
1289
1294
  const consumerGroups = handlers.map((h) => h.consumerGroup);
1290
1295
  console.log(
1291
- `[Dev Mode] Invoking handlers for topic="${topicName}" messageId="${messageId}" \u2192 consumers: [${consumerGroups.join(", ")}]`
1296
+ `${PREFIX} Invoking handlers for topic="${topicName}" messageId="${messageId}" \u2192 consumers: [${consumerGroups.join(", ")}]`
1292
1297
  );
1293
1298
  const effectiveRetention = retentionSeconds ?? DEFAULT_RETENTION_S;
1294
1299
  for (const entry of handlers) {
@@ -1350,11 +1355,11 @@ Ensure vercel.json has a matching experimentalTriggers entry and the route file
1350
1355
  await invokeWithRetry(wrappedHandler, request, callbackOptions);
1351
1356
  if (handlerSucceeded) {
1352
1357
  console.log(
1353
- `[Dev Mode] \u2713 Message processed: topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`
1358
+ `${PREFIX} ${OK} Message processed: topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`
1354
1359
  );
1355
1360
  } else if (retryAcknowledged) {
1356
1361
  console.log(
1357
- `[Dev Mode] \u2713 Message acknowledged (will not retry): topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`
1362
+ `${PREFIX} ${OK} Message acknowledged (will not retry): topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`
1358
1363
  );
1359
1364
  } else if (retryAfterS !== null) {
1360
1365
  const devDelay = Math.min(retryAfterS, DEV_REDELIVERY_MAX_DELAY_S);
@@ -1362,7 +1367,7 @@ Ensure vercel.json has a matching experimentalTriggers entry and the route file
1362
1367
  }
1363
1368
  } catch (error) {
1364
1369
  console.error(
1365
- `[Dev Mode] \u2717 Handler failed: topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`,
1370
+ `${PREFIX} ${FAIL} Handler failed: topic="${topicName}" consumer="${entry.consumerGroup}" messageId="${messageId}"`,
1366
1371
  error
1367
1372
  );
1368
1373
  if (!handlerSucceeded) {
@@ -1458,6 +1463,7 @@ var ApiClient = class _ApiClient {
1458
1463
  transport;
1459
1464
  region;
1460
1465
  baseUrlResolver;
1466
+ dispatcher;
1461
1467
  constructor(options) {
1462
1468
  this.region = options.region;
1463
1469
  this.baseUrlResolver = options.resolveBaseUrl;
@@ -1465,6 +1471,7 @@ var ApiClient = class _ApiClient {
1465
1471
  this.customHeaders = options.headers || {};
1466
1472
  this.providedToken = options.token;
1467
1473
  this.transport = options.transport || new JsonTransport();
1474
+ this.dispatcher = options.dispatcher;
1468
1475
  if (options.deploymentId === null) {
1469
1476
  this.pinSends = false;
1470
1477
  this.explicitlyUnpinned = true;
@@ -1487,7 +1494,8 @@ var ApiClient = class _ApiClient {
1487
1494
  token: this.providedToken,
1488
1495
  headers: { ...this.customHeaders },
1489
1496
  deploymentId: this.explicitlyUnpinned ? null : this.resolvedDeploymentId,
1490
- transport: this.transport
1497
+ transport: this.transport,
1498
+ dispatcher: this.dispatcher
1491
1499
  });
1492
1500
  }
1493
1501
  getRegion() {
@@ -1522,13 +1530,25 @@ var ApiClient = class _ApiClient {
1522
1530
  if (this.providedToken) {
1523
1531
  return this.providedToken;
1524
1532
  }
1525
- const token = await getVercelOidcToken();
1526
- if (!token) {
1533
+ try {
1534
+ return await getVercelOidcToken();
1535
+ } catch (err) {
1536
+ const cause = err instanceof Error ? err.message : String(err);
1527
1537
  throw new Error(
1528
- "Failed to get OIDC token from Vercel Functions. Make sure you are running in a Vercel Function environment, or provide a token explicitly.\n\nTo set up your environment:\n1. Link your project: 'vercel link'\n2. Pull environment variables: 'vercel env pull'\n3. Run with environment: 'dotenv -e .env.local -- your-command'"
1538
+ isDevMode() ? `Failed to get OIDC token for local development.
1539
+
1540
+ To fix this, pull your environment variables with Vercel CLI:
1541
+ \`vercel env pull\`
1542
+
1543
+ Cause: ${cause}` : `Failed to get OIDC token. This usually means the function is running outside of a Vercel Function environment.
1544
+
1545
+ To fix this, either:
1546
+ - Deploy to Vercel (OIDC tokens are provisioned automatically)
1547
+ - Provide a token explicitly: \`new QueueClient({ token: '...' })\`
1548
+
1549
+ Cause: ${cause}`
1529
1550
  );
1530
1551
  }
1531
- return token;
1532
1552
  }
1533
1553
  buildUrl(queueName, ...pathSegments) {
1534
1554
  const encodedQueue = encodeURIComponent(queueName);
@@ -1559,9 +1579,10 @@ var ApiClient = class _ApiClient {
1559
1579
  }
1560
1580
  console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
1561
1581
  }
1562
- init.headers.set("User-Agent", `@vercel/queue/${"0.1.2"}`);
1582
+ init.headers.set("User-Agent", `@vercel/queue/${"0.1.4"}`);
1563
1583
  init.headers.set("Vqs-Client-Ts", (/* @__PURE__ */ new Date()).toISOString());
1564
- const response = await fetch(url, init);
1584
+ const fetchInit = this.dispatcher ? { ...init, dispatcher: this.dispatcher } : init;
1585
+ const response = await fetch(url, fetchInit);
1565
1586
  if (isDebugEnabled()) {
1566
1587
  const logData = {
1567
1588
  method,