@workflow/world-testing 4.0.1-beta.24 → 4.0.1-beta.25

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.
@@ -9098,7 +9098,7 @@ var require_client = __commonJS({
9098
9098
  return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1;
9099
9099
  }
9100
9100
  __name(getPipelining, "getPipelining");
9101
- var Client = class extends DispatcherBase {
9101
+ var Client2 = class extends DispatcherBase {
9102
9102
  static {
9103
9103
  __name(this, "Client");
9104
9104
  }
@@ -9532,7 +9532,7 @@ var require_client = __commonJS({
9532
9532
  }
9533
9533
  }
9534
9534
  __name(_resume, "_resume");
9535
- module2.exports = Client;
9535
+ module2.exports = Client2;
9536
9536
  }
9537
9537
  });
9538
9538
  // ../../node_modules/.pnpm/undici@6.19.0/node_modules/undici/lib/dispatcher/fixed-queue.js
@@ -9813,7 +9813,7 @@ var require_pool = __commonJS({
9813
9813
  "../../node_modules/.pnpm/undici@6.19.0/node_modules/undici/lib/dispatcher/pool.js"(exports2, module2) {
9814
9814
  "use strict";
9815
9815
  var { PoolBase, kClients, kNeedDrain, kAddClient, kGetDispatcher } = require_pool_base();
9816
- var Client = require_client();
9816
+ var Client2 = require_client();
9817
9817
  var { InvalidArgumentError } = require_errors();
9818
9818
  var util = require_util();
9819
9819
  var { kUrl, kInterceptors } = require_symbols();
@@ -9822,7 +9822,7 @@ var require_pool = __commonJS({
9822
9822
  var kConnections = Symbol("connections");
9823
9823
  var kFactory = Symbol("factory");
9824
9824
  function defaultFactory(origin, opts) {
9825
- return new Client(origin, opts);
9825
+ return new Client2(origin, opts);
9826
9826
  }
9827
9827
  __name(defaultFactory, "defaultFactory");
9828
9828
  var Pool = class extends PoolBase {
@@ -10023,7 +10023,7 @@ var require_agent = __commonJS({
10023
10023
  var { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols();
10024
10024
  var DispatcherBase = require_dispatcher_base();
10025
10025
  var Pool = require_pool();
10026
- var Client = require_client();
10026
+ var Client2 = require_client();
10027
10027
  var util = require_util();
10028
10028
  var createRedirectInterceptor = require_redirect_interceptor();
10029
10029
  var kOnConnect = Symbol("onConnect");
@@ -10034,7 +10034,7 @@ var require_agent = __commonJS({
10034
10034
  var kFactory = Symbol("factory");
10035
10035
  var kOptions = Symbol("options");
10036
10036
  function defaultFactory(origin, opts) {
10037
- return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts);
10037
+ return opts && opts.connections === 1 ? new Client2(origin, opts) : new Pool(origin, opts);
10038
10038
  }
10039
10039
  __name(defaultFactory, "defaultFactory");
10040
10040
  var Agent2 = class extends DispatcherBase {
@@ -12597,13 +12597,13 @@ var require_mock_client = __commonJS({
12597
12597
  "../../node_modules/.pnpm/undici@6.19.0/node_modules/undici/lib/mock/mock-client.js"(exports2, module2) {
12598
12598
  "use strict";
12599
12599
  var { promisify: promisify2 } = require("node:util");
12600
- var Client = require_client();
12600
+ var Client2 = require_client();
12601
12601
  var { buildMockDispatch } = require_mock_utils();
12602
12602
  var { kDispatches, kMockAgent, kClose, kOriginalClose, kOrigin, kOriginalDispatch, kConnected } = require_mock_symbols();
12603
12603
  var { MockInterceptor } = require_mock_interceptor();
12604
12604
  var Symbols = require_symbols();
12605
12605
  var { InvalidArgumentError } = require_errors();
12606
- var MockClient = class extends Client {
12606
+ var MockClient = class extends Client2 {
12607
12607
  static {
12608
12608
  __name(this, "MockClient");
12609
12609
  }
@@ -20102,7 +20102,7 @@ var require_eventsource = __commonJS({
20102
20102
  var require_undici = __commonJS({
20103
20103
  "../../node_modules/.pnpm/undici@6.19.0/node_modules/undici/index.js"(exports2, module2) {
20104
20104
  "use strict";
20105
- var Client = require_client();
20105
+ var Client2 = require_client();
20106
20106
  var Dispatcher = require_dispatcher();
20107
20107
  var Pool = require_pool();
20108
20108
  var BalancedPool = require_balanced_pool();
@@ -20126,7 +20126,7 @@ var require_undici = __commonJS({
20126
20126
  var createRedirectInterceptor = require_redirect_interceptor();
20127
20127
  Object.assign(Dispatcher.prototype, api);
20128
20128
  module2.exports.Dispatcher = Dispatcher;
20129
- module2.exports.Client = Client;
20129
+ module2.exports.Client = Client2;
20130
20130
  module2.exports.Pool = Pool;
20131
20131
  module2.exports.BalancedPool = BalancedPool;
20132
20132
  module2.exports.Agent = Agent2;
@@ -23661,17 +23661,6 @@ __name(__builtin_response_text, "__builtin_response_text");
23661
23661
  registerStepFunction("__builtin_response_array_buffer", __builtin_response_array_buffer);
23662
23662
  registerStepFunction("__builtin_response_json", __builtin_response_json);
23663
23663
  registerStepFunction("__builtin_response_text", __builtin_response_text);
23664
- // workflows/addition.ts
23665
- async function add(num, num2) {
23666
- return num + num2;
23667
- }
23668
- __name(add, "add");
23669
- async function addition(num, num2) {
23670
- throw new Error("You attempted to execute workflow addition function directly. To start a workflow, use start(addition) from workflow/api");
23671
- }
23672
- __name(addition, "addition");
23673
- addition.workflowId = "workflow//workflows/addition.ts//addition";
23674
- registerStepFunction("step//workflows/addition.ts//add", add);
23675
23664
  // ../utils/dist/index.js
23676
23665
  var import_ms = __toESM(require_ms(), 1);
23677
23666
  function once(fn) {
@@ -25015,7 +25004,7 @@ var StreamingMultipartParser = class {
25015
25004
  }
25016
25005
  }
25017
25006
  };
25018
- // ../../node_modules/.pnpm/@vercel+queue@0.0.0-alpha.29/node_modules/@vercel/queue/dist/index.mjs
25007
+ // ../../node_modules/.pnpm/@vercel+queue@0.0.0-alpha.33/node_modules/@vercel/queue/dist/index.mjs
25019
25008
  var import_oidc = __toESM(require_dist(), 1);
25020
25009
  async function streamToBuffer(stream) {
25021
25010
  let totalLength = 0;
@@ -25148,6 +25137,10 @@ var InvalidLimitError = class extends Error {
25148
25137
  this.name = "InvalidLimitError";
25149
25138
  }
25150
25139
  };
25140
+ function isDebugEnabled() {
25141
+ return process.env.VERCEL_QUEUE_DEBUG === "1" || process.env.VERCEL_QUEUE_DEBUG === "true";
25142
+ }
25143
+ __name(isDebugEnabled, "isDebugEnabled");
25151
25144
  async function consumeStream(stream) {
25152
25145
  const reader = stream.getReader();
25153
25146
  try {
@@ -25162,6 +25155,31 @@ async function consumeStream(stream) {
25162
25155
  }
25163
25156
  }
25164
25157
  __name(consumeStream, "consumeStream");
25158
+ function parseRetryAfter(headers) {
25159
+ const retryAfterHeader = headers.get("Retry-After");
25160
+ if (retryAfterHeader) {
25161
+ const parsed = parseInt(retryAfterHeader, 10);
25162
+ return Number.isNaN(parsed) ? void 0 : parsed;
25163
+ }
25164
+ return void 0;
25165
+ }
25166
+ __name(parseRetryAfter, "parseRetryAfter");
25167
+ function throwCommonHttpError(status, statusText, errorText, operation, badRequestDefault = "Invalid parameters") {
25168
+ if (status === 400) {
25169
+ throw new BadRequestError(errorText || badRequestDefault);
25170
+ }
25171
+ if (status === 401) {
25172
+ throw new UnauthorizedError(errorText || void 0);
25173
+ }
25174
+ if (status === 403) {
25175
+ throw new ForbiddenError(errorText || void 0);
25176
+ }
25177
+ if (status >= 500) {
25178
+ throw new InternalServerError(errorText || `Server error: ${status} ${statusText}`);
25179
+ }
25180
+ throw new Error(`Failed to ${operation}: ${status} ${statusText}`);
25181
+ }
25182
+ __name(throwCommonHttpError, "throwCommonHttpError");
25165
25183
  function parseQueueHeaders(headers) {
25166
25184
  const messageId = headers.get("Vqs-Message-Id");
25167
25185
  const deliveryCountStr = headers.get("Vqs-Delivery-Count") || "0";
@@ -25172,7 +25190,7 @@ function parseQueueHeaders(headers) {
25172
25190
  return null;
25173
25191
  }
25174
25192
  const deliveryCount = parseInt(deliveryCountStr, 10);
25175
- if (isNaN(deliveryCount)) {
25193
+ if (Number.isNaN(deliveryCount)) {
25176
25194
  return null;
25177
25195
  }
25178
25196
  return {
@@ -25190,22 +25208,22 @@ var QueueClient = class {
25190
25208
  }
25191
25209
  baseUrl;
25192
25210
  basePath;
25193
- customHeaders = {};
25211
+ customHeaders;
25212
+ providedToken;
25194
25213
  /**
25195
25214
  * Create a new Vercel Queue Service client
25196
- * @param options Client configuration options
25215
+ * @param options QueueClient configuration options
25197
25216
  */
25198
25217
  constructor(options = {}) {
25199
25218
  this.baseUrl = options.baseUrl || process.env.VERCEL_QUEUE_BASE_URL || "https://vercel-queue.com";
25200
25219
  this.basePath = options.basePath || process.env.VERCEL_QUEUE_BASE_PATH || "/api/v2/messages";
25201
- const VERCEL_QUEUE_HEADER_PREFIX = "VERCEL_QUEUE_HEADER_";
25202
- this.customHeaders = Object.fromEntries(Object.entries(process.env).filter(([key]) => key.startsWith(VERCEL_QUEUE_HEADER_PREFIX)).map(([key, value]) => [
25203
- // This allows headers to use dashes independent of shell used
25204
- key.replace(VERCEL_QUEUE_HEADER_PREFIX, "").replaceAll("__", "-"),
25205
- value || ""
25206
- ]));
25220
+ this.customHeaders = options.headers || {};
25221
+ this.providedToken = options.token;
25207
25222
  }
25208
25223
  async getToken() {
25224
+ if (this.providedToken) {
25225
+ return this.providedToken;
25226
+ }
25209
25227
  const token = await (0, import_oidc.getVercelOidcToken)();
25210
25228
  if (!token) {
25211
25229
  throw new Error("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'");
@@ -25213,6 +25231,48 @@ var QueueClient = class {
25213
25231
  return token;
25214
25232
  }
25215
25233
  /**
25234
+ * Internal fetch wrapper that automatically handles debug logging
25235
+ * when VERCEL_QUEUE_DEBUG is enabled
25236
+ */
25237
+ async fetch(url2, init) {
25238
+ const method = init.method || "GET";
25239
+ if (isDebugEnabled()) {
25240
+ const logData = {
25241
+ method,
25242
+ url: url2,
25243
+ headers: init.headers
25244
+ };
25245
+ const body = init.body;
25246
+ if (body !== void 0 && body !== null) {
25247
+ if (body instanceof ArrayBuffer) {
25248
+ logData.bodySize = body.byteLength;
25249
+ }
25250
+ else if (body instanceof Uint8Array) {
25251
+ logData.bodySize = body.byteLength;
25252
+ }
25253
+ else if (typeof body === "string") {
25254
+ logData.bodySize = body.length;
25255
+ }
25256
+ else {
25257
+ logData.bodyType = typeof body;
25258
+ }
25259
+ }
25260
+ console.debug("[VQS Debug] Request:", JSON.stringify(logData, null, 2));
25261
+ }
25262
+ const response = await fetch(url2, init);
25263
+ if (isDebugEnabled()) {
25264
+ const logData = {
25265
+ method,
25266
+ url: url2,
25267
+ status: response.status,
25268
+ statusText: response.statusText,
25269
+ headers: response.headers
25270
+ };
25271
+ console.debug("[VQS Debug] Response:", JSON.stringify(logData, null, 2));
25272
+ }
25273
+ return response;
25274
+ }
25275
+ /**
25216
25276
  * Send a message to a queue
25217
25277
  * @param options Send message options
25218
25278
  * @param transport Serializer/deserializer for the payload
@@ -25241,29 +25301,17 @@ var QueueClient = class {
25241
25301
  headers.set("Vqs-Retention-Seconds", retentionSeconds.toString());
25242
25302
  }
25243
25303
  const body = transport.serialize(payload);
25244
- const response = await fetch(`${this.baseUrl}${this.basePath}`, {
25304
+ const response = await this.fetch(`${this.baseUrl}${this.basePath}`, {
25245
25305
  method: "POST",
25246
25306
  body,
25247
25307
  headers
25248
25308
  });
25249
25309
  if (!response.ok) {
25250
- if (response.status === 400) {
25251
- const errorText = await response.text();
25252
- throw new BadRequestError(errorText || "Invalid parameters");
25253
- }
25254
- if (response.status === 401) {
25255
- throw new UnauthorizedError();
25256
- }
25257
- if (response.status === 403) {
25258
- throw new ForbiddenError();
25259
- }
25310
+ const errorText = await response.text();
25260
25311
  if (response.status === 409) {
25261
25312
  throw new Error("Duplicate idempotency key detected");
25262
25313
  }
25263
- if (response.status >= 500) {
25264
- throw new InternalServerError(`Server error: ${response.status} ${response.statusText}`);
25265
- }
25266
- throw new Error(`Failed to send message: ${response.status} ${response.statusText}`);
25314
+ throwCommonHttpError(response.status, response.statusText, errorText, "send message");
25267
25315
  }
25268
25316
  const responseData = await response.json();
25269
25317
  return responseData;
@@ -25299,7 +25347,7 @@ var QueueClient = class {
25299
25347
  if (limit !== void 0) {
25300
25348
  headers.set("Vqs-Limit", limit.toString());
25301
25349
  }
25302
- const response = await fetch(`${this.baseUrl}${this.basePath}`, {
25350
+ const response = await this.fetch(`${this.baseUrl}${this.basePath}`, {
25303
25351
  method: "GET",
25304
25352
  headers
25305
25353
  });
@@ -25307,29 +25355,11 @@ var QueueClient = class {
25307
25355
  throw new QueueEmptyError(queueName, consumerGroup);
25308
25356
  }
25309
25357
  if (!response.ok) {
25310
- if (response.status === 400) {
25311
- const errorText = await response.text();
25312
- throw new BadRequestError(errorText || "Invalid parameters");
25313
- }
25314
- if (response.status === 401) {
25315
- throw new UnauthorizedError();
25316
- }
25317
- if (response.status === 403) {
25318
- throw new ForbiddenError();
25319
- }
25358
+ const errorText = await response.text();
25320
25359
  if (response.status === 423) {
25321
- const retryAfterHeader = response.headers.get("Retry-After");
25322
- let retryAfter;
25323
- if (retryAfterHeader) {
25324
- const parsed = parseInt(retryAfterHeader, 10);
25325
- retryAfter = isNaN(parsed) ? void 0 : parsed;
25326
- }
25327
- throw new MessageLockedError("next message", retryAfter);
25360
+ throw new MessageLockedError("next message", parseRetryAfter(response.headers));
25328
25361
  }
25329
- if (response.status >= 500) {
25330
- throw new InternalServerError(`Server error: ${response.status} ${response.statusText}`);
25331
- }
25332
- throw new Error(`Failed to receive messages: ${response.status} ${response.statusText}`);
25362
+ throwCommonHttpError(response.status, response.statusText, errorText, "receive messages");
25333
25363
  }
25334
25364
  for await (const multipartMessage of parseMultipartStream(response)) {
25335
25365
  try {
@@ -25367,40 +25397,22 @@ var QueueClient = class {
25367
25397
  if (skipPayload) {
25368
25398
  headers.set("Vqs-Skip-Payload", "1");
25369
25399
  }
25370
- const response = await fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25400
+ const response = await this.fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25371
25401
  method: "GET",
25372
25402
  headers
25373
25403
  });
25374
25404
  if (!response.ok) {
25375
- if (response.status === 400) {
25376
- const errorText = await response.text();
25377
- throw new BadRequestError(errorText || "Invalid parameters");
25378
- }
25379
- if (response.status === 401) {
25380
- throw new UnauthorizedError();
25381
- }
25382
- if (response.status === 403) {
25383
- throw new ForbiddenError();
25384
- }
25405
+ const errorText = await response.text();
25385
25406
  if (response.status === 404) {
25386
25407
  throw new MessageNotFoundError(messageId);
25387
25408
  }
25388
- if (response.status === 423) {
25389
- const retryAfterHeader = response.headers.get("Retry-After");
25390
- let retryAfter;
25391
- if (retryAfterHeader) {
25392
- const parsed = parseInt(retryAfterHeader, 10);
25393
- retryAfter = isNaN(parsed) ? void 0 : parsed;
25394
- }
25395
- throw new MessageLockedError(messageId, retryAfter);
25396
- }
25397
25409
  if (response.status === 409) {
25398
25410
  throw new MessageNotAvailableError(messageId);
25399
25411
  }
25400
- if (response.status >= 500) {
25401
- throw new InternalServerError(`Server error: ${response.status} ${response.statusText}`);
25412
+ if (response.status === 423) {
25413
+ throw new MessageLockedError(messageId, parseRetryAfter(response.headers));
25402
25414
  }
25403
- throw new Error(`Failed to receive message by ID: ${response.status} ${response.statusText}`);
25415
+ throwCommonHttpError(response.status, response.statusText, errorText, "receive message by ID");
25404
25416
  }
25405
25417
  if (skipPayload && response.status === 204) {
25406
25418
  const parsedHeaders = parseQueueHeaders(response.headers);
@@ -25464,7 +25476,7 @@ var QueueClient = class {
25464
25476
  */
25465
25477
  async deleteMessage(options) {
25466
25478
  const { queueName, consumerGroup, messageId, ticket } = options;
25467
- const response = await fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25479
+ const response = await this.fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25468
25480
  method: "DELETE",
25469
25481
  headers: new Headers({
25470
25482
  Authorization: `Bearer ${await this.getToken()}`,
@@ -25475,25 +25487,14 @@ var QueueClient = class {
25475
25487
  })
25476
25488
  });
25477
25489
  if (!response.ok) {
25478
- if (response.status === 400) {
25479
- throw new BadRequestError("Missing or invalid ticket");
25480
- }
25481
- if (response.status === 401) {
25482
- throw new UnauthorizedError();
25483
- }
25484
- if (response.status === 403) {
25485
- throw new ForbiddenError();
25486
- }
25490
+ const errorText = await response.text();
25487
25491
  if (response.status === 404) {
25488
25492
  throw new MessageNotFoundError(messageId);
25489
25493
  }
25490
25494
  if (response.status === 409) {
25491
- throw new MessageNotAvailableError(messageId, "Invalid ticket, message not in correct state, or already processed");
25495
+ throw new MessageNotAvailableError(messageId, errorText || "Invalid ticket, message not in correct state, or already processed");
25492
25496
  }
25493
- if (response.status >= 500) {
25494
- throw new InternalServerError(`Server error: ${response.status} ${response.statusText}`);
25495
- }
25496
- throw new Error(`Failed to delete message: ${response.status} ${response.statusText}`);
25497
+ throwCommonHttpError(response.status, response.statusText, errorText, "delete message", "Missing or invalid ticket");
25497
25498
  }
25498
25499
  return {
25499
25500
  deleted: true
@@ -25512,7 +25513,7 @@ var QueueClient = class {
25512
25513
  */
25513
25514
  async changeVisibility(options) {
25514
25515
  const { queueName, consumerGroup, messageId, ticket, visibilityTimeoutSeconds } = options;
25515
- const response = await fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25516
+ const response = await this.fetch(`${this.baseUrl}${this.basePath}/${encodeURIComponent(messageId)}`, {
25516
25517
  method: "PATCH",
25517
25518
  headers: new Headers({
25518
25519
  Authorization: `Bearer ${await this.getToken()}`,
@@ -25524,165 +25525,33 @@ var QueueClient = class {
25524
25525
  })
25525
25526
  });
25526
25527
  if (!response.ok) {
25527
- if (response.status === 400) {
25528
- throw new BadRequestError("Missing ticket or invalid visibility timeout");
25529
- }
25530
- if (response.status === 401) {
25531
- throw new UnauthorizedError();
25532
- }
25533
- if (response.status === 403) {
25534
- throw new ForbiddenError();
25535
- }
25528
+ const errorText = await response.text();
25536
25529
  if (response.status === 404) {
25537
25530
  throw new MessageNotFoundError(messageId);
25538
25531
  }
25539
25532
  if (response.status === 409) {
25540
- throw new MessageNotAvailableError(messageId, "Invalid ticket, message not in correct state, or already processed");
25541
- }
25542
- if (response.status >= 500) {
25543
- throw new InternalServerError(`Server error: ${response.status} ${response.statusText}`);
25533
+ throw new MessageNotAvailableError(messageId, errorText || "Invalid ticket, message not in correct state, or already processed");
25544
25534
  }
25545
- throw new Error(`Failed to change visibility: ${response.status} ${response.statusText}`);
25535
+ throwCommonHttpError(response.status, response.statusText, errorText, "change visibility", "Missing ticket or invalid visibility timeout");
25546
25536
  }
25547
25537
  return {
25548
25538
  updated: true
25549
25539
  };
25550
25540
  }
25551
25541
  };
25552
- function validateWildcardPattern(pattern) {
25553
- const firstIndex = pattern.indexOf("*");
25554
- const lastIndex = pattern.lastIndexOf("*");
25555
- if (firstIndex !== lastIndex) {
25556
- return false;
25557
- }
25558
- if (firstIndex === -1) {
25559
- return false;
25560
- }
25561
- if (firstIndex !== pattern.length - 1) {
25562
- return false;
25563
- }
25564
- return true;
25565
- }
25566
- __name(validateWildcardPattern, "validateWildcardPattern");
25567
- function matchesWildcardPattern(topicName, pattern) {
25568
- const prefix = pattern.slice(0, -1);
25569
- return topicName.startsWith(prefix);
25570
- }
25571
- __name(matchesWildcardPattern, "matchesWildcardPattern");
25572
- function findTopicHandler(queueName, handlers) {
25573
- const exactHandler = handlers[queueName];
25574
- if (exactHandler) {
25575
- return exactHandler;
25576
- }
25577
- for (const pattern in handlers) {
25578
- if (pattern.includes("*") && matchesWildcardPattern(queueName, pattern)) {
25579
- return handlers[pattern];
25580
- }
25581
- }
25582
- return null;
25583
- }
25584
- __name(findTopicHandler, "findTopicHandler");
25585
- async function parseCallback(request) {
25586
- const contentType = request.headers.get("content-type");
25587
- if (!contentType || !contentType.includes("application/cloudevents+json")) {
25588
- throw new Error("Invalid content type: expected 'application/cloudevents+json'");
25589
- }
25590
- let cloudEvent;
25591
- try {
25592
- cloudEvent = await request.json();
25593
- }
25594
- catch (error45) {
25595
- throw new Error("Failed to parse CloudEvent from request body");
25596
- }
25597
- if (!cloudEvent.type || !cloudEvent.source || !cloudEvent.id || typeof cloudEvent.data !== "object" || cloudEvent.data == null) {
25598
- throw new Error("Invalid CloudEvent: missing required fields");
25599
- }
25600
- if (cloudEvent.type !== "com.vercel.queue.v1beta") {
25601
- throw new Error(`Invalid CloudEvent type: expected 'com.vercel.queue.v1beta', got '${cloudEvent.type}'`);
25602
- }
25603
- const missingFields = [];
25604
- if (!("queueName" in cloudEvent.data))
25605
- missingFields.push("queueName");
25606
- if (!("consumerGroup" in cloudEvent.data))
25607
- missingFields.push("consumerGroup");
25608
- if (!("messageId" in cloudEvent.data))
25609
- missingFields.push("messageId");
25610
- if (missingFields.length > 0) {
25611
- throw new Error(`Missing required CloudEvent data fields: ${missingFields.join(", ")}`);
25612
- }
25613
- const { messageId, queueName, consumerGroup } = cloudEvent.data;
25614
- return {
25615
- queueName,
25616
- consumerGroup,
25617
- messageId
25618
- };
25619
- }
25620
- __name(parseCallback, "parseCallback");
25621
- function handleCallback(handlers) {
25622
- for (const topicPattern in handlers) {
25623
- if (topicPattern.includes("*")) {
25624
- if (!validateWildcardPattern(topicPattern)) {
25625
- throw new Error(`Invalid wildcard pattern "${topicPattern}": * may only appear once and must be at the end of the topic name`);
25626
- }
25627
- }
25628
- }
25629
- const routeHandler = /* @__PURE__ */ __name(async (request) => {
25630
- try {
25631
- const { queueName, consumerGroup, messageId } = await parseCallback(request);
25632
- const topicHandler = findTopicHandler(queueName, handlers);
25633
- if (!topicHandler) {
25634
- const availableTopics = Object.keys(handlers).join(", ");
25635
- return Response.json({
25636
- error: `No handler found for topic: ${queueName}`,
25637
- availableTopics
25638
- }, {
25639
- status: 404
25640
- });
25641
- }
25642
- const consumerGroupHandler = topicHandler[consumerGroup];
25643
- if (!consumerGroupHandler) {
25644
- const availableGroups = Object.keys(topicHandler).join(", ");
25645
- return Response.json({
25646
- error: `No handler found for consumer group "${consumerGroup}" in topic "${queueName}".`,
25647
- availableGroups
25648
- }, {
25649
- status: 404
25650
- });
25651
- }
25652
- const client = new QueueClient();
25653
- const topic = new Topic(client, queueName);
25654
- const cg = topic.consumerGroup(consumerGroup);
25655
- await cg.consume(consumerGroupHandler, {
25656
- messageId
25657
- });
25658
- return Response.json({
25659
- status: "success"
25660
- });
25661
- }
25662
- catch (error45) {
25663
- console.error("Queue callback error:", error45);
25664
- if (error45 instanceof Error && (error45.message.includes("Missing required CloudEvent data fields") || error45.message.includes("Invalid CloudEvent") || error45.message.includes("Invalid CloudEvent type") || error45.message.includes("Invalid content type") || error45.message.includes("Failed to parse CloudEvent"))) {
25665
- return Response.json({
25666
- error: error45.message
25667
- }, {
25668
- status: 400
25669
- });
25670
- }
25671
- return Response.json({
25672
- error: "Failed to process queue message"
25673
- }, {
25674
- status: 500
25675
- });
25676
- }
25677
- }, "routeHandler");
25678
- if (isDevMode()) {
25679
- registerDevRouteHandler(routeHandler, handlers);
25542
+ var GLOBAL_KEY = Symbol.for("@vercel/queue.devHandlers");
25543
+ function getDevHandlerState() {
25544
+ const g = globalThis;
25545
+ if (!g[GLOBAL_KEY]) {
25546
+ g[GLOBAL_KEY] = {
25547
+ devRouteHandlers: /* @__PURE__ */ new Map(),
25548
+ wildcardRouteHandlers: /* @__PURE__ */ new Map()
25549
+ };
25680
25550
  }
25681
- return routeHandler;
25551
+ return g[GLOBAL_KEY];
25682
25552
  }
25683
- __name(handleCallback, "handleCallback");
25684
- var devRouteHandlers = /* @__PURE__ */ new Map();
25685
- var wildcardRouteHandlers = /* @__PURE__ */ new Map();
25553
+ __name(getDevHandlerState, "getDevHandlerState");
25554
+ var { devRouteHandlers, wildcardRouteHandlers } = getDevHandlerState();
25686
25555
  function cleanupDeadRefs(key, refs) {
25687
25556
  const aliveRefs = refs.filter((ref) => ref.deref() !== void 0);
25688
25557
  if (aliveRefs.length === 0) {
@@ -26092,9 +25961,144 @@ var Topic = class {
26092
25961
  return this.transport;
26093
25962
  }
26094
25963
  };
25964
+ function validateWildcardPattern(pattern) {
25965
+ const firstIndex = pattern.indexOf("*");
25966
+ const lastIndex = pattern.lastIndexOf("*");
25967
+ if (firstIndex !== lastIndex) {
25968
+ return false;
25969
+ }
25970
+ if (firstIndex === -1) {
25971
+ return false;
25972
+ }
25973
+ if (firstIndex !== pattern.length - 1) {
25974
+ return false;
25975
+ }
25976
+ return true;
25977
+ }
25978
+ __name(validateWildcardPattern, "validateWildcardPattern");
25979
+ function matchesWildcardPattern(topicName, pattern) {
25980
+ const prefix = pattern.slice(0, -1);
25981
+ return topicName.startsWith(prefix);
25982
+ }
25983
+ __name(matchesWildcardPattern, "matchesWildcardPattern");
25984
+ function findTopicHandler(queueName, handlers) {
25985
+ const exactHandler = handlers[queueName];
25986
+ if (exactHandler) {
25987
+ return exactHandler;
25988
+ }
25989
+ for (const pattern in handlers) {
25990
+ if (pattern.includes("*") && matchesWildcardPattern(queueName, pattern)) {
25991
+ return handlers[pattern];
25992
+ }
25993
+ }
25994
+ return null;
25995
+ }
25996
+ __name(findTopicHandler, "findTopicHandler");
25997
+ async function parseCallback(request) {
25998
+ const contentType = request.headers.get("content-type");
25999
+ if (!contentType || !contentType.includes("application/cloudevents+json")) {
26000
+ throw new Error("Invalid content type: expected 'application/cloudevents+json'");
26001
+ }
26002
+ let cloudEvent;
26003
+ try {
26004
+ cloudEvent = await request.json();
26005
+ }
26006
+ catch (error45) {
26007
+ throw new Error("Failed to parse CloudEvent from request body");
26008
+ }
26009
+ if (!cloudEvent.type || !cloudEvent.source || !cloudEvent.id || typeof cloudEvent.data !== "object" || cloudEvent.data == null) {
26010
+ throw new Error("Invalid CloudEvent: missing required fields");
26011
+ }
26012
+ if (cloudEvent.type !== "com.vercel.queue.v1beta") {
26013
+ throw new Error(`Invalid CloudEvent type: expected 'com.vercel.queue.v1beta', got '${cloudEvent.type}'`);
26014
+ }
26015
+ const missingFields = [];
26016
+ if (!("queueName" in cloudEvent.data))
26017
+ missingFields.push("queueName");
26018
+ if (!("consumerGroup" in cloudEvent.data))
26019
+ missingFields.push("consumerGroup");
26020
+ if (!("messageId" in cloudEvent.data))
26021
+ missingFields.push("messageId");
26022
+ if (missingFields.length > 0) {
26023
+ throw new Error(`Missing required CloudEvent data fields: ${missingFields.join(", ")}`);
26024
+ }
26025
+ const { messageId, queueName, consumerGroup } = cloudEvent.data;
26026
+ return {
26027
+ queueName,
26028
+ consumerGroup,
26029
+ messageId
26030
+ };
26031
+ }
26032
+ __name(parseCallback, "parseCallback");
26033
+ function createCallbackHandler(handlers, client) {
26034
+ for (const topicPattern in handlers) {
26035
+ if (topicPattern.includes("*")) {
26036
+ if (!validateWildcardPattern(topicPattern)) {
26037
+ throw new Error(`Invalid wildcard pattern "${topicPattern}": * may only appear once and must be at the end of the topic name`);
26038
+ }
26039
+ }
26040
+ }
26041
+ const routeHandler = /* @__PURE__ */ __name(async (request) => {
26042
+ try {
26043
+ const { queueName, consumerGroup, messageId } = await parseCallback(request);
26044
+ const topicHandler = findTopicHandler(queueName, handlers);
26045
+ if (!topicHandler) {
26046
+ const availableTopics = Object.keys(handlers).join(", ");
26047
+ return Response.json({
26048
+ error: `No handler found for topic: ${queueName}`,
26049
+ availableTopics
26050
+ }, {
26051
+ status: 404
26052
+ });
26053
+ }
26054
+ const consumerGroupHandler = topicHandler[consumerGroup];
26055
+ if (!consumerGroupHandler) {
26056
+ const availableGroups = Object.keys(topicHandler).join(", ");
26057
+ return Response.json({
26058
+ error: `No handler found for consumer group "${consumerGroup}" in topic "${queueName}".`,
26059
+ availableGroups
26060
+ }, {
26061
+ status: 404
26062
+ });
26063
+ }
26064
+ const topic = new Topic(client, queueName);
26065
+ const cg = topic.consumerGroup(consumerGroup);
26066
+ await cg.consume(consumerGroupHandler, {
26067
+ messageId
26068
+ });
26069
+ return Response.json({
26070
+ status: "success"
26071
+ });
26072
+ }
26073
+ catch (error45) {
26074
+ console.error("Queue callback error:", error45);
26075
+ if (error45 instanceof Error && (error45.message.includes("Missing required CloudEvent data fields") || error45.message.includes("Invalid CloudEvent") || error45.message.includes("Invalid CloudEvent type") || error45.message.includes("Invalid content type") || error45.message.includes("Failed to parse CloudEvent"))) {
26076
+ return Response.json({
26077
+ error: error45.message
26078
+ }, {
26079
+ status: 400
26080
+ });
26081
+ }
26082
+ return Response.json({
26083
+ error: "Failed to process queue message"
26084
+ }, {
26085
+ status: 500
26086
+ });
26087
+ }
26088
+ }, "routeHandler");
26089
+ if (isDevMode()) {
26090
+ registerDevRouteHandler(routeHandler, handlers);
26091
+ }
26092
+ return routeHandler;
26093
+ }
26094
+ __name(createCallbackHandler, "createCallbackHandler");
26095
+ function handleCallback(handlers, client) {
26096
+ return createCallbackHandler(handlers, client || new QueueClient());
26097
+ }
26098
+ __name(handleCallback, "handleCallback");
26095
26099
  async function send(topicName, payload, options) {
26096
26100
  const transport = options?.transport || new JsonTransport();
26097
- const client = new QueueClient();
26101
+ const client = options?.client || new QueueClient();
26098
26102
  const result = await client.sendMessage({
26099
26103
  queueName: topicName,
26100
26104
  payload,
@@ -26110,6 +26114,55 @@ async function send(topicName, payload, options) {
26110
26114
  };
26111
26115
  }
26112
26116
  __name(send, "send");
26117
+ var Client = class {
26118
+ static {
26119
+ __name(this, "Client");
26120
+ }
26121
+ client;
26122
+ /**
26123
+ * Create a new Client
26124
+ * @param options QueueClient configuration options
26125
+ */
26126
+ constructor(options = {}) {
26127
+ this.client = new QueueClient(options);
26128
+ }
26129
+ /**
26130
+ * Send a message to a topic
26131
+ * @param topicName Name of the topic to send to
26132
+ * @param payload The data to send
26133
+ * @param options Optional publish options and transport
26134
+ * @returns Promise with the message ID
26135
+ * @throws {BadRequestError} When request parameters are invalid
26136
+ * @throws {UnauthorizedError} When authentication fails
26137
+ * @throws {ForbiddenError} When access is denied (environment mismatch)
26138
+ * @throws {InternalServerError} When server encounters an error
26139
+ */
26140
+ async send(topicName, payload, options) {
26141
+ return send(topicName, payload, {
26142
+ ...options,
26143
+ client: this.client
26144
+ });
26145
+ }
26146
+ /**
26147
+ * Create a callback handler for processing queue messages
26148
+ * Returns a Next.js route handler function that routes messages to appropriate handlers
26149
+ * @param handlers Object with topic-specific handlers organized by consumer groups
26150
+ * @returns A Next.js route handler function
26151
+ *
26152
+ * @example
26153
+ * ```typescript
26154
+ * export const POST = client.handleCallback({
26155
+ * "user-events": {
26156
+ * "welcome": (user, metadata) => console.log("Welcoming user", user),
26157
+ * "analytics": (user, metadata) => console.log("Tracking user", user),
26158
+ * },
26159
+ * });
26160
+ * ```
26161
+ */
26162
+ handleCallback(handlers) {
26163
+ return handleCallback(handlers, this.client);
26164
+ }
26165
+ };
26113
26166
  // ../../node_modules/.pnpm/zod@4.1.11/node_modules/zod/v4/classic/external.js
26114
26167
  var external_exports = {};
26115
26168
  __export(external_exports, {
@@ -41333,7 +41386,7 @@ __name(createLocalWorld, "createLocalWorld");
41333
41386
  var import_node_os = __toESM(require("node:os"), 1);
41334
41387
  var import_oidc2 = __toESM(require_dist(), 1);
41335
41388
  // ../world-vercel/dist/version.js
41336
- var version2 = "4.0.1-beta.14";
41389
+ var version2 = "4.0.1-beta.15";
41337
41390
  // ../world-vercel/dist/utils.js
41338
41391
  var DEFAULT_RESOLVE_DATA_OPTION2 = "all";
41339
41392
  function dateToStringReplacer(_key, value) {
@@ -41475,19 +41528,12 @@ var VERCEL_QUEUE_MAX_VISIBILITY = 82800;
41475
41528
  function createQueue2(config3) {
41476
41529
  const { baseUrl, usingProxy } = getHttpUrl(config3);
41477
41530
  const headers = getHeaders(config3);
41478
- if (usingProxy) {
41479
- process.env.VERCEL_QUEUE_BASE_URL = `${baseUrl}`;
41480
- process.env.VERCEL_QUEUE_BASE_PATH = "/queues/v2/messages";
41481
- if (config3?.token) {
41482
- process.env.VERCEL_QUEUE_TOKEN = config3.token;
41483
- }
41484
- if (headers) {
41485
- headers.forEach((value, key) => {
41486
- const sanitizedKey = key.replaceAll("-", "__");
41487
- process.env[`VERCEL_QUEUE_HEADER_${sanitizedKey}`] = value;
41488
- });
41489
- }
41490
- }
41531
+ const queueClient = new Client({
41532
+ baseUrl: usingProxy ? baseUrl : void 0,
41533
+ basePath: usingProxy ? "/queues/v2/messages" : void 0,
41534
+ token: usingProxy ? config3?.token : void 0,
41535
+ headers: Object.fromEntries(headers.entries())
41536
+ });
41491
41537
  const queue = /* @__PURE__ */ __name(async (queueName, x, opts) => {
41492
41538
  const hasEncoder = typeof MessageWrapper.encode === "function";
41493
41539
  if (!hasEncoder) {
@@ -41499,13 +41545,13 @@ function createQueue2(config3) {
41499
41545
  queueName
41500
41546
  });
41501
41547
  const sanitizedQueueName = queueName.replace(/[^A-Za-z0-9-_]/g, "-");
41502
- const { messageId } = await send(sanitizedQueueName, encoded, opts);
41548
+ const { messageId } = await queueClient.send(sanitizedQueueName, encoded, opts);
41503
41549
  return {
41504
41550
  messageId: MessageId.parse(messageId)
41505
41551
  };
41506
41552
  }, "queue");
41507
41553
  const createQueueHandler = /* @__PURE__ */ __name((prefix, handler) => {
41508
- return handleCallback({
41554
+ return queueClient.handleCallback({
41509
41555
  [`${prefix}*`]: {
41510
41556
  default: /* @__PURE__ */ __name(async (body, meta) => {
41511
41557
  const { payload, queueName } = MessageWrapper.parse(body);
@@ -42944,17 +42990,6 @@ async function brokenWf() {
42944
42990
  __name(brokenWf, "brokenWf");
42945
42991
  brokenWf.workflowId = "workflow//workflows/noop.ts//brokenWf";
42946
42992
  registerStepFunction("step//workflows/noop.ts//noop", noop);
42947
- // workflows/null-byte.ts
42948
- async function nullByteStep() {
42949
- return "null byte \0";
42950
- }
42951
- __name(nullByteStep, "nullByteStep");
42952
- async function nullByteWorkflow() {
42953
- throw new Error("You attempted to execute workflow nullByteWorkflow function directly. To start a workflow, use start(nullByteWorkflow) from workflow/api");
42954
- }
42955
- __name(nullByteWorkflow, "nullByteWorkflow");
42956
- nullByteWorkflow.workflowId = "workflow//workflows/null-byte.ts//nullByteWorkflow";
42957
- registerStepFunction("step//workflows/null-byte.ts//nullByteStep", nullByteStep);
42958
42993
  // workflows/retriable-and-fatal.ts
42959
42994
  async function retryableAndFatalErrorWorkflow() {
42960
42995
  throw new Error("You attempted to execute workflow retryableAndFatalErrorWorkflow function directly. To start a workflow, use start(retryableAndFatalErrorWorkflow) from workflow/api");
@@ -42982,6 +43017,28 @@ async function stepThatFails() {
42982
43017
  __name(stepThatFails, "stepThatFails");
42983
43018
  registerStepFunction("step//workflows/retriable-and-fatal.ts//stepThatThrowsRetryableError", stepThatThrowsRetryableError);
42984
43019
  registerStepFunction("step//workflows/retriable-and-fatal.ts//stepThatFails", stepThatFails);
43020
+ // workflows/null-byte.ts
43021
+ async function nullByteStep() {
43022
+ return "null byte \0";
43023
+ }
43024
+ __name(nullByteStep, "nullByteStep");
43025
+ async function nullByteWorkflow() {
43026
+ throw new Error("You attempted to execute workflow nullByteWorkflow function directly. To start a workflow, use start(nullByteWorkflow) from workflow/api");
43027
+ }
43028
+ __name(nullByteWorkflow, "nullByteWorkflow");
43029
+ nullByteWorkflow.workflowId = "workflow//workflows/null-byte.ts//nullByteWorkflow";
43030
+ registerStepFunction("step//workflows/null-byte.ts//nullByteStep", nullByteStep);
43031
+ // workflows/addition.ts
43032
+ async function add(num, num2) {
43033
+ return num + num2;
43034
+ }
43035
+ __name(add, "add");
43036
+ async function addition(num, num2) {
43037
+ throw new Error("You attempted to execute workflow addition function directly. To start a workflow, use start(addition) from workflow/api");
43038
+ }
43039
+ __name(addition, "addition");
43040
+ addition.workflowId = "workflow//workflows/addition.ts//addition";
43041
+ registerStepFunction("step//workflows/addition.ts//add", add);
42985
43042
  // ../core/dist/runtime.js
42986
43043
  var import_functions4 = __toESM(require_functions(), 1);
42987
43044
  // ../core/dist/logger.js