@tangle-network/agent-integrations 0.53.24 → 0.53.26

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.
@@ -82,7 +82,9 @@ __export(adapters_exports, {
82
82
  azureAdConnector: () => azureAdConnector,
83
83
  azureBlobStorageConnector: () => azureBlobStorageConnector,
84
84
  azureCommunicationServicesConnector: () => azureCommunicationServicesConnector,
85
+ azureEventGridConnector: () => azureEventGridConnector,
85
86
  azureOpenaiConnector: () => azureOpenaiConnector,
87
+ azureServiceBusConnector: () => azureServiceBusConnector,
86
88
  backblazeConnector: () => backblazeConnector,
87
89
  bamboohrConnector: () => bamboohrConnector,
88
90
  bannerbearConnector: () => bannerbearConnector,
@@ -786,11 +788,11 @@ function declarativeRestConnector(spec) {
786
788
  const op = readOperation(spec, inv.capabilityName, "read");
787
789
  const response = await executeRestRequest(spec, op.request, inv, requiredArgsOf(op.parameters));
788
790
  if (response.outcome === "rate-limited") {
789
- const retryAfterMs5 = response.retryAfterMs ?? DEFAULT_RETRY_AFTER_MS;
791
+ const retryAfterMs7 = response.retryAfterMs ?? DEFAULT_RETRY_AFTER_MS;
790
792
  throw new ProviderRateLimited(
791
- `${spec.displayName} ${inv.capabilityName} rate limit (429); retry after ${retryAfterMs5}ms`,
793
+ `${spec.displayName} ${inv.capabilityName} rate limit (429); retry after ${retryAfterMs7}ms`,
792
794
  inv.source.id,
793
- { status: 429, body: response.data, retryAfterMs: retryAfterMs5 }
795
+ { status: 429, body: response.data, retryAfterMs: retryAfterMs7 }
794
796
  );
795
797
  }
796
798
  if (response.outcome === "conflict") {
@@ -11928,11 +11930,11 @@ async function azureRequest(credentials, inv, method, pathSegments, query2 = new
11928
11930
  throw new CredentialsExpired(`Azure Blob Storage rejected credentials (${response.status})`, inv.source.id);
11929
11931
  }
11930
11932
  if (response.status === 429 || response.status === 503) {
11931
- const retryAfterMs5 = retryAfter(response.headers.get("retry-after"));
11933
+ const retryAfterMs7 = retryAfter(response.headers.get("retry-after"));
11932
11934
  throw new ProviderRateLimited(
11933
- `Azure Blob Storage rate limit (${response.status}); retry after ${retryAfterMs5}ms`,
11935
+ `Azure Blob Storage rate limit (${response.status}); retry after ${retryAfterMs7}ms`,
11934
11936
  inv.source.id,
11935
- { status: response.status, retryAfterMs: retryAfterMs5 }
11937
+ { status: response.status, retryAfterMs: retryAfterMs7 }
11936
11938
  );
11937
11939
  }
11938
11940
  if (!response.ok) {
@@ -12205,6 +12207,878 @@ function numberOrUndefined(value) {
12205
12207
  return Number.isFinite(parsed) ? parsed : void 0;
12206
12208
  }
12207
12209
 
12210
+ // src/connectors/adapters/azure-event-grid.ts
12211
+ import { createHash as createHash3, timingSafeEqual } from "crypto";
12212
+ var API_VERSION2 = "2018-01-01";
12213
+ var MAX_BATCH_BYTES = 1024 * 1024;
12214
+ var MAX_EVENTS = 5e3;
12215
+ var EVENT_GRID_SUFFIXES = [
12216
+ ".eventgrid.azure.net",
12217
+ ".eventgrid.azure.us",
12218
+ ".eventgrid.azure.cn"
12219
+ ];
12220
+ var azureEventGridConnector = {
12221
+ manifest: {
12222
+ kind: "azure-event-grid",
12223
+ displayName: "Azure Event Grid",
12224
+ description: "Publish Event Grid and CloudEvents batches to customer topics and authenticate inbound subscription validation and event delivery.",
12225
+ auth: {
12226
+ kind: "api-key",
12227
+ hint: "JSON containing endpoint, accessKey, and deliverySecret. endpoint is the Azure custom topic or domain /api/events URL. Configure deliverySecret as the static x-tangle-eventgrid-secret delivery header on each Event Grid subscription."
12228
+ },
12229
+ category: "webhook",
12230
+ defaultConsistencyModel: "advisory",
12231
+ rateLimit: { requests: 600, windowMs: 6e4, scope: "data-source" },
12232
+ capabilities: [
12233
+ mutationCapability2(
12234
+ "events.publish",
12235
+ "Publish a bounded batch using the native Azure Event Grid event schema.",
12236
+ "Events require id, eventType, subject, eventTime, dataVersion, and data."
12237
+ ),
12238
+ mutationCapability2(
12239
+ "cloudEvents.publish",
12240
+ "Publish a bounded CloudEvents 1.0 batch.",
12241
+ "CloudEvents require id, source, type, specversion=1.0, and data."
12242
+ )
12243
+ ]
12244
+ },
12245
+ async executeMutation(inv) {
12246
+ const credentials = parseCredentials(inv.source.credentials, inv.source.id);
12247
+ const events = inv.capabilityName === "events.publish" ? eventGridEvents(inv.args.events) : inv.capabilityName === "cloudEvents.publish" ? cloudEvents(inv.args.events) : void 0;
12248
+ if (!events) throw new Error(`azure-event-grid: unknown mutation capability ${inv.capabilityName}`);
12249
+ const body = JSON.stringify(events);
12250
+ if (Buffer.byteLength(body) > MAX_BATCH_BYTES) {
12251
+ throw new Error(`Azure Event Grid batch exceeds ${MAX_BATCH_BYTES} bytes`);
12252
+ }
12253
+ const response = await fetch(publishUrl(credentials.endpoint), {
12254
+ method: "POST",
12255
+ headers: {
12256
+ "aeg-sas-key": credentials.accessKey,
12257
+ "content-type": inv.capabilityName === "cloudEvents.publish" ? "application/cloudevents-batch+json; charset=utf-8" : "application/json; charset=utf-8",
12258
+ accept: "application/json"
12259
+ },
12260
+ body
12261
+ });
12262
+ const responseBody = await readBoundedText(response, 256 * 1024);
12263
+ if (!response.ok) throwEventGridError(response, responseBody, inv);
12264
+ return {
12265
+ status: "committed",
12266
+ data: { accepted: true, count: events.length, requestId: response.headers.get("x-ms-request-id") ?? void 0 },
12267
+ committedAt: Date.now(),
12268
+ idempotentReplay: false
12269
+ };
12270
+ },
12271
+ verifySignature({ headers, source }) {
12272
+ let credentials;
12273
+ try {
12274
+ credentials = parseCredentials(source.credentials, source.id);
12275
+ } catch {
12276
+ return { valid: false, reason: "Azure Event Grid credentials are invalid" };
12277
+ }
12278
+ const provided = headerValue(headers, "x-tangle-eventgrid-secret");
12279
+ if (!provided) return { valid: false, reason: "Missing x-tangle-eventgrid-secret delivery header" };
12280
+ const expectedDigest = createHash3("sha256").update(credentials.deliverySecret).digest();
12281
+ const providedDigest = createHash3("sha256").update(provided).digest();
12282
+ return timingSafeEqual(expectedDigest, providedDigest) ? { valid: true } : { valid: false, reason: "Invalid x-tangle-eventgrid-secret delivery header" };
12283
+ },
12284
+ async handleInboundEvent({ rawBody }) {
12285
+ if (Buffer.byteLength(rawBody) > MAX_BATCH_BYTES) {
12286
+ throw new Error(`Azure Event Grid delivery exceeds ${MAX_BATCH_BYTES} bytes`);
12287
+ }
12288
+ let parsed;
12289
+ try {
12290
+ parsed = JSON.parse(rawBody);
12291
+ } catch {
12292
+ throw new Error("Azure Event Grid delivery body must be valid JSON");
12293
+ }
12294
+ const entries = Array.isArray(parsed) ? parsed : [parsed];
12295
+ if (entries.length > MAX_EVENTS) throw new Error(`Azure Event Grid delivery exceeds ${MAX_EVENTS} events`);
12296
+ const validation = entries.find((entry) => isValidationEvent(entry));
12297
+ if (validation && isRecord(validation.data) && typeof validation.data.validationCode === "string") {
12298
+ return {
12299
+ events: [],
12300
+ response: { status: 200, body: { validationResponse: validation.data.validationCode } }
12301
+ };
12302
+ }
12303
+ return {
12304
+ events: entries.map((entry, index) => inboundEvent(entry, index))
12305
+ };
12306
+ },
12307
+ async test(source) {
12308
+ try {
12309
+ parseCredentials(source.credentials, source.id);
12310
+ return { ok: true };
12311
+ } catch (error) {
12312
+ return { ok: false, reason: error instanceof Error ? error.message : "Azure Event Grid credentials are invalid" };
12313
+ }
12314
+ }
12315
+ };
12316
+ function mutationCapability2(name, description, eventDescription) {
12317
+ return {
12318
+ name,
12319
+ class: "mutation",
12320
+ description,
12321
+ parameters: {
12322
+ type: "object",
12323
+ properties: {
12324
+ events: {
12325
+ type: "array",
12326
+ minItems: 1,
12327
+ maxItems: MAX_EVENTS,
12328
+ description: eventDescription
12329
+ }
12330
+ },
12331
+ required: ["events"]
12332
+ },
12333
+ cas: "none",
12334
+ externalEffect: true
12335
+ };
12336
+ }
12337
+ function parseCredentials(credentials, dataSourceId) {
12338
+ if (credentials.kind !== "api-key") {
12339
+ throw new CredentialsExpired("Azure Event Grid requires a credential JSON bundle", dataSourceId);
12340
+ }
12341
+ let parsed;
12342
+ try {
12343
+ parsed = JSON.parse(credentials.apiKey);
12344
+ } catch {
12345
+ throw new CredentialsExpired("Azure Event Grid credentials must be valid JSON", dataSourceId);
12346
+ }
12347
+ if (!isRecord(parsed)) throw new CredentialsExpired("Azure Event Grid credentials must be a JSON object", dataSourceId);
12348
+ const endpointValue = credentialString(parsed.endpoint, "endpoint", dataSourceId);
12349
+ const accessKey = credentialString(parsed.accessKey, "accessKey", dataSourceId);
12350
+ const deliverySecret = credentialString(parsed.deliverySecret, "deliverySecret", dataSourceId);
12351
+ let endpoint;
12352
+ try {
12353
+ endpoint = new URL(endpointValue);
12354
+ } catch {
12355
+ throw new CredentialsExpired("Azure Event Grid endpoint is invalid", dataSourceId);
12356
+ }
12357
+ if (endpoint.protocol !== "https:" || endpoint.username || endpoint.password || endpoint.port || endpoint.search || endpoint.hash || endpoint.pathname.replace(/\/$/, "").toLowerCase() !== "/api/events" || !EVENT_GRID_SUFFIXES.some((suffix) => endpoint.hostname.endsWith(suffix))) {
12358
+ throw new CredentialsExpired("Azure Event Grid endpoint must be a public Azure custom topic or domain /api/events URL", dataSourceId);
12359
+ }
12360
+ if (!canonicalBase64(accessKey) || Buffer.from(accessKey, "base64").length < 16) {
12361
+ throw new CredentialsExpired("Azure Event Grid accessKey must be a valid base64 topic key", dataSourceId);
12362
+ }
12363
+ if (deliverySecret.length < 32 || deliverySecret.length > 4096) {
12364
+ throw new CredentialsExpired("Azure Event Grid deliverySecret must contain 32 to 4096 characters", dataSourceId);
12365
+ }
12366
+ endpoint.pathname = "/api/events";
12367
+ return { endpoint, accessKey, deliverySecret };
12368
+ }
12369
+ function publishUrl(endpoint) {
12370
+ const url = new URL(endpoint);
12371
+ url.searchParams.set("api-version", API_VERSION2);
12372
+ return url;
12373
+ }
12374
+ function eventGridEvents(value) {
12375
+ const entries = eventArray(value);
12376
+ return entries.map((entry, index) => {
12377
+ const result = {
12378
+ id: requiredString4(entry.id, `events[${index}].id`),
12379
+ eventType: requiredString4(entry.eventType, `events[${index}].eventType`),
12380
+ subject: requiredString4(entry.subject, `events[${index}].subject`),
12381
+ eventTime: isoDate(entry.eventTime, `events[${index}].eventTime`),
12382
+ dataVersion: requiredString4(entry.dataVersion, `events[${index}].dataVersion`),
12383
+ data: requiredJsonValue(entry.data, `events[${index}].data`)
12384
+ };
12385
+ if (entry.topic !== void 0) result.topic = requiredString4(entry.topic, `events[${index}].topic`);
12386
+ return result;
12387
+ });
12388
+ }
12389
+ function cloudEvents(value) {
12390
+ const entries = eventArray(value);
12391
+ return entries.map((entry, index) => {
12392
+ if (entry.specversion !== "1.0") throw new Error(`events[${index}].specversion must be 1.0`);
12393
+ const result = {
12394
+ specversion: "1.0",
12395
+ id: requiredString4(entry.id, `events[${index}].id`),
12396
+ source: requiredString4(entry.source, `events[${index}].source`),
12397
+ type: requiredString4(entry.type, `events[${index}].type`),
12398
+ data: requiredJsonValue(entry.data, `events[${index}].data`)
12399
+ };
12400
+ if (entry.subject !== void 0) result.subject = requiredString4(entry.subject, `events[${index}].subject`);
12401
+ if (entry.time !== void 0) result.time = isoDate(entry.time, `events[${index}].time`);
12402
+ if (entry.datacontenttype !== void 0) result.datacontenttype = requiredString4(entry.datacontenttype, `events[${index}].datacontenttype`);
12403
+ if (entry.dataschema !== void 0) result.dataschema = requiredString4(entry.dataschema, `events[${index}].dataschema`);
12404
+ return result;
12405
+ });
12406
+ }
12407
+ function eventArray(value) {
12408
+ if (!Array.isArray(value) || value.length < 1 || value.length > MAX_EVENTS) {
12409
+ throw new Error(`events must contain 1 to ${MAX_EVENTS} entries`);
12410
+ }
12411
+ return value.map((entry, index) => {
12412
+ if (!isRecord(entry)) throw new Error(`events[${index}] must be an object`);
12413
+ return entry;
12414
+ });
12415
+ }
12416
+ function inboundEvent(entry, index) {
12417
+ if (!isRecord(entry)) throw new Error(`Azure Event Grid delivery entry ${index} must be an object`);
12418
+ const eventType = typeof entry.eventType === "string" ? entry.eventType : typeof entry.type === "string" ? entry.type : "azure.event-grid.event";
12419
+ return {
12420
+ eventType,
12421
+ providerEventId: typeof entry.id === "string" ? entry.id : void 0,
12422
+ payload: entry
12423
+ };
12424
+ }
12425
+ function isValidationEvent(value) {
12426
+ return isRecord(value) && value.eventType === "Microsoft.EventGrid.SubscriptionValidationEvent";
12427
+ }
12428
+ function throwEventGridError(response, body, inv) {
12429
+ const redacted = body.replace(/[A-Za-z0-9+/]{32,}={0,2}/g, "[redacted]").slice(0, 500);
12430
+ if (response.status === 401) {
12431
+ throw new CredentialsExpired("Azure Event Grid rejected the topic access key", inv.source.id, {
12432
+ status: response.status,
12433
+ body: redacted
12434
+ });
12435
+ }
12436
+ if (response.status === 403) {
12437
+ throw new ProviderConfigError("Azure Event Grid topic policy rejected publishing", inv.source.id, {
12438
+ status: response.status,
12439
+ body: redacted
12440
+ });
12441
+ }
12442
+ if (response.status === 429 || response.status === 503) {
12443
+ throw new ProviderRateLimited("Azure Event Grid is throttling publishes", inv.source.id, {
12444
+ status: response.status,
12445
+ body: redacted,
12446
+ retryAfterMs: retryAfterMs3(response.headers.get("retry-after"))
12447
+ });
12448
+ }
12449
+ throw new Error(`Azure Event Grid publish failed with HTTP ${response.status}: ${redacted}`);
12450
+ }
12451
+ async function readBoundedText(response, limit) {
12452
+ const declared = Number(response.headers.get("content-length"));
12453
+ if (Number.isFinite(declared) && declared > limit) throw new Error(`Azure Event Grid response exceeds ${limit} bytes`);
12454
+ if (!response.body) return "";
12455
+ const reader = response.body.getReader();
12456
+ const chunks = [];
12457
+ let size = 0;
12458
+ while (true) {
12459
+ const { done, value } = await reader.read();
12460
+ if (done) break;
12461
+ size += value.byteLength;
12462
+ if (size > limit) {
12463
+ await reader.cancel();
12464
+ throw new Error(`Azure Event Grid response exceeds ${limit} bytes`);
12465
+ }
12466
+ chunks.push(value);
12467
+ }
12468
+ const body = new Uint8Array(size);
12469
+ let offset = 0;
12470
+ for (const chunk of chunks) {
12471
+ body.set(chunk, offset);
12472
+ offset += chunk.byteLength;
12473
+ }
12474
+ return new TextDecoder("utf-8", { fatal: true }).decode(body);
12475
+ }
12476
+ function headerValue(headers, name) {
12477
+ const match = Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1];
12478
+ return Array.isArray(match) ? match[0] : match;
12479
+ }
12480
+ function credentialString(value, field, dataSourceId) {
12481
+ if (typeof value !== "string" || value.trim() === "") {
12482
+ throw new CredentialsExpired(`Azure Event Grid ${field} is missing`, dataSourceId);
12483
+ }
12484
+ return value.trim();
12485
+ }
12486
+ function requiredString4(value, field) {
12487
+ if (typeof value !== "string" || value.trim() === "" || value.length > 4096) {
12488
+ throw new Error(`${field} must be a non-empty string no longer than 4096 characters`);
12489
+ }
12490
+ return value;
12491
+ }
12492
+ function isoDate(value, field) {
12493
+ const parsed = requiredString4(value, field);
12494
+ const date = new Date(parsed);
12495
+ if (!Number.isFinite(date.getTime())) throw new Error(`${field} must be an ISO 8601 timestamp`);
12496
+ return date.toISOString();
12497
+ }
12498
+ function requiredJsonValue(value, field) {
12499
+ if (value === void 0) throw new Error(`${field} is required`);
12500
+ try {
12501
+ if (JSON.stringify(value) === void 0) throw new Error("not JSON");
12502
+ } catch {
12503
+ throw new Error(`${field} must be JSON-serializable`);
12504
+ }
12505
+ return value;
12506
+ }
12507
+ function canonicalBase64(value) {
12508
+ return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value) && Buffer.from(value, "base64").toString("base64").replace(/=+$/, "") === value.replace(/=+$/, "");
12509
+ }
12510
+ function retryAfterMs3(value) {
12511
+ if (!value) return 6e4;
12512
+ const seconds = Number(value);
12513
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
12514
+ const date = Date.parse(value);
12515
+ return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 6e4;
12516
+ }
12517
+ function isRecord(value) {
12518
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12519
+ }
12520
+
12521
+ // src/connectors/adapters/azure-service-bus.ts
12522
+ import { createHmac as createHmac3 } from "crypto";
12523
+ var MANAGEMENT_API_VERSION = "2017-04";
12524
+ var MAX_RESPONSE_BYTES2 = 8 * 1024 * 1024;
12525
+ var MAX_MESSAGE_BYTES = 256 * 1024;
12526
+ var SERVICE_BUS_SUFFIXES = [
12527
+ ".servicebus.windows.net",
12528
+ ".servicebus.usgovcloudapi.net",
12529
+ ".servicebus.chinacloudapi.cn",
12530
+ ".servicebus.cloudapi.de"
12531
+ ];
12532
+ var azureServiceBusConnector = {
12533
+ manifest: {
12534
+ kind: "azure-service-bus",
12535
+ displayName: "Azure Service Bus",
12536
+ description: "Send and receive Azure Service Bus queue and topic messages and discover queue, topic, and subscription entities with a customer-owned SAS connection string.",
12537
+ auth: {
12538
+ kind: "api-key",
12539
+ hint: "Azure Service Bus connection string containing Endpoint, SharedAccessKeyName, and SharedAccessKey. EntityPath is supported and restricts this connection to that queue or topic."
12540
+ },
12541
+ category: "webhook",
12542
+ // The REST receive-and-delete operation destructively consumes a message,
12543
+ // and message delivery is at-least-once. Acceptance is not proof that a
12544
+ // downstream consumer processed the payload exactly once.
12545
+ defaultConsistencyModel: "advisory",
12546
+ rateLimit: { requests: 600, windowMs: 6e4, scope: "data-source" },
12547
+ capabilities: [
12548
+ readCapability2("queues.list", "List queues visible to a namespace-level Manage policy.", listProperties()),
12549
+ readCapability2("queues.get", "Get one queue description and message counts.", {
12550
+ queue: { type: "string" }
12551
+ }, ["queue"]),
12552
+ readCapability2("topics.list", "List topics visible to a namespace-level Manage policy.", listProperties()),
12553
+ readCapability2("topics.get", "Get one topic description and message counts.", {
12554
+ topic: { type: "string" }
12555
+ }, ["topic"]),
12556
+ readCapability2("subscriptions.list", "List subscriptions for one topic.", {
12557
+ topic: { type: "string" },
12558
+ ...listProperties()
12559
+ }, ["topic"]),
12560
+ readCapability2("subscriptions.get", "Get one topic subscription description and message counts.", {
12561
+ topic: { type: "string" },
12562
+ subscription: { type: "string" }
12563
+ }, ["topic", "subscription"]),
12564
+ mutationCapability3("queues.send", "Send a UTF-8 or base64 message to a queue.", sendProperties("queue"), ["queue", "content"]),
12565
+ mutationCapability3("topics.send", "Publish a UTF-8 or base64 message to a topic.", sendProperties("topic"), ["topic", "content"]),
12566
+ mutationCapability3("queues.receiveDelete", "Receive and permanently delete the next queue message.", {
12567
+ queue: { type: "string" },
12568
+ timeoutSeconds: { type: "integer", minimum: 0, maximum: 55 }
12569
+ }, ["queue"]),
12570
+ mutationCapability3("subscriptions.receiveDelete", "Receive and permanently delete the next message from a topic subscription.", {
12571
+ topic: { type: "string" },
12572
+ subscription: { type: "string" },
12573
+ timeoutSeconds: { type: "integer", minimum: 0, maximum: 55 }
12574
+ }, ["topic", "subscription"]),
12575
+ mutationCapability3("queues.deadLetters.receiveDelete", "Receive and permanently delete the next queue dead-letter message.", {
12576
+ queue: { type: "string" },
12577
+ timeoutSeconds: { type: "integer", minimum: 0, maximum: 55 }
12578
+ }, ["queue"]),
12579
+ mutationCapability3("subscriptions.deadLetters.receiveDelete", "Receive and permanently delete the next subscription dead-letter message.", {
12580
+ topic: { type: "string" },
12581
+ subscription: { type: "string" },
12582
+ timeoutSeconds: { type: "integer", minimum: 0, maximum: 55 }
12583
+ }, ["topic", "subscription"])
12584
+ ]
12585
+ },
12586
+ async executeRead(inv) {
12587
+ const credentials = parseConnectionString(inv.source.credentials, inv.source.id);
12588
+ let path;
12589
+ let list2 = false;
12590
+ switch (inv.capabilityName) {
12591
+ case "queues.list":
12592
+ requireNamespacePolicy(credentials, "queues.list");
12593
+ path = "$Resources/Queues";
12594
+ list2 = true;
12595
+ break;
12596
+ case "queues.get":
12597
+ path = entityName(inv.args.queue, "queue");
12598
+ enforceEntityPath(credentials, path);
12599
+ break;
12600
+ case "topics.list":
12601
+ requireNamespacePolicy(credentials, "topics.list");
12602
+ path = "$Resources/Topics";
12603
+ list2 = true;
12604
+ break;
12605
+ case "topics.get":
12606
+ path = entityName(inv.args.topic, "topic");
12607
+ enforceEntityPath(credentials, path);
12608
+ break;
12609
+ case "subscriptions.list": {
12610
+ const topic = entityName(inv.args.topic, "topic");
12611
+ enforceEntityPath(credentials, topic);
12612
+ path = `${topic}/Subscriptions/`;
12613
+ list2 = true;
12614
+ break;
12615
+ }
12616
+ case "subscriptions.get": {
12617
+ const topic = entityName(inv.args.topic, "topic");
12618
+ enforceEntityPath(credentials, topic);
12619
+ path = `${topic}/Subscriptions/${entityName(inv.args.subscription, "subscription")}`;
12620
+ break;
12621
+ }
12622
+ default:
12623
+ throw new Error(`azure-service-bus: unknown read capability ${inv.capabilityName}`);
12624
+ }
12625
+ const query2 = list2 ? managementListQuery(inv.args) : new URLSearchParams({ "api-version": MANAGEMENT_API_VERSION });
12626
+ const result = await serviceBusRequest(
12627
+ credentials,
12628
+ inv,
12629
+ "GET",
12630
+ path,
12631
+ query2
12632
+ );
12633
+ const xml = decodeUtf82(result.body);
12634
+ const data4 = list2 ? parseAtomFeed(xml) : parseAtomEntry(xml);
12635
+ return { data: data4, fetchedAt: Date.now() };
12636
+ },
12637
+ async executeMutation(inv) {
12638
+ const credentials = parseConnectionString(inv.source.credentials, inv.source.id);
12639
+ let data4;
12640
+ switch (inv.capabilityName) {
12641
+ case "queues.send":
12642
+ data4 = await sendMessage(credentials, inv, entityName(inv.args.queue, "queue"));
12643
+ break;
12644
+ case "topics.send":
12645
+ data4 = await sendMessage(credentials, inv, entityName(inv.args.topic, "topic"));
12646
+ break;
12647
+ case "queues.receiveDelete":
12648
+ data4 = await receiveAndDelete(credentials, inv, entityName(inv.args.queue, "queue"));
12649
+ break;
12650
+ case "subscriptions.receiveDelete":
12651
+ data4 = await receiveAndDelete(
12652
+ credentials,
12653
+ inv,
12654
+ `${entityName(inv.args.topic, "topic")}/subscriptions/${entityName(inv.args.subscription, "subscription")}`
12655
+ );
12656
+ break;
12657
+ case "queues.deadLetters.receiveDelete":
12658
+ data4 = await receiveAndDelete(
12659
+ credentials,
12660
+ inv,
12661
+ `${entityName(inv.args.queue, "queue")}/$DeadLetterQueue`
12662
+ );
12663
+ break;
12664
+ case "subscriptions.deadLetters.receiveDelete":
12665
+ data4 = await receiveAndDelete(
12666
+ credentials,
12667
+ inv,
12668
+ `${entityName(inv.args.topic, "topic")}/subscriptions/${entityName(inv.args.subscription, "subscription")}/$DeadLetterQueue`
12669
+ );
12670
+ break;
12671
+ default:
12672
+ throw new Error(`azure-service-bus: unknown mutation capability ${inv.capabilityName}`);
12673
+ }
12674
+ return {
12675
+ status: "committed",
12676
+ data: data4,
12677
+ committedAt: Date.now(),
12678
+ idempotentReplay: false
12679
+ };
12680
+ },
12681
+ async test(source) {
12682
+ try {
12683
+ parseConnectionString(source.credentials, source.id);
12684
+ return { ok: true };
12685
+ } catch (error) {
12686
+ return { ok: false, reason: error instanceof Error ? error.message : "Azure Service Bus connection string is invalid" };
12687
+ }
12688
+ }
12689
+ };
12690
+ function readCapability2(name, description, properties, required = []) {
12691
+ return {
12692
+ name,
12693
+ class: "read",
12694
+ description,
12695
+ parameters: { type: "object", properties, ...required.length ? { required } : {} }
12696
+ };
12697
+ }
12698
+ function mutationCapability3(name, description, properties, required) {
12699
+ return {
12700
+ name,
12701
+ class: "mutation",
12702
+ description,
12703
+ parameters: { type: "object", properties, required },
12704
+ cas: "none",
12705
+ externalEffect: true
12706
+ };
12707
+ }
12708
+ function sendProperties(entity) {
12709
+ return {
12710
+ [entity]: { type: "string" },
12711
+ content: { type: "string", description: "UTF-8 text or canonical base64 message body." },
12712
+ encoding: { type: "string", enum: ["utf-8", "base64"], default: "utf-8" },
12713
+ contentType: { type: "string" },
12714
+ brokerProperties: {
12715
+ type: "object",
12716
+ description: "Allowed broker properties such as MessageId, CorrelationId, Label, SessionId, TimeToLive, and ScheduledEnqueueTimeUtc."
12717
+ },
12718
+ applicationProperties: {
12719
+ type: "object",
12720
+ description: "Application property headers with string, number, or boolean values."
12721
+ }
12722
+ };
12723
+ }
12724
+ function listProperties() {
12725
+ return {
12726
+ skip: { type: "integer", minimum: 0 },
12727
+ top: { type: "integer", minimum: 1, maximum: 1e3 }
12728
+ };
12729
+ }
12730
+ function managementListQuery(args) {
12731
+ const query2 = new URLSearchParams({ "api-version": MANAGEMENT_API_VERSION });
12732
+ if (args.skip !== void 0) query2.set("$skip", String(boundedInteger(args.skip, "skip", 0, 1e6)));
12733
+ if (args.top !== void 0) query2.set("$top", String(boundedInteger(args.top, "top", 1, 1e3)));
12734
+ return query2;
12735
+ }
12736
+ function parseConnectionString(credentials, dataSourceId) {
12737
+ if (credentials.kind !== "api-key") {
12738
+ throw new CredentialsExpired("Azure Service Bus requires a connection string", dataSourceId);
12739
+ }
12740
+ const values = /* @__PURE__ */ new Map();
12741
+ for (const part of credentials.apiKey.split(";")) {
12742
+ if (!part.trim()) continue;
12743
+ const separator = part.indexOf("=");
12744
+ if (separator <= 0) {
12745
+ throw new CredentialsExpired("Azure Service Bus connection string is malformed", dataSourceId);
12746
+ }
12747
+ const name = part.slice(0, separator).trim().toLowerCase();
12748
+ if (values.has(name)) {
12749
+ throw new CredentialsExpired(`Azure Service Bus connection string repeats ${name}`, dataSourceId);
12750
+ }
12751
+ values.set(name, part.slice(separator + 1).trim());
12752
+ }
12753
+ const endpointValue = values.get("endpoint");
12754
+ const keyName = values.get("sharedaccesskeyname");
12755
+ const keyValue = values.get("sharedaccesskey");
12756
+ if (!endpointValue || !keyName || !keyValue) {
12757
+ throw new CredentialsExpired("Azure Service Bus connection string is missing Endpoint, SharedAccessKeyName, or SharedAccessKey", dataSourceId);
12758
+ }
12759
+ let endpoint;
12760
+ try {
12761
+ endpoint = new URL(endpointValue.replace(/^sb:/i, "https:"));
12762
+ } catch {
12763
+ throw new CredentialsExpired("Azure Service Bus Endpoint is invalid", dataSourceId);
12764
+ }
12765
+ if (endpoint.protocol !== "https:" || endpoint.username || endpoint.password || endpoint.port || endpoint.search || endpoint.hash || endpoint.pathname !== "/" || !SERVICE_BUS_SUFFIXES.some((suffix) => endpoint.hostname.endsWith(suffix))) {
12766
+ throw new CredentialsExpired("Azure Service Bus Endpoint must be a public Azure Service Bus namespace", dataSourceId);
12767
+ }
12768
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,255}$/.test(keyName)) {
12769
+ throw new CredentialsExpired("Azure Service Bus SharedAccessKeyName is invalid", dataSourceId);
12770
+ }
12771
+ let key;
12772
+ try {
12773
+ key = Buffer.from(keyValue, "base64");
12774
+ } catch {
12775
+ throw new CredentialsExpired("Azure Service Bus SharedAccessKey is invalid base64", dataSourceId);
12776
+ }
12777
+ if (key.length < 16 || key.toString("base64").replace(/=+$/, "") !== keyValue.replace(/=+$/, "")) {
12778
+ throw new CredentialsExpired("Azure Service Bus SharedAccessKey is invalid base64", dataSourceId);
12779
+ }
12780
+ const entityPathValue = values.get("entitypath");
12781
+ const entityPath = entityPathValue ? entityName(entityPathValue, "EntityPath") : void 0;
12782
+ return { endpoint, keyName, key, entityPath };
12783
+ }
12784
+ async function sendMessage(credentials, inv, entityPath) {
12785
+ enforceEntityPath(credentials, entityPath);
12786
+ const content = requiredString5(inv.args.content, "content", true);
12787
+ const encoding = inv.args.encoding === void 0 ? "utf-8" : enumValue(inv.args.encoding, "encoding", ["utf-8", "base64"]);
12788
+ const body = encoding === "base64" ? strictBase64(content) : Buffer.from(content, "utf8");
12789
+ if (body.byteLength > MAX_MESSAGE_BYTES) {
12790
+ throw new Error(`Azure Service Bus message exceeds ${MAX_MESSAGE_BYTES} bytes`);
12791
+ }
12792
+ const headers = {
12793
+ "content-type": inv.args.contentType === void 0 ? "application/octet-stream" : requiredHeaderValue(inv.args.contentType, "contentType")
12794
+ };
12795
+ const brokerProperties = allowedBrokerProperties(inv.args.brokerProperties);
12796
+ if (brokerProperties) {
12797
+ const serializedBrokerProperties = JSON.stringify(brokerProperties);
12798
+ if (Buffer.byteLength(serializedBrokerProperties) > 16 * 1024) {
12799
+ throw new Error("brokerProperties exceeds 16384 bytes");
12800
+ }
12801
+ headers.BrokerProperties = serializedBrokerProperties;
12802
+ }
12803
+ Object.assign(headers, applicationPropertyHeaders(inv.args.applicationProperties));
12804
+ const result = await serviceBusRequest(credentials, inv, "POST", `${entityPath}/messages`, void 0, headers, body);
12805
+ return {
12806
+ accepted: true,
12807
+ entityPath,
12808
+ size: body.byteLength,
12809
+ location: result.response.headers.get("location") ?? void 0
12810
+ };
12811
+ }
12812
+ async function receiveAndDelete(credentials, inv, entityPath) {
12813
+ enforceEntityPath(credentials, entityPath);
12814
+ const timeoutSeconds = inv.args.timeoutSeconds === void 0 ? 0 : boundedInteger(inv.args.timeoutSeconds, "timeoutSeconds", 0, 55);
12815
+ const result = await serviceBusRequest(
12816
+ credentials,
12817
+ inv,
12818
+ "DELETE",
12819
+ `${entityPath}/messages/head`,
12820
+ new URLSearchParams({ timeout: String(timeoutSeconds) }),
12821
+ void 0,
12822
+ void 0,
12823
+ [200, 204]
12824
+ );
12825
+ if (result.response.status === 204) return { message: null };
12826
+ const brokerPropertiesHeader = result.response.headers.get("brokerproperties");
12827
+ let brokerProperties;
12828
+ if (brokerPropertiesHeader) {
12829
+ try {
12830
+ brokerProperties = JSON.parse(brokerPropertiesHeader);
12831
+ } catch {
12832
+ throw new Error("Azure Service Bus returned invalid BrokerProperties JSON");
12833
+ }
12834
+ }
12835
+ return {
12836
+ message: {
12837
+ body: Buffer.from(result.body).toString("base64"),
12838
+ encoding: "base64",
12839
+ contentType: result.response.headers.get("content-type") ?? "application/octet-stream",
12840
+ brokerProperties,
12841
+ applicationProperties: responseApplicationProperties(result.response.headers)
12842
+ }
12843
+ };
12844
+ }
12845
+ async function serviceBusRequest(credentials, inv, method, path, query2, headers = {}, body, acceptedStatuses = [200, 201, 202, 204]) {
12846
+ const url = new URL(path.split("/").map(encodePathSegment2).join("/"), credentials.endpoint);
12847
+ if (query2) url.search = query2.toString();
12848
+ const resourceUri = `${url.origin}${url.pathname}`;
12849
+ const expiry = Math.floor(Date.now() / 1e3) + 300;
12850
+ const encodedResourceUri = encodeURIComponent(resourceUri);
12851
+ const signature = createHmac3("sha256", credentials.key).update(`${encodedResourceUri}
12852
+ ${expiry}`, "utf8").digest("base64");
12853
+ const authorization = `SharedAccessSignature sr=${encodedResourceUri}&sig=${encodeURIComponent(signature)}&se=${expiry}&skn=${encodeURIComponent(credentials.keyName)}`;
12854
+ const response = await fetch(url, {
12855
+ method,
12856
+ headers: { authorization, accept: "application/atom+xml, application/xml, */*", ...headers },
12857
+ body: body === void 0 ? void 0 : Uint8Array.from(body).buffer
12858
+ });
12859
+ const responseBody = await readBounded(response, MAX_RESPONSE_BYTES2);
12860
+ if (acceptedStatuses.includes(response.status)) return { response, body: responseBody };
12861
+ const text = decodeUtf82(responseBody);
12862
+ if (response.status === 401) {
12863
+ throw new CredentialsExpired("Azure Service Bus rejected the shared access signature", inv.source.id, {
12864
+ status: response.status,
12865
+ body: redactProviderText(text)
12866
+ });
12867
+ }
12868
+ if (response.status === 403) {
12869
+ throw new ProviderConfigError("Azure Service Bus policy lacks permission for this operation", inv.source.id, {
12870
+ status: response.status,
12871
+ body: redactProviderText(text)
12872
+ });
12873
+ }
12874
+ if (response.status === 429 || response.status === 503) {
12875
+ throw new ProviderRateLimited("Azure Service Bus is throttling requests", inv.source.id, {
12876
+ status: response.status,
12877
+ body: redactProviderText(text),
12878
+ retryAfterMs: retryAfterMs4(response.headers.get("retry-after"))
12879
+ });
12880
+ }
12881
+ throw new Error(`Azure Service Bus request failed with HTTP ${response.status}: ${redactProviderText(text).slice(0, 500)}`);
12882
+ }
12883
+ function encodePathSegment2(segment) {
12884
+ if (segment === "$Resources" || segment === "$DeadLetterQueue") return segment;
12885
+ return encodeURIComponent(segment);
12886
+ }
12887
+ function entityName(value, field) {
12888
+ const name = requiredString5(value, field);
12889
+ if (!/^[A-Za-z0-9][A-Za-z0-9._~-]{0,259}$/.test(name)) {
12890
+ throw new Error(`${field} must be a valid Azure Service Bus entity name`);
12891
+ }
12892
+ return name;
12893
+ }
12894
+ function requireNamespacePolicy(credentials, capability) {
12895
+ if (credentials.entityPath) {
12896
+ throw new Error(`${capability} requires a namespace-level connection string without EntityPath`);
12897
+ }
12898
+ }
12899
+ function enforceEntityPath(credentials, requestedPath) {
12900
+ if (!credentials.entityPath) return;
12901
+ const normalized = requestedPath.toLowerCase();
12902
+ const allowed = credentials.entityPath.toLowerCase();
12903
+ if (normalized !== allowed && normalized !== `${allowed}/$deadletterqueue` && !normalized.startsWith(`${allowed}/subscriptions/`)) {
12904
+ throw new Error(`Connection string EntityPath restricts access to ${credentials.entityPath}`);
12905
+ }
12906
+ }
12907
+ var BROKER_PROPERTY_NAMES = /* @__PURE__ */ new Set([
12908
+ "CorrelationId",
12909
+ "SessionId",
12910
+ "Label",
12911
+ "MessageId",
12912
+ "ReplyTo",
12913
+ "ReplyToSessionId",
12914
+ "To",
12915
+ "TimeToLive",
12916
+ "ScheduledEnqueueTimeUtc",
12917
+ "PartitionKey",
12918
+ "ViaPartitionKey",
12919
+ "ForcePersistence"
12920
+ ]);
12921
+ function allowedBrokerProperties(value) {
12922
+ if (value === void 0) return void 0;
12923
+ if (!isRecord2(value)) throw new Error("brokerProperties must be an object");
12924
+ const entries = Object.entries(value);
12925
+ if (entries.length > BROKER_PROPERTY_NAMES.size) throw new Error("brokerProperties contains too many fields");
12926
+ const result = {};
12927
+ for (const [key, property] of entries) {
12928
+ if (!BROKER_PROPERTY_NAMES.has(key)) throw new Error(`brokerProperties.${key} is not allowed`);
12929
+ if (!["string", "number", "boolean"].includes(typeof property) || !Number.isFinite(typeof property === "number" ? property : 0)) {
12930
+ throw new Error(`brokerProperties.${key} must be a finite string, number, or boolean`);
12931
+ }
12932
+ if (typeof property === "string") requiredHeaderValue(property, `brokerProperties.${key}`);
12933
+ result[key] = property;
12934
+ }
12935
+ return result;
12936
+ }
12937
+ var RESERVED_HEADERS = /* @__PURE__ */ new Set([
12938
+ "authorization",
12939
+ "brokerproperties",
12940
+ "content-length",
12941
+ "content-type",
12942
+ "host"
12943
+ ]);
12944
+ function applicationPropertyHeaders(value) {
12945
+ if (value === void 0) return {};
12946
+ if (!isRecord2(value)) throw new Error("applicationProperties must be an object");
12947
+ const entries = Object.entries(value);
12948
+ if (entries.length > 64) throw new Error("applicationProperties cannot contain more than 64 entries");
12949
+ const result = {};
12950
+ let size = 0;
12951
+ for (const [key, property] of entries) {
12952
+ if (!/^[A-Za-z][A-Za-z0-9-]{0,63}$/.test(key) || RESERVED_HEADERS.has(key.toLowerCase()) || key.toLowerCase().startsWith("x-ms-")) {
12953
+ throw new Error(`applicationProperties.${key} is not a safe header name`);
12954
+ }
12955
+ if (!["string", "number", "boolean"].includes(typeof property)) {
12956
+ throw new Error(`applicationProperties.${key} must be a string, number, or boolean`);
12957
+ }
12958
+ if (typeof property === "number" && !Number.isFinite(property)) {
12959
+ throw new Error(`applicationProperties.${key} must be finite`);
12960
+ }
12961
+ const headerValue2 = requiredHeaderValue(String(property), `applicationProperties.${key}`);
12962
+ size += Buffer.byteLength(key) + Buffer.byteLength(headerValue2);
12963
+ if (size > 32 * 1024) throw new Error("applicationProperties exceeds 32768 bytes");
12964
+ result[key] = headerValue2;
12965
+ }
12966
+ return result;
12967
+ }
12968
+ function responseApplicationProperties(headers) {
12969
+ const result = {};
12970
+ for (const [key, value] of headers.entries()) {
12971
+ if (!RESERVED_HEADERS.has(key.toLowerCase()) && !key.toLowerCase().startsWith("x-ms-") && key.toLowerCase() !== "date" && key.toLowerCase() !== "server" && key.toLowerCase() !== "transfer-encoding") result[key] = value;
12972
+ }
12973
+ return result;
12974
+ }
12975
+ function parseAtomFeed(xml) {
12976
+ const nextLink = xml.match(/<link\b(?=[^>]*\brel=["']next["'])(?=[^>]*\bhref=["']([^"']+)["'])[^>]*\/?>/i)?.[1];
12977
+ return {
12978
+ entries: [...xml.matchAll(/<entry\b[^>]*>([\s\S]*?)<\/entry>/gi)].map((match) => parseAtomEntry(match[0])),
12979
+ ...nextLink ? { nextLink: decodeXml2(nextLink) } : {}
12980
+ };
12981
+ }
12982
+ function parseAtomEntry(xml) {
12983
+ const title = xmlValue(xml, "title");
12984
+ const id2 = xmlValue(xml, "id");
12985
+ const updated = xmlValue(xml, "updated");
12986
+ const properties = {};
12987
+ for (const match of xml.matchAll(/<(?:[A-Za-z0-9]+:)?([A-Za-z][A-Za-z0-9]*)\b[^>]*>([^<]*)<\/(?:[A-Za-z0-9]+:)?\1>/g)) {
12988
+ const key = match[1];
12989
+ if (["title", "id", "updated"].includes(key.toLowerCase())) continue;
12990
+ const raw = decodeXml2(match[2]);
12991
+ properties[key] = xmlScalar(raw);
12992
+ }
12993
+ return { title, id: id2, updated, properties };
12994
+ }
12995
+ function xmlValue(xml, tag) {
12996
+ const match = xml.match(new RegExp(`<(?:[A-Za-z0-9]+:)?${tag}\\b[^>]*>([^<]*)<\\/(?:[A-Za-z0-9]+:)?${tag}>`, "i"));
12997
+ return match ? decodeXml2(match[1]) : void 0;
12998
+ }
12999
+ function xmlScalar(value) {
13000
+ if (value === "true") return true;
13001
+ if (value === "false") return false;
13002
+ if (/^-?\d+$/.test(value)) {
13003
+ const parsed = Number(value);
13004
+ if (Number.isSafeInteger(parsed)) return parsed;
13005
+ }
13006
+ return value;
13007
+ }
13008
+ function decodeXml2(value) {
13009
+ return value.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
13010
+ }
13011
+ async function readBounded(response, limit) {
13012
+ const declared = Number(response.headers.get("content-length"));
13013
+ if (Number.isFinite(declared) && declared > limit) throw new Error(`Azure Service Bus response exceeds ${limit} bytes`);
13014
+ if (!response.body) return new Uint8Array();
13015
+ const reader = response.body.getReader();
13016
+ const chunks = [];
13017
+ let size = 0;
13018
+ while (true) {
13019
+ const { done, value } = await reader.read();
13020
+ if (done) break;
13021
+ size += value.byteLength;
13022
+ if (size > limit) {
13023
+ await reader.cancel();
13024
+ throw new Error(`Azure Service Bus response exceeds ${limit} bytes`);
13025
+ }
13026
+ chunks.push(value);
13027
+ }
13028
+ const body = new Uint8Array(size);
13029
+ let offset = 0;
13030
+ for (const chunk of chunks) {
13031
+ body.set(chunk, offset);
13032
+ offset += chunk.byteLength;
13033
+ }
13034
+ return body;
13035
+ }
13036
+ function strictBase64(value) {
13037
+ if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
13038
+ throw new Error("content must be canonical base64 when encoding=base64");
13039
+ }
13040
+ return Buffer.from(value, "base64");
13041
+ }
13042
+ function requiredString5(value, field, allowEmpty = false) {
13043
+ if (typeof value !== "string" || !allowEmpty && value.trim() === "") {
13044
+ throw new Error(`${field} must be ${allowEmpty ? "a string" : "a non-empty string"}`);
13045
+ }
13046
+ return allowEmpty ? value : value.trim();
13047
+ }
13048
+ function requiredHeaderValue(value, field) {
13049
+ const parsed = requiredString5(value, field);
13050
+ if (/\r|\n/.test(parsed) || parsed.length > 4096) throw new Error(`${field} is not a safe header value`);
13051
+ return parsed;
13052
+ }
13053
+ function boundedInteger(value, field, minimum, maximum) {
13054
+ if (!Number.isInteger(value) || value < minimum || value > maximum) {
13055
+ throw new Error(`${field} must be an integer from ${minimum} to ${maximum}`);
13056
+ }
13057
+ return value;
13058
+ }
13059
+ function enumValue(value, field, choices) {
13060
+ if (typeof value !== "string" || !choices.includes(value)) {
13061
+ throw new Error(`${field} must be one of ${choices.join(", ")}`);
13062
+ }
13063
+ return value;
13064
+ }
13065
+ function decodeUtf82(value) {
13066
+ return new TextDecoder("utf-8", { fatal: true }).decode(value);
13067
+ }
13068
+ function retryAfterMs4(value) {
13069
+ if (!value) return 6e4;
13070
+ const seconds = Number(value);
13071
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
13072
+ const date = Date.parse(value);
13073
+ return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 6e4;
13074
+ }
13075
+ function redactProviderText(value) {
13076
+ return value.replace(/SharedAccessSignature\s+[^\s<]+/gi, "SharedAccessSignature [redacted]").replace(/SharedAccessKey=[^;\s<]+/gi, "SharedAccessKey=[redacted]");
13077
+ }
13078
+ function isRecord2(value) {
13079
+ return typeof value === "object" && value !== null && !Array.isArray(value);
13080
+ }
13081
+
12208
13082
  // src/connectors/adapters/basecamp.ts
12209
13083
  var basecampConnector = declarativeRestConnector({
12210
13084
  kind: "basecamp",
@@ -18735,7 +19609,7 @@ var checkoutConnector = declarativeRestConnector({
18735
19609
  });
18736
19610
 
18737
19611
  // src/connectors/adapters/docuseal.ts
18738
- import { createHmac as createHmac3, timingSafeEqual } from "crypto";
19612
+ import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual2 } from "crypto";
18739
19613
  var DEFAULT_BASE = "https://api.docuseal.com";
18740
19614
  function readDocuSealCredentials(creds) {
18741
19615
  if (creds.kind === "api-key" && typeof creds.apiKey === "string" && creds.apiKey.length > 0) {
@@ -18860,11 +19734,11 @@ function docuseal(opts = {}) {
18860
19734
  if (!creds?.webhookSecret) return { valid: false, reason: "missing_webhook_secret" };
18861
19735
  const sig = firstHeader(headers, "x-docuseal-signature");
18862
19736
  if (!sig) return { valid: false, reason: "missing_signature_header" };
18863
- const expected = createHmac3("sha256", creds.webhookSecret).update(rawBody).digest("hex");
19737
+ const expected = createHmac4("sha256", creds.webhookSecret).update(rawBody).digest("hex");
18864
19738
  const a = Buffer.from(sig.toLowerCase(), "utf-8");
18865
19739
  const b = Buffer.from(expected, "utf-8");
18866
19740
  if (a.length !== b.length) return { valid: false, reason: "invalid_signature" };
18867
- return timingSafeEqual(a, b) ? { valid: true } : { valid: false, reason: "invalid_signature" };
19741
+ return timingSafeEqual2(a, b) ? { valid: true } : { valid: false, reason: "invalid_signature" };
18868
19742
  },
18869
19743
  async handleInboundEvent({ rawBody }) {
18870
19744
  let parsed;
@@ -22482,7 +23356,7 @@ var frontConnector = declarativeRestConnector({
22482
23356
  });
22483
23357
 
22484
23358
  // src/connectors/oauth.ts
22485
- import { createHash as createHash3, randomBytes } from "crypto";
23359
+ import { createHash as createHash4, randomBytes } from "crypto";
22486
23360
  var PENDING_TTL_MS = 10 * 60 * 1e3;
22487
23361
  var InMemoryOAuthFlowStore = class {
22488
23362
  pendingFlows = /* @__PURE__ */ new Map();
@@ -22510,7 +23384,7 @@ function startOAuthFlow(input) {
22510
23384
  const now = input.now ?? Date.now();
22511
23385
  store.sweep?.(now);
22512
23386
  const codeVerifier = base64Url(randomBytes(48));
22513
- const codeChallenge = base64Url(createHash3("sha256").update(codeVerifier).digest());
23387
+ const codeChallenge = base64Url(createHash4("sha256").update(codeVerifier).digest());
22514
23388
  const state = base64Url(randomBytes(24));
22515
23389
  store.put(state, {
22516
23390
  codeVerifier,
@@ -24429,11 +25303,11 @@ var googleCloudStorageConnector = declarativeRestConnector({
24429
25303
  });
24430
25304
 
24431
25305
  // src/connectors/adapters/google-pubsub.ts
24432
- import { createHash as createHash4, createSign } from "crypto";
25306
+ import { createHash as createHash5, createSign } from "crypto";
24433
25307
  var TOKEN_URL3 = "https://oauth2.googleapis.com/token";
24434
25308
  var API_ROOT = "https://pubsub.googleapis.com/v1";
24435
25309
  var PUBSUB_SCOPE = "https://www.googleapis.com/auth/pubsub";
24436
- var MAX_RESPONSE_BYTES2 = 8 * 1024 * 1024;
25310
+ var MAX_RESPONSE_BYTES3 = 8 * 1024 * 1024;
24437
25311
  var MAX_REQUEST_BYTES = 1e7;
24438
25312
  var MAX_TOKEN_CACHE_ENTRIES = 256;
24439
25313
  var tokenCache = /* @__PURE__ */ new Map();
@@ -24454,14 +25328,14 @@ var googlePubSubConnector = {
24454
25328
  defaultConsistencyModel: "advisory",
24455
25329
  rateLimit: { requests: 600, windowMs: 6e4, scope: "data-source" },
24456
25330
  capabilities: [
24457
- readCapability2("topics.list", "List topics in the service account project.", {
25331
+ readCapability3("topics.list", "List topics in the service account project.", {
24458
25332
  pageSize: { type: "integer", minimum: 1, maximum: 1e3 },
24459
25333
  pageToken: { type: "string" }
24460
25334
  }),
24461
- readCapability2("topics.get", "Get one topic and its server-side configuration.", {
25335
+ readCapability3("topics.get", "Get one topic and its server-side configuration.", {
24462
25336
  topic: { type: "string", description: "Topic ID in the service account project." }
24463
25337
  }, ["topic"]),
24464
- mutationCapability2("topics.create", "Create a topic in the service account project.", {
25338
+ mutationCapability4("topics.create", "Create a topic in the service account project.", {
24465
25339
  topic: { type: "string" },
24466
25340
  labels: { type: "object", additionalProperties: { type: "string" } },
24467
25341
  allowedPersistenceRegions: { type: "array", items: { type: "string" } },
@@ -24469,10 +25343,10 @@ var googlePubSubConnector = {
24469
25343
  schema: { type: "string", description: "Full Pub/Sub schema resource name." },
24470
25344
  schemaEncoding: { type: "string", enum: ["JSON", "BINARY"] }
24471
25345
  }, ["topic"]),
24472
- mutationCapability2("topics.delete", "Delete a topic. Existing subscriptions remain but stop receiving messages.", {
25346
+ mutationCapability4("topics.delete", "Delete a topic. Existing subscriptions remain but stop receiving messages.", {
24473
25347
  topic: { type: "string" }
24474
25348
  }, ["topic"]),
24475
- mutationCapability2("messages.publish", "Publish up to 1,000 messages to a topic.", {
25349
+ mutationCapability4("messages.publish", "Publish up to 1,000 messages to a topic.", {
24476
25350
  topic: { type: "string" },
24477
25351
  messages: {
24478
25352
  type: "array",
@@ -24481,14 +25355,14 @@ var googlePubSubConnector = {
24481
25355
  description: "Messages with either text (UTF-8) or data (base64), plus optional string attributes and orderingKey."
24482
25356
  }
24483
25357
  }, ["topic", "messages"]),
24484
- readCapability2("subscriptions.list", "List subscriptions in the service account project.", {
25358
+ readCapability3("subscriptions.list", "List subscriptions in the service account project.", {
24485
25359
  pageSize: { type: "integer", minimum: 1, maximum: 1e3 },
24486
25360
  pageToken: { type: "string" }
24487
25361
  }),
24488
- readCapability2("subscriptions.get", "Get one subscription and its delivery configuration.", {
25362
+ readCapability3("subscriptions.get", "Get one subscription and its delivery configuration.", {
24489
25363
  subscription: { type: "string" }
24490
25364
  }, ["subscription"]),
24491
- mutationCapability2("subscriptions.create", "Create a pull subscription for a topic.", {
25365
+ mutationCapability4("subscriptions.create", "Create a pull subscription for a topic.", {
24492
25366
  subscription: { type: "string" },
24493
25367
  topic: { type: "string" },
24494
25368
  ackDeadlineSeconds: { type: "integer", minimum: 10, maximum: 600 },
@@ -24504,18 +25378,18 @@ var googlePubSubConnector = {
24504
25378
  enableExactlyOnceDelivery: { type: "boolean" },
24505
25379
  labels: { type: "object", additionalProperties: { type: "string" } }
24506
25380
  }, ["subscription", "topic"]),
24507
- mutationCapability2("subscriptions.delete", "Delete a subscription and discard its retained messages.", {
25381
+ mutationCapability4("subscriptions.delete", "Delete a subscription and discard its retained messages.", {
24508
25382
  subscription: { type: "string" }
24509
25383
  }, ["subscription"]),
24510
- mutationCapability2("messages.pull", "Pull messages and make them temporarily unavailable to other subscribers.", {
25384
+ mutationCapability4("messages.pull", "Pull messages and make them temporarily unavailable to other subscribers.", {
24511
25385
  subscription: { type: "string" },
24512
25386
  maxMessages: { type: "integer", minimum: 1, maximum: 1e3 }
24513
25387
  }, ["subscription", "maxMessages"]),
24514
- mutationCapability2("messages.acknowledge", "Acknowledge delivered messages by ack ID.", {
25388
+ mutationCapability4("messages.acknowledge", "Acknowledge delivered messages by ack ID.", {
24515
25389
  subscription: { type: "string" },
24516
25390
  ackIds: { type: "array", minItems: 1, maxItems: 1e3, items: { type: "string" } }
24517
25391
  }, ["subscription", "ackIds"]),
24518
- mutationCapability2("messages.modifyAckDeadline", "Change the acknowledgement deadline for delivered messages.", {
25392
+ mutationCapability4("messages.modifyAckDeadline", "Change the acknowledgement deadline for delivered messages.", {
24519
25393
  subscription: { type: "string" },
24520
25394
  ackIds: { type: "array", minItems: 1, maxItems: 1e3, items: { type: "string" } },
24521
25395
  ackDeadlineSeconds: { type: "integer", minimum: 0, maximum: 600 }
@@ -24553,11 +25427,11 @@ var googlePubSubConnector = {
24553
25427
  if (labels) body.labels = labels;
24554
25428
  const regions2 = optionalStringArray(inv.args.allowedPersistenceRegions, "allowedPersistenceRegions");
24555
25429
  if (regions2) body.messageStoragePolicy = { allowedPersistenceRegions: regions2 };
24556
- if (inv.args.kmsKeyName !== void 0) body.kmsKeyName = requiredString4(inv.args.kmsKeyName, "kmsKeyName");
25430
+ if (inv.args.kmsKeyName !== void 0) body.kmsKeyName = requiredString6(inv.args.kmsKeyName, "kmsKeyName");
24557
25431
  if (inv.args.schema !== void 0) {
24558
25432
  body.schemaSettings = {
24559
- schema: requiredString4(inv.args.schema, "schema"),
24560
- ...inv.args.schemaEncoding === void 0 ? {} : { encoding: enumValue(inv.args.schemaEncoding, "schemaEncoding", ["JSON", "BINARY"]) }
25433
+ schema: requiredString6(inv.args.schema, "schema"),
25434
+ ...inv.args.schemaEncoding === void 0 ? {} : { encoding: enumValue2(inv.args.schemaEncoding, "schemaEncoding", ["JSON", "BINARY"]) }
24561
25435
  };
24562
25436
  }
24563
25437
  data4 = await pubSubRequest(credentials, inv, "PUT", topicPath(credentials, inv.args.topic), void 0, body);
@@ -24596,7 +25470,7 @@ var googlePubSubConnector = {
24596
25470
  "POST",
24597
25471
  `${subscriptionPath(credentials, inv.args.subscription)}:pull`,
24598
25472
  void 0,
24599
- { maxMessages: boundedInteger(inv.args.maxMessages, "maxMessages", 1, 1e3) }
25473
+ { maxMessages: boundedInteger2(inv.args.maxMessages, "maxMessages", 1, 1e3) }
24600
25474
  );
24601
25475
  break;
24602
25476
  case "messages.acknowledge":
@@ -24618,7 +25492,7 @@ var googlePubSubConnector = {
24618
25492
  void 0,
24619
25493
  {
24620
25494
  ackIds: requiredStringArray(inv.args.ackIds, "ackIds", 1e3),
24621
- ackDeadlineSeconds: boundedInteger(inv.args.ackDeadlineSeconds, "ackDeadlineSeconds", 0, 600)
25495
+ ackDeadlineSeconds: boundedInteger2(inv.args.ackDeadlineSeconds, "ackDeadlineSeconds", 0, 600)
24622
25496
  }
24623
25497
  );
24624
25498
  break;
@@ -24647,7 +25521,7 @@ var googlePubSubConnector = {
24647
25521
  }
24648
25522
  }
24649
25523
  };
24650
- function readCapability2(name, description, properties, required = []) {
25524
+ function readCapability3(name, description, properties, required = []) {
24651
25525
  return {
24652
25526
  name,
24653
25527
  class: "read",
@@ -24655,7 +25529,7 @@ function readCapability2(name, description, properties, required = []) {
24655
25529
  parameters: { type: "object", properties, ...required.length ? { required } : {} }
24656
25530
  };
24657
25531
  }
24658
- function mutationCapability2(name, description, properties, required) {
25532
+ function mutationCapability4(name, description, properties, required) {
24659
25533
  return {
24660
25534
  name,
24661
25535
  class: "mutation",
@@ -24675,7 +25549,7 @@ function parseServiceAccountCredentials(credentials, dataSourceId) {
24675
25549
  } catch {
24676
25550
  throw new CredentialsExpired("Google Pub/Sub service-account key must be valid JSON", dataSourceId);
24677
25551
  }
24678
- if (!isRecord(parsed) || parsed.type !== "service_account") {
25552
+ if (!isRecord3(parsed) || parsed.type !== "service_account") {
24679
25553
  throw new CredentialsExpired("Google Pub/Sub requires a Google service_account key", dataSourceId);
24680
25554
  }
24681
25555
  const projectId = requiredCredentialString(parsed.project_id, "project_id", dataSourceId);
@@ -24693,7 +25567,7 @@ function parseServiceAccountCredentials(credentials, dataSourceId) {
24693
25567
  return { projectId, clientEmail, privateKey };
24694
25568
  }
24695
25569
  async function accessToken(credentials, dataSourceId) {
24696
- const cacheKey = createHash4("sha256").update(credentials.clientEmail).update("\0").update(credentials.privateKey).digest("hex");
25570
+ const cacheKey = createHash5("sha256").update(credentials.clientEmail).update("\0").update(credentials.privateKey).digest("hex");
24697
25571
  const cached = tokenCache.get(cacheKey);
24698
25572
  if (cached && cached.expiresAt > Date.now() + 6e4) {
24699
25573
  tokenCache.delete(cacheKey);
@@ -24735,8 +25609,8 @@ async function exchangeAccessToken(credentials, dataSourceId, cacheKey) {
24735
25609
  body: form2
24736
25610
  });
24737
25611
  const body = await readJson(response, 64 * 1024);
24738
- if (!response.ok || !isRecord(body) || typeof body.access_token !== "string" || body.access_token.trim() === "") {
24739
- const reason = isRecord(body) && typeof body.error === "string" ? body.error : void 0;
25612
+ if (!response.ok || !isRecord3(body) || typeof body.access_token !== "string" || body.access_token.trim() === "") {
25613
+ const reason = isRecord3(body) && typeof body.error === "string" ? body.error : void 0;
24740
25614
  throw new CredentialsExpired("Google rejected the Pub/Sub service-account grant", dataSourceId, {
24741
25615
  status: response.status,
24742
25616
  reason,
@@ -24772,9 +25646,9 @@ async function pubSubRequest(credentials, inv, method, path, query2, body) {
24772
25646
  },
24773
25647
  body: serialized
24774
25648
  });
24775
- const responseBody = await readJson(response, MAX_RESPONSE_BYTES2);
25649
+ const responseBody = await readJson(response, MAX_RESPONSE_BYTES3);
24776
25650
  if (response.ok) return responseBody;
24777
- const providerError = isRecord(responseBody) && isRecord(responseBody.error) ? responseBody.error : void 0;
25651
+ const providerError = isRecord3(responseBody) && isRecord3(responseBody.error) ? responseBody.error : void 0;
24778
25652
  const reason = providerError && typeof providerError.status === "string" ? providerError.status : void 0;
24779
25653
  if (response.status === 401) {
24780
25654
  throw new CredentialsExpired("Google Pub/Sub credentials were rejected", inv.source.id, {
@@ -24795,7 +25669,7 @@ async function pubSubRequest(credentials, inv, method, path, query2, body) {
24795
25669
  status: response.status,
24796
25670
  reason,
24797
25671
  body: responseBody,
24798
- retryAfterMs: retryAfterMs3(response.headers.get("retry-after"))
25672
+ retryAfterMs: retryAfterMs5(response.headers.get("retry-after"))
24799
25673
  });
24800
25674
  }
24801
25675
  const message = providerError && typeof providerError.message === "string" ? providerError.message : `HTTP ${response.status}`;
@@ -24811,7 +25685,7 @@ function subscriptionPath(credentials, value) {
24811
25685
  return `${projectPath(credentials, "subscriptions")}/${encodeURIComponent(resourceId(value, "subscription"))}`;
24812
25686
  }
24813
25687
  function resourceId(value, field) {
24814
- const id2 = requiredString4(value, field);
25688
+ const id2 = requiredString6(value, field);
24815
25689
  if (!/^[A-Za-z][A-Za-z0-9._~+%-]{2,254}$/.test(id2) || id2.toLowerCase().startsWith("goog")) {
24816
25690
  throw new Error(`${field} must be a valid Pub/Sub resource ID`);
24817
25691
  }
@@ -24819,8 +25693,8 @@ function resourceId(value, field) {
24819
25693
  }
24820
25694
  function pagination(args) {
24821
25695
  const query2 = new URLSearchParams();
24822
- if (args.pageSize !== void 0) query2.set("pageSize", String(boundedInteger(args.pageSize, "pageSize", 1, 1e3)));
24823
- if (args.pageToken !== void 0) query2.set("pageToken", requiredString4(args.pageToken, "pageToken"));
25696
+ if (args.pageSize !== void 0) query2.set("pageSize", String(boundedInteger2(args.pageSize, "pageSize", 1, 1e3)));
25697
+ if (args.pageToken !== void 0) query2.set("pageToken", requiredString6(args.pageToken, "pageToken"));
24824
25698
  return query2;
24825
25699
  }
24826
25700
  function subscriptionBody(credentials, args) {
@@ -24829,11 +25703,11 @@ function subscriptionBody(credentials, args) {
24829
25703
  setOptionalBoolean(body, "retainAckedMessages", args.retainAckedMessages);
24830
25704
  setOptionalDuration(body, "messageRetentionDuration", args.messageRetentionDuration);
24831
25705
  if (args.expirationTtl !== void 0) body.expirationPolicy = { ttl: duration(args.expirationTtl, "expirationTtl") };
24832
- if (args.filter !== void 0) body.filter = requiredString4(args.filter, "filter");
25706
+ if (args.filter !== void 0) body.filter = requiredString6(args.filter, "filter");
24833
25707
  if (args.deadLetterTopic !== void 0) {
24834
25708
  body.deadLetterPolicy = {
24835
25709
  deadLetterTopic: topicPath(credentials, args.deadLetterTopic),
24836
- maxDeliveryAttempts: boundedInteger(args.maxDeliveryAttempts, "maxDeliveryAttempts", 5, 100)
25710
+ maxDeliveryAttempts: boundedInteger2(args.maxDeliveryAttempts, "maxDeliveryAttempts", 5, 100)
24837
25711
  };
24838
25712
  } else if (args.maxDeliveryAttempts !== void 0) {
24839
25713
  throw new Error("maxDeliveryAttempts requires deadLetterTopic");
@@ -24855,15 +25729,15 @@ function publishMessages(value) {
24855
25729
  throw new Error("messages must contain 1 to 1000 entries");
24856
25730
  }
24857
25731
  return value.map((entry, index) => {
24858
- if (!isRecord(entry)) throw new Error(`messages[${index}] must be an object`);
25732
+ if (!isRecord3(entry)) throw new Error(`messages[${index}] must be an object`);
24859
25733
  const hasText = typeof entry.text === "string";
24860
25734
  const hasData = typeof entry.data === "string";
24861
25735
  if (hasText === hasData) throw new Error(`messages[${index}] requires exactly one of text or data`);
24862
- const data4 = hasText ? Buffer.from(entry.text, "utf8").toString("base64") : strictBase64(entry.data, `messages[${index}].data`);
25736
+ const data4 = hasText ? Buffer.from(entry.text, "utf8").toString("base64") : strictBase642(entry.data, `messages[${index}].data`);
24863
25737
  const message = { data: data4 };
24864
25738
  const attributes = optionalStringMap(entry.attributes, `messages[${index}].attributes`);
24865
25739
  if (attributes) message.attributes = attributes;
24866
- if (entry.orderingKey !== void 0) message.orderingKey = requiredString4(entry.orderingKey, `messages[${index}].orderingKey`);
25740
+ if (entry.orderingKey !== void 0) message.orderingKey = requiredString6(entry.orderingKey, `messages[${index}].orderingKey`);
24867
25741
  return message;
24868
25742
  });
24869
25743
  }
@@ -24904,11 +25778,11 @@ function requiredCredentialString(value, field, dataSourceId) {
24904
25778
  }
24905
25779
  return value.trim();
24906
25780
  }
24907
- function requiredString4(value, field) {
25781
+ function requiredString6(value, field) {
24908
25782
  if (typeof value !== "string" || value.trim() === "") throw new Error(`${field} must be a non-empty string`);
24909
25783
  return value.trim();
24910
25784
  }
24911
- function boundedInteger(value, field, minimum, maximum) {
25785
+ function boundedInteger2(value, field, minimum, maximum) {
24912
25786
  if (!Number.isInteger(value) || value < minimum || value > maximum) {
24913
25787
  throw new Error(`${field} must be an integer from ${minimum} to ${maximum}`);
24914
25788
  }
@@ -24918,7 +25792,7 @@ function requiredStringArray(value, field, maximum) {
24918
25792
  if (!Array.isArray(value) || value.length < 1 || value.length > maximum) {
24919
25793
  throw new Error(`${field} must contain 1 to ${maximum} strings`);
24920
25794
  }
24921
- return value.map((entry, index) => requiredString4(entry, `${field}[${index}]`));
25795
+ return value.map((entry, index) => requiredString6(entry, `${field}[${index}]`));
24922
25796
  }
24923
25797
  function optionalStringArray(value, field) {
24924
25798
  if (value === void 0) return void 0;
@@ -24926,16 +25800,16 @@ function optionalStringArray(value, field) {
24926
25800
  }
24927
25801
  function optionalStringMap(value, field) {
24928
25802
  if (value === void 0) return void 0;
24929
- if (!isRecord(value)) throw new Error(`${field} must be an object of strings`);
25803
+ if (!isRecord3(value)) throw new Error(`${field} must be an object of strings`);
24930
25804
  const entries = Object.entries(value);
24931
25805
  if (entries.length > 64) throw new Error(`${field} cannot contain more than 64 entries`);
24932
25806
  return Object.fromEntries(entries.map(([key, entry]) => [
24933
- requiredString4(key, `${field} key`),
24934
- requiredString4(entry, `${field}.${key}`)
25807
+ requiredString6(key, `${field} key`),
25808
+ requiredString6(entry, `${field}.${key}`)
24935
25809
  ]));
24936
25810
  }
24937
25811
  function setOptionalInteger(body, key, value, minimum, maximum) {
24938
- if (value !== void 0) body[key] = boundedInteger(value, key, minimum, maximum);
25812
+ if (value !== void 0) body[key] = boundedInteger2(value, key, minimum, maximum);
24939
25813
  }
24940
25814
  function setOptionalBoolean(body, key, value) {
24941
25815
  if (value === void 0) return;
@@ -24946,17 +25820,17 @@ function setOptionalDuration(body, key, value) {
24946
25820
  if (value !== void 0) body[key] = duration(value, key);
24947
25821
  }
24948
25822
  function duration(value, field) {
24949
- const parsed = requiredString4(value, field);
25823
+ const parsed = requiredString6(value, field);
24950
25824
  if (!/^\d+(?:\.\d{1,9})?s$/.test(parsed)) throw new Error(`${field} must be a protobuf duration ending in s`);
24951
25825
  return parsed;
24952
25826
  }
24953
- function enumValue(value, field, choices) {
25827
+ function enumValue2(value, field, choices) {
24954
25828
  if (typeof value !== "string" || !choices.includes(value)) {
24955
25829
  throw new Error(`${field} must be one of ${choices.join(", ")}`);
24956
25830
  }
24957
25831
  return value;
24958
25832
  }
24959
- function strictBase64(value, field) {
25833
+ function strictBase642(value, field) {
24960
25834
  if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
24961
25835
  throw new Error(`${field} must be canonical base64`);
24962
25836
  }
@@ -24965,14 +25839,14 @@ function strictBase64(value, field) {
24965
25839
  function base64UrlJson(value) {
24966
25840
  return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
24967
25841
  }
24968
- function retryAfterMs3(value) {
25842
+ function retryAfterMs5(value) {
24969
25843
  if (!value) return 6e4;
24970
25844
  const seconds = Number(value);
24971
25845
  if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
24972
25846
  const date = Date.parse(value);
24973
25847
  return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 6e4;
24974
25848
  }
24975
- function isRecord(value) {
25849
+ function isRecord3(value) {
24976
25850
  return typeof value === "object" && value !== null && !Array.isArray(value);
24977
25851
  }
24978
25852
 
@@ -26748,7 +27622,7 @@ async function ensureFreshAccessToken5(creds, clientId, clientSecret) {
26748
27622
  }
26749
27623
 
26750
27624
  // src/connectors/adapters/google-sheets.ts
26751
- import { createHash as createHash5 } from "crypto";
27625
+ import { createHash as createHash6 } from "crypto";
26752
27626
  var SCOPES5 = ["https://www.googleapis.com/auth/spreadsheets"];
26753
27627
  var AUTH_URL6 = "https://accounts.google.com/o/oauth2/v2/auth";
26754
27628
  var TOKEN_URL7 = "https://oauth2.googleapis.com/token";
@@ -27021,7 +27895,7 @@ async function fetchAllRows(accessToken4, meta) {
27021
27895
  function rowFingerprint(values) {
27022
27896
  const keys = Object.keys(values).sort();
27023
27897
  const blob = keys.map((k) => `${k}=${values[k]}`).join("");
27024
- return createHash5("sha256").update(blob).digest("hex").slice(0, 16);
27898
+ return createHash6("sha256").update(blob).digest("hex").slice(0, 16);
27025
27899
  }
27026
27900
  function matchesPredicate(row, predicate) {
27027
27901
  for (const [k, v] of Object.entries(predicate)) {
@@ -27875,7 +28749,7 @@ var granolaConnector = declarativeRestConnector({
27875
28749
  });
27876
28750
 
27877
28751
  // src/connectors/adapters/hellosign.ts
27878
- import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual2 } from "crypto";
28752
+ import { createHmac as createHmac5, timingSafeEqual as timingSafeEqual3 } from "crypto";
27879
28753
  var SCOPES6 = [
27880
28754
  "basic_account_info",
27881
28755
  "request_signature",
@@ -28098,11 +28972,11 @@ function hellosign(opts) {
28098
28972
  if (!event || typeof event.event_time !== "string" || typeof event.event_type !== "string" || typeof event.event_hash !== "string") {
28099
28973
  return { valid: false, reason: "missing_event_fields" };
28100
28974
  }
28101
- const expected = createHmac4("sha256", source.credentials.accessToken).update(`${event.event_time}${event.event_type}`).digest("hex");
28975
+ const expected = createHmac5("sha256", source.credentials.accessToken).update(`${event.event_time}${event.event_type}`).digest("hex");
28102
28976
  const a = Buffer.from(event.event_hash.toLowerCase(), "utf-8");
28103
28977
  const b = Buffer.from(expected.toLowerCase(), "utf-8");
28104
28978
  if (a.length !== b.length) return { valid: false, reason: "invalid_signature" };
28105
- return timingSafeEqual2(a, b) ? { valid: true } : { valid: false, reason: "invalid_signature" };
28979
+ return timingSafeEqual3(a, b) ? { valid: true } : { valid: false, reason: "invalid_signature" };
28106
28980
  },
28107
28981
  async handleInboundEvent({ rawBody }) {
28108
28982
  const parsed = parseInboundBody(rawBody);
@@ -40041,7 +40915,7 @@ function outlookMail(opts) {
40041
40915
  async executeMutation(inv) {
40042
40916
  const accessToken4 = await ensureFreshAccessToken13(inv.source.credentials, clientId, clientSecret, inv.onCredentialsRotated);
40043
40917
  if (inv.capabilityName === "send_reply") return sendReply2(inv, accessToken4, timeoutMs);
40044
- if (inv.capabilityName === "send_message") return sendMessage(inv, accessToken4, timeoutMs);
40918
+ if (inv.capabilityName === "send_message") return sendMessage2(inv, accessToken4, timeoutMs);
40045
40919
  if (inv.capabilityName === "create_draft") return createDraft(inv, accessToken4, timeoutMs);
40046
40920
  if (inv.capabilityName === "subscribe_folder") return subscribeFolder(inv, accessToken4, timeoutMs);
40047
40921
  if (inv.capabilityName === "forward_message") return forwardMessage(inv, accessToken4, timeoutMs);
@@ -40299,7 +41173,7 @@ function buildMessagePayload(args, idempotencyKey, cap) {
40299
41173
  }
40300
41174
  return payload;
40301
41175
  }
40302
- async function sendMessage(inv, accessToken4, timeoutMs) {
41176
+ async function sendMessage2(inv, accessToken4, timeoutMs) {
40303
41177
  const args = inv.args ?? {};
40304
41178
  const message = buildMessagePayload(args, inv.idempotencyKey, "send_message");
40305
41179
  const res = await fetch(`${API7}/me/sendMail`, {
@@ -42581,7 +43455,7 @@ var rssConnector = {
42581
43455
  if (!res.ok) {
42582
43456
  throw new Error(`rss fetch ${res.status} ${res.statusText} for ${url.toString()}`);
42583
43457
  }
42584
- const body = await readBoundedText(res, MAX_BODY_BYTES);
43458
+ const body = await readBoundedText2(res, MAX_BODY_BYTES);
42585
43459
  const parsed = parseFeed(body, url.toString());
42586
43460
  const filtered = filterAndLimit(parsed.entries, since, limit);
42587
43461
  const data4 = {
@@ -42661,7 +43535,7 @@ function readSinceMs(value) {
42661
43535
  }
42662
43536
  return ms;
42663
43537
  }
42664
- async function readBoundedText(res, maxBytes) {
43538
+ async function readBoundedText2(res, maxBytes) {
42665
43539
  const reader = res.body?.getReader();
42666
43540
  if (!reader) return await res.text();
42667
43541
  const decoder = new TextDecoder("utf-8", { fatal: false });
@@ -42715,7 +43589,7 @@ function parseRss(text) {
42715
43589
  return { feedTitle: null, feedUpdated: null, entries: [], format: "rss" };
42716
43590
  }
42717
43591
  const channelInner = stripAllElements(channelOuter, "item");
42718
- const feedTitle = decodeXml2(firstTagText(channelInner, "title"));
43592
+ const feedTitle = decodeXml3(firstTagText(channelInner, "title"));
42719
43593
  const items = collectElements(channelOuter, "item");
42720
43594
  const entries = items.map((item) => {
42721
43595
  const guid = firstTagText(item, "guid");
@@ -42725,17 +43599,17 @@ function parseRss(text) {
42725
43599
  const contentEncoded = firstTagText(item, "content:encoded");
42726
43600
  const pubDate = firstTagText(item, "pubDate");
42727
43601
  const author = firstTagText(item, "author") ?? firstTagText(item, "dc:creator");
42728
- const categories = collectElements(item, "category").map((cat) => decodeXml2(stripTags(cat)) ?? "").filter(Boolean);
42729
- const id2 = decodeXml2(guid) ?? decodeXml2(link) ?? hash(item);
43602
+ const categories = collectElements(item, "category").map((cat) => decodeXml3(stripTags(cat)) ?? "").filter(Boolean);
43603
+ const id2 = decodeXml3(guid) ?? decodeXml3(link) ?? hash(item);
42730
43604
  return {
42731
43605
  id: id2,
42732
- title: decodeXml2(title),
42733
- link: decodeXml2(link),
42734
- summary: decodeXml2(description),
42735
- content: decodeXml2(contentEncoded),
42736
- published: normalizeDate(decodeXml2(pubDate)),
43606
+ title: decodeXml3(title),
43607
+ link: decodeXml3(link),
43608
+ summary: decodeXml3(description),
43609
+ content: decodeXml3(contentEncoded),
43610
+ published: normalizeDate(decodeXml3(pubDate)),
42737
43611
  updated: null,
42738
- author: decodeXml2(author),
43612
+ author: decodeXml3(author),
42739
43613
  categories
42740
43614
  };
42741
43615
  });
@@ -42744,17 +43618,17 @@ function parseRss(text) {
42744
43618
  function parseAtom(text, feedUrl) {
42745
43619
  const feedOuter = extractFirstElement(text, "feed") ?? text;
42746
43620
  const feedInner = stripAllElements(feedOuter, "entry");
42747
- const feedTitle = decodeXml2(firstTagText(feedInner, "title"));
42748
- const feedUpdated = normalizeDate(decodeXml2(firstTagText(feedInner, "updated")));
43621
+ const feedTitle = decodeXml3(firstTagText(feedInner, "title"));
43622
+ const feedUpdated = normalizeDate(decodeXml3(firstTagText(feedInner, "updated")));
42749
43623
  const items = collectElements(feedOuter, "entry");
42750
43624
  const entries = items.map((item) => {
42751
- const id2 = decodeXml2(firstTagText(item, "id"));
42752
- const title = decodeXml2(firstTagText(item, "title"));
42753
- const summary = decodeXml2(firstTagText(item, "summary"));
43625
+ const id2 = decodeXml3(firstTagText(item, "id"));
43626
+ const title = decodeXml3(firstTagText(item, "title"));
43627
+ const summary = decodeXml3(firstTagText(item, "summary"));
42754
43628
  const contentNode = firstTagText(item, "content");
42755
- const published = normalizeDate(decodeXml2(firstTagText(item, "published")));
42756
- const updated = normalizeDate(decodeXml2(firstTagText(item, "updated")));
42757
- const author = decodeXml2(firstTagText(extractFirstElement(item, "author") ?? "", "name")) ?? decodeXml2(firstTagText(item, "author"));
43629
+ const published = normalizeDate(decodeXml3(firstTagText(item, "published")));
43630
+ const updated = normalizeDate(decodeXml3(firstTagText(item, "updated")));
43631
+ const author = decodeXml3(firstTagText(extractFirstElement(item, "author") ?? "", "name")) ?? decodeXml3(firstTagText(item, "author"));
42758
43632
  const link = pickAtomLink(item);
42759
43633
  const categories = collectAtomCategories(item);
42760
43634
  return {
@@ -42762,7 +43636,7 @@ function parseAtom(text, feedUrl) {
42762
43636
  title,
42763
43637
  link,
42764
43638
  summary,
42765
- content: decodeXml2(contentNode),
43639
+ content: decodeXml3(contentNode),
42766
43640
  published,
42767
43641
  updated,
42768
43642
  author,
@@ -42848,9 +43722,9 @@ function collectAtomCategories(entryOuter) {
42848
43722
  let m;
42849
43723
  while ((m = re.exec(entryOuter)) !== null) {
42850
43724
  const term = readAttr(m[1] ?? "", "term");
42851
- if (term) out.push(decodeXml2(term) ?? "");
43725
+ if (term) out.push(decodeXml3(term) ?? "");
42852
43726
  else if (m[2]) {
42853
- const inner = decodeXml2(stripTags(m[2]));
43727
+ const inner = decodeXml3(stripTags(m[2]));
42854
43728
  if (inner) out.push(inner);
42855
43729
  }
42856
43730
  }
@@ -42878,7 +43752,7 @@ function unwrapCdata(value) {
42878
43752
  out += value.slice(lastIdx);
42879
43753
  return out;
42880
43754
  }
42881
- function decodeXml2(value) {
43755
+ function decodeXml3(value) {
42882
43756
  if (value === null) return null;
42883
43757
  const trimmed = value.trim();
42884
43758
  if (trimmed.length === 0) return null;
@@ -52665,17 +53539,17 @@ var zohoBookingsConnector = {
52665
53539
  category: "calendar",
52666
53540
  defaultConsistencyModel: "authoritative",
52667
53541
  capabilities: [
52668
- readCapability3("workspaces.list", "List Zoho Bookings workspaces.", {}),
52669
- readCapability3("services.list", "List services, optionally within one workspace.", {
53542
+ readCapability4("workspaces.list", "List Zoho Bookings workspaces.", {}),
53543
+ readCapability4("services.list", "List services, optionally within one workspace.", {
52670
53544
  workspace_id: { type: "string" }
52671
53545
  }),
52672
- readCapability3("resources.list", "List bookable resources, optionally for one service.", {
53546
+ readCapability4("resources.list", "List bookable resources, optionally for one service.", {
52673
53547
  service_id: { type: "string" }
52674
53548
  }),
52675
- readCapability3("staff.list", "List staff, optionally for one service.", {
53549
+ readCapability4("staff.list", "List staff, optionally for one service.", {
52676
53550
  service_id: { type: "string" }
52677
53551
  }),
52678
- readCapability3("appointments.list", "List appointments from a required start time.", {
53552
+ readCapability4("appointments.list", "List appointments from a required start time.", {
52679
53553
  from_time: {
52680
53554
  type: "string",
52681
53555
  description: "Zoho timestamp in dd-MMM-yyyy HH:mm:ss format."
@@ -52685,17 +53559,17 @@ var zohoBookingsConnector = {
52685
53559
  staff_id: { type: "string" },
52686
53560
  status: { type: "string" }
52687
53561
  }, ["from_time"]),
52688
- readCapability3("appointments.get", "Read one appointment by booking id.", {
53562
+ readCapability4("appointments.get", "Read one appointment by booking id.", {
52689
53563
  booking_id: { type: "string" }
52690
53564
  }, ["booking_id"]),
52691
- readCapability3("availability.fetch", "Fetch open time slots for a service and date.", {
53565
+ readCapability4("availability.fetch", "Fetch open time slots for a service and date.", {
52692
53566
  service_id: { type: "string" },
52693
53567
  selected_date: { type: "string", description: "Date in YYYY-MM-DD format." },
52694
53568
  staff_id: { type: "string" },
52695
53569
  group_id: { type: "string" },
52696
53570
  resource_id: { type: "string" }
52697
53571
  }, ["service_id", "selected_date"]),
52698
- mutationCapability3("appointments.book", "Book an appointment for a customer.", {
53572
+ mutationCapability5("appointments.book", "Book an appointment for a customer.", {
52699
53573
  service_id: { type: "string" },
52700
53574
  from_time: { type: "string", description: "Zoho timestamp in dd-MMM-yyyy HH:mm:ss format." },
52701
53575
  customer_details: {
@@ -52711,13 +53585,13 @@ var zohoBookingsConnector = {
52711
53585
  additional_fields: { type: "object" },
52712
53586
  payment_info: { type: "object" }
52713
53587
  }, ["service_id", "from_time", "customer_details"]),
52714
- mutationCapability3("appointments.reschedule", "Move an appointment to a new time, staff member, or group.", {
53588
+ mutationCapability5("appointments.reschedule", "Move an appointment to a new time, staff member, or group.", {
52715
53589
  booking_id: { type: "string" },
52716
53590
  start_time: { type: "string", description: "Zoho timestamp in dd-MMM-yyyy HH:mm:ss format." },
52717
53591
  staff_id: { type: "string" },
52718
53592
  group_id: { type: "string" }
52719
53593
  }, ["booking_id"]),
52720
- mutationCapability3("appointments.cancel", "Cancel an appointment by booking id.", {
53594
+ mutationCapability5("appointments.cancel", "Cancel an appointment by booking id.", {
52721
53595
  booking_id: { type: "string" }
52722
53596
  }, ["booking_id"])
52723
53597
  ]
@@ -52834,7 +53708,7 @@ var zohoBookingsConnector = {
52834
53708
  }
52835
53709
  }
52836
53710
  };
52837
- function readCapability3(name, description, properties, required = []) {
53711
+ function readCapability4(name, description, properties, required = []) {
52838
53712
  return {
52839
53713
  name,
52840
53714
  class: "read",
@@ -52843,7 +53717,7 @@ function readCapability3(name, description, properties, required = []) {
52843
53717
  requiredScopes: ["zohobookings.data.READ"]
52844
53718
  };
52845
53719
  }
52846
- function mutationCapability3(name, description, properties, required) {
53720
+ function mutationCapability5(name, description, properties, required) {
52847
53721
  return {
52848
53722
  name,
52849
53723
  class: "mutation",
@@ -52898,7 +53772,7 @@ async function request2(source, path, options) {
52898
53772
  throw new ProviderRateLimited("Zoho Bookings rate limit (429)", source.id, {
52899
53773
  status: 429,
52900
53774
  body: responseBody,
52901
- retryAfterMs: retryAfterMs4(response.headers.get("retry-after"))
53775
+ retryAfterMs: retryAfterMs6(response.headers.get("retry-after"))
52902
53776
  });
52903
53777
  }
52904
53778
  if (!response.ok) throw new Error(`zoho-bookings ${options.method} ${path} HTTP ${response.status}`);
@@ -52943,7 +53817,7 @@ function exactlyOne(args, keys, label) {
52943
53817
  const present = keys.filter((key) => args[key] !== void 0 && args[key] !== null && args[key] !== "");
52944
53818
  if (present.length !== 1) throw new Error(`zoho-bookings: exactly one ${label} is required`);
52945
53819
  }
52946
- function retryAfterMs4(value) {
53820
+ function retryAfterMs6(value) {
52947
53821
  if (!value) return 6e4;
52948
53822
  const seconds = Number(value);
52949
53823
  return Number.isFinite(seconds) && seconds >= 0 ? Math.max(1e3, seconds * 1e3) : 6e4;
@@ -54082,11 +54956,11 @@ async function request3(source, path, options) {
54082
54956
  });
54083
54957
  }
54084
54958
  if (response.status === 429) {
54085
- const retryAfterMs5 = parseRetryAfter(response.headers.get("retry-after"));
54959
+ const retryAfterMs7 = parseRetryAfter(response.headers.get("retry-after"));
54086
54960
  throw new ProviderRateLimited("Zoho Campaigns rate limit (429)", source.id, {
54087
54961
  status: 429,
54088
54962
  body: responseBody,
54089
- retryAfterMs: retryAfterMs5
54963
+ retryAfterMs: retryAfterMs7
54090
54964
  });
54091
54965
  }
54092
54966
  if (!response.ok) {
@@ -61746,6 +62620,8 @@ var CONNECTOR_ADAPTER_FACTORIES = [
61746
62620
  defineFactoryAdapter(() => googleCloudStorageConnector, googleOAuthEnvMap),
61747
62621
  defineFactoryAdapter(() => googlePubSubConnector, {}),
61748
62622
  defineFactoryAdapter(() => azureBlobStorageConnector, {}),
62623
+ defineFactoryAdapter(() => azureEventGridConnector, {}),
62624
+ defineFactoryAdapter(() => azureServiceBusConnector, {}),
61749
62625
  defineFactoryAdapter(() => backblazeConnector, {}),
61750
62626
  defineFactoryAdapter(() => cloudinaryConnector, {}),
61751
62627
  defineFactoryAdapter(() => codaConnector, {}),
@@ -62519,11 +63395,11 @@ function validateOutboundStartArgs(args) {
62519
63395
  assertNonEmptyString(args.agentId, "agentId", 128);
62520
63396
  assertE164(args.toNumber, "toNumber");
62521
63397
  assertE164(args.fromNumber, "fromNumber");
62522
- if (!isRecord2(args.mission)) throw new Error("phony start_outbound_call requires mission");
63398
+ if (!isRecord4(args.mission)) throw new Error("phony start_outbound_call requires mission");
62523
63399
  const mission = args.mission;
62524
63400
  assertNonEmptyString(mission.goal, "mission.goal", 2e3);
62525
63401
  if (mission.goal.trim().length < 8) throw new Error("phony start_outbound_call mission.goal must be at least 8 characters");
62526
- if (mission.successSchema !== void 0 && !isRecord2(mission.successSchema)) {
63402
+ if (mission.successSchema !== void 0 && !isRecord4(mission.successSchema)) {
62527
63403
  throw new Error("phony start_outbound_call mission.successSchema must be an object when supplied");
62528
63404
  }
62529
63405
  if (mission.ivrHints !== void 0) {
@@ -62537,7 +63413,7 @@ function validateOutboundStartArgs(args) {
62537
63413
  if (args.missionId !== void 0) assertNonEmptyString(args.missionId, "missionId", 128);
62538
63414
  if (args.voiceCloneId !== void 0) assertNonEmptyString(args.voiceCloneId, "voiceCloneId", 128);
62539
63415
  if (args.callerProfile !== void 0) {
62540
- if (!isRecord2(args.callerProfile)) throw new Error("phony start_outbound_call callerProfile must be an object");
63416
+ if (!isRecord4(args.callerProfile)) throw new Error("phony start_outbound_call callerProfile must be an object");
62541
63417
  if (args.callerProfile.userName !== void 0) assertNonEmptyString(args.callerProfile.userName, "callerProfile.userName", 120);
62542
63418
  if (args.callerProfile.companyName !== void 0) {
62543
63419
  assertNonEmptyString(args.callerProfile.companyName, "callerProfile.companyName", 120);
@@ -62564,7 +63440,7 @@ function assertOptionalInteger(value, field, min, max) {
62564
63440
  throw new Error(`phony start_outbound_call ${field} must be an integer between ${min} and ${max}`);
62565
63441
  }
62566
63442
  }
62567
- function isRecord2(value) {
63443
+ function isRecord4(value) {
62568
63444
  return typeof value === "object" && value !== null && !Array.isArray(value);
62569
63445
  }
62570
63446
  async function getJson(inv, token, url, label) {
@@ -62636,7 +63512,7 @@ var INGEST_FIELDS = [
62636
63512
  ];
62637
63513
 
62638
63514
  // src/connectors/adapters/webhook.ts
62639
- import { createHmac as createHmac5 } from "crypto";
63515
+ import { createHmac as createHmac6 } from "crypto";
62640
63516
  var webhookConnector = {
62641
63517
  manifest: {
62642
63518
  kind: "webhook",
@@ -62750,7 +63626,7 @@ function signHeaders(creds, body, idempotencyKey) {
62750
63626
  "x-phony-idempotency-key": idempotencyKey
62751
63627
  };
62752
63628
  if (creds.kind === "hmac" && typeof creds.secret === "string" && creds.secret.length > 0) {
62753
- const sig = createHmac5("sha256", creds.secret).update(`${ts}.${body}`).digest("hex");
63629
+ const sig = createHmac6("sha256", creds.secret).update(`${ts}.${body}`).digest("hex");
62754
63630
  headers["x-phony-signature"] = `sha256=${sig}`;
62755
63631
  }
62756
63632
  return headers;
@@ -141686,6 +142562,8 @@ export {
141686
142562
  avalaraConnector,
141687
142563
  azureAdConnector,
141688
142564
  azureBlobStorageConnector,
142565
+ azureEventGridConnector,
142566
+ azureServiceBusConnector,
141689
142567
  basecampConnector,
141690
142568
  backblazeConnector,
141691
142569
  biginByZohoConnector,
@@ -142254,4 +143132,4 @@ export {
142254
143132
  demandbaseConnector,
142255
143133
  adapters_exports
142256
143134
  };
142257
- //# sourceMappingURL=chunk-YWNB5M5K.js.map
143135
+ //# sourceMappingURL=chunk-XZL47RBS.js.map