@voyant-travel/webhook-delivery 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export type { ExternalWebhookEventContract, WebhookSubscriptionEventInput, } from "./contracts.js";
2
2
  export { assertWebhookSubscriptionCreateEvents, assertWebhookSubscriptionUpdateEvents, prepareExternalWebhookEvent, } from "./contracts.js";
3
+ export type { OutboundWebhookDeliveryEnqueuer, OutboundWebhookEnqueueProvider, ResolveOutboundWebhookDeliveryEnqueuerOptions, } from "./provider.js";
4
+ export { resolveOutboundWebhookDeliveryEnqueuer } from "./provider.js";
3
5
  export { hashWebhookPayload, redactWebhookHeaders, signWebhookPayload, webhookBodyExcerpt, } from "./security.js";
4
6
  export type { CreateSelectedExternalWebhookQueueOptions } from "./selected-queue.js";
5
7
  export { createSelectedExternalWebhookQueue, externalContractFromEventMetadata, } from "./selected-queue.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,yCAAyC,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,EACL,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAA;AACrE,YAAY,EACV,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,EACtB,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,6CAA6C,GAC9C,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,sCAAsC,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,yCAAyC,EAAE,MAAM,qBAAqB,CAAA;AACpF,OAAO,EACL,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAA;AACrE,YAAY,EACV,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,EACtB,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { assertWebhookSubscriptionCreateEvents, assertWebhookSubscriptionUpdateEvents, prepareExternalWebhookEvent, } from "./contracts.js";
2
+ export { resolveOutboundWebhookDeliveryEnqueuer } from "./provider.js";
2
3
  export { hashWebhookPayload, redactWebhookHeaders, signWebhookPayload, webhookBodyExcerpt, } from "./security.js";
3
4
  export { createSelectedExternalWebhookQueue, externalContractFromEventMetadata, } from "./selected-queue.js";
4
5
  export { createWebhookSubscriptionService } from "./subscriptions.js";
@@ -2,11 +2,17 @@ import type { EventEnvelope } from "@voyant-travel/core";
2
2
  import type { AnyDrizzleDb } from "@voyant-travel/db";
3
3
  import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
4
4
  import type { ExternalWebhookEventContract } from "./contracts.js";
5
+ import type { OutboundWebhookDeliveryEnqueuer } from "./provider.js";
5
6
  import { type WebhookSubscriptionService } from "./subscriptions.js";
6
7
  import type { SelectedExternalWebhookQueue, WebhookDeliveryStore, WebhookEnqueueOutcome } from "./types.js";
7
8
  export interface EnqueuePostgresWebhookEventOptions {
8
9
  queue?: SelectedExternalWebhookQueue;
9
10
  }
11
+ export interface CreatePostgresWebhookDeliveryEnqueuerOptions extends EnqueuePostgresWebhookEventOptions {
12
+ resolveDatabase(bindings: unknown): AnyDrizzleDb;
13
+ }
14
+ /** Create the package-owned Postgres enqueue adapter for a resident Node host. */
15
+ export declare function createPostgresWebhookDeliveryEnqueuer(options: CreatePostgresWebhookDeliveryEnqueuerOptions): OutboundWebhookDeliveryEnqueuer;
10
16
  /** Persist one graph-selected event through the neutral Postgres delivery queue. */
11
17
  export declare function enqueuePostgresWebhookEvent(db: AnyDrizzleDb, event: EventEnvelope, options?: EnqueuePostgresWebhookEventOptions): Promise<WebhookEnqueueOutcome[]>;
12
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../src/postgres-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAYrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAA;AAKlE,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAIV,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,kCAAkC;IACjD,KAAK,CAAC,EAAE,4BAA4B,CAAA;CACrC;AAED,oFAAoF;AACpF,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAQlC;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,EAAE,EAAE,kBAAkB,GAAG,oBAAoB,CA+K/F;AAkCD,mFAAmF;AACnF,wBAAgB,wCAAwC,CACtD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,SAAS,4BAA4B,EAAE,GACjD,0BAA0B,CAuB5B"}
1
+ {"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../src/postgres-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAYrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAA;AAClE,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAA;AAKpE,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAIV,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,kCAAkC;IACjD,KAAK,CAAC,EAAE,4BAA4B,CAAA;CACrC;AAED,MAAM,WAAW,4CACf,SAAQ,kCAAkC;IAC1C,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,YAAY,CAAA;CACjD;AAED,kFAAkF;AAClF,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,4CAA4C,GACpD,+BAA+B,CAOjC;AAED,oFAAoF;AACpF,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAQlC;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,EAAE,EAAE,kBAAkB,GAAG,oBAAoB,CAiL/F;AAkCD,mFAAmF;AACnF,wBAAgB,wCAAwC,CACtD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,SAAS,4BAA4B,EAAE,GACjD,0BAA0B,CAuB5B"}
@@ -3,6 +3,14 @@ import { infraWebhookDeliveriesTable, infraWebhookDeliverySelectSchema, infraWeb
3
3
  import { and, arrayContains, asc, eq, isNull, lte, or, sql } from "drizzle-orm";
4
4
  import { createSelectedExternalWebhookQueue, externalContractFromEventMetadata, } from "./selected-queue.js";
5
5
  import { createWebhookSubscriptionService, } from "./subscriptions.js";
6
+ /** Create the package-owned Postgres enqueue adapter for a resident Node host. */
7
+ export function createPostgresWebhookDeliveryEnqueuer(options) {
8
+ return {
9
+ enqueue: (event, bindings) => enqueuePostgresWebhookEvent(options.resolveDatabase(bindings), event, {
10
+ ...(options.queue ? { queue: options.queue } : {}),
11
+ }),
12
+ };
13
+ }
6
14
  /** Persist one graph-selected event through the neutral Postgres delivery queue. */
7
15
  export async function enqueuePostgresWebhookEvent(db, event, options = {}) {
8
16
  const queue = options.queue ??
@@ -46,6 +54,7 @@ export function createPostgresWebhookDeliveryStore(db) {
46
54
  async enqueueAttempt(input) {
47
55
  return db.transaction(async (tx) => {
48
56
  const lockKey = `webhook-delivery:${input.idempotencyKey}:${input.attemptNumber}`;
57
+ // agent-quality: raw-sql reviewed -- owner: webhook-delivery; lockKey is parameter-bound and the SQL function/table identifiers are static.
49
58
  await tx.execute(sql `SELECT pg_advisory_xact_lock(hashtextextended(${lockKey}, 0))`);
50
59
  const existing = await tx
51
60
  .select()
@@ -129,6 +138,7 @@ export function createPostgresWebhookDeliveryStore(db) {
129
138
  .update(infraWebhookSubscriptionsTable)
130
139
  .set({
131
140
  lastDeliveryAt: at,
141
+ // agent-quality: raw-sql reviewed -- owner: webhook-delivery; Drizzle supplies the typed column identifier and binds no caller-controlled SQL.
132
142
  failureCount: succeeded ? 0 : sql `${infraWebhookSubscriptionsTable.failureCount} + 1`,
133
143
  updatedAt: at,
134
144
  })
@@ -204,8 +214,8 @@ function pendingAttemptValues(input) {
204
214
  requestHeaders: input.requestHeaders,
205
215
  requestBodyHash: input.requestBodyHash,
206
216
  requestBodyExcerpt: input.requestBodyExcerpt,
207
- requestPayload: input.requestPayload,
208
- deliveryContract: input.deliveryContract,
217
+ requestPayload: objectRecord(input.requestPayload),
218
+ deliveryContract: objectRecord(input.deliveryContract),
209
219
  attemptNumber: input.attemptNumber,
210
220
  parentDeliveryId: input.parentDeliveryId,
211
221
  idempotencyKey: input.idempotencyKey,
@@ -214,3 +224,6 @@ function pendingAttemptValues(input) {
214
224
  startedAt: null,
215
225
  };
216
226
  }
227
+ function objectRecord(value) {
228
+ return Object.fromEntries(Object.entries(value));
229
+ }
@@ -0,0 +1,13 @@
1
+ import type { EventEnvelope } from "@voyant-travel/core";
2
+ export type OutboundWebhookEnqueueProvider = "postgres" | "host" | "none";
3
+ export interface OutboundWebhookDeliveryEnqueuer {
4
+ enqueue(event: EventEnvelope, bindings: unknown): Promise<unknown>;
5
+ }
6
+ export interface ResolveOutboundWebhookDeliveryEnqueuerOptions {
7
+ provider: unknown;
8
+ createPostgres?: () => OutboundWebhookDeliveryEnqueuer;
9
+ host?: OutboundWebhookDeliveryEnqueuer;
10
+ }
11
+ /** Resolve the graph-selected deployment enqueue implementation. */
12
+ export declare function resolveOutboundWebhookDeliveryEnqueuer(options: ResolveOutboundWebhookDeliveryEnqueuerOptions): OutboundWebhookDeliveryEnqueuer | undefined;
13
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,MAAM,8BAA8B,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAEzE,MAAM,WAAW,+BAA+B;IAC9C,OAAO,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACnE;AAED,MAAM,WAAW,6CAA6C;IAC5D,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,+BAA+B,CAAA;IACtD,IAAI,CAAC,EAAE,+BAA+B,CAAA;CACvC;AAED,oEAAoE;AACpE,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,6CAA6C,GACrD,+BAA+B,GAAG,SAAS,CA0B7C"}
@@ -0,0 +1,22 @@
1
+ /** Resolve the graph-selected deployment enqueue implementation. */
2
+ export function resolveOutboundWebhookDeliveryEnqueuer(options) {
3
+ const { provider } = options;
4
+ if (typeof provider !== "string" || provider.length === 0) {
5
+ throw new Error("deployment provider outboundWebhooks must be explicitly selected");
6
+ }
7
+ if (provider === "none")
8
+ return undefined;
9
+ if (provider === "host") {
10
+ if (!options.host) {
11
+ throw new Error('deployment provider outboundWebhooks="host" requires host.deliverEvent');
12
+ }
13
+ return options.host;
14
+ }
15
+ if (provider === "postgres") {
16
+ if (!options.createPostgres) {
17
+ throw new Error('deployment provider outboundWebhooks="postgres" requires a Postgres enqueue adapter');
18
+ }
19
+ return options.createPostgres();
20
+ }
21
+ throw new Error(`deployment provider outboundWebhooks="${provider}" is not supported; expected postgres, host, or none`);
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyant-travel/webhook-delivery",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Durable, policy-aware outbound webhook delivery for Voyant Node deployments.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -19,8 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "drizzle-orm": "^0.45.2",
22
- "@voyant-travel/core": "^0.120.0",
23
- "@voyant-travel/db": "^0.114.0"
22
+ "@voyant-travel/core": "^0.122.0",
23
+ "@voyant-travel/db": "^0.114.2"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "^25.5.2",