@nestarc/webhook 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/webhook-options.interface.d.ts +16 -0
- package/dist/interfaces/webhook-options.interface.d.ts.map +1 -1
- package/dist/webhook.delivery-worker.d.ts.map +1 -1
- package/dist/webhook.delivery-worker.js +13 -3
- package/dist/webhook.delivery-worker.js.map +1 -1
- package/dist/webhook.url-validator.d.ts +9 -1
- package/dist/webhook.url-validator.d.ts.map +1 -1
- package/dist/webhook.url-validator.js +36 -21
- package/dist/webhook.url-validator.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,9 +186,28 @@ export class WebhookController {
|
|
|
186
186
|
| `polling.staleSendingMinutes` | `5` | Minutes before a stuck SENDING delivery is recovered |
|
|
187
187
|
| `allowPrivateUrls` | `false` | Allow private/internal URLs (dev/test only) |
|
|
188
188
|
| `secretVault` | `PlaintextSecretVault` | Custom vault for encrypting/decrypting endpoint secrets at rest |
|
|
189
|
-
| `onDeliveryFailed` | — | Fire-and-forget callback when a delivery exhausts all retries. Receives `DeliveryFailedContext` (`tenantId` is `null` for global endpoints). |
|
|
189
|
+
| `onDeliveryFailed` | — | Fire-and-forget callback when a delivery exhausts all retries. Receives `DeliveryFailedContext` (`tenantId` is `null` for global endpoints). See **Delivery failure classification** below. |
|
|
190
190
|
| `onEndpointDisabled` | — | Fire-and-forget callback when the circuit breaker disables an endpoint. Fires once at exact threshold crossing. |
|
|
191
191
|
|
|
192
|
+
**Delivery failure classification.** `DeliveryFailedContext.failureKind` categorizes why a delivery was abandoned after all retries:
|
|
193
|
+
|
|
194
|
+
| `failureKind` | When | Extra fields |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| `url_validation` | SSRF defense rejected the URL (private, loopback, link-local, etc.) | `validationReason`, `validationUrl`, `resolvedIp` |
|
|
197
|
+
| `dispatch_error` | Dispatcher threw (DNS failure, ECONNREFUSED, timeout) | — |
|
|
198
|
+
| `http_error` | Endpoint responded with non-2xx status | `responseStatus` |
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
onDeliveryFailed: (ctx) => {
|
|
202
|
+
if (ctx.failureKind === 'url_validation') {
|
|
203
|
+
// ctx.validationReason: 'private' | 'loopback' | 'link_local' | ...
|
|
204
|
+
alerting.endpointMisconfigured(ctx.endpointId, ctx.validationReason);
|
|
205
|
+
} else if (ctx.failureKind === 'http_error') {
|
|
206
|
+
alerting.downstreamUnhealthy(ctx.endpointId, ctx.responseStatus);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
192
211
|
### Custom adapters
|
|
193
212
|
|
|
194
213
|
Replace default Prisma or fetch implementations by providing custom ports:
|
|
@@ -241,6 +260,24 @@ webhook-signature: v1,<base64-hmac-sha256>
|
|
|
241
260
|
- HTTP redirects are disabled (`redirect: 'manual'`)
|
|
242
261
|
- Use `allowPrivateUrls: true` for local development only
|
|
243
262
|
|
|
263
|
+
**Structured validation errors** — validation failures throw `WebhookUrlValidationError` (subclass of `Error`) with a machine-readable `reason`:
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
import { WebhookUrlValidationError } from '@nestarc/webhook';
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
await endpointAdmin.createEndpoint({ url, events: ['*'] });
|
|
270
|
+
} catch (err) {
|
|
271
|
+
if (err instanceof WebhookUrlValidationError) {
|
|
272
|
+
// err.reason: 'parse' | 'scheme' | 'blocked_hostname'
|
|
273
|
+
// | 'loopback' | 'private' | 'link_local' | 'invalid_target'
|
|
274
|
+
// err.url, err.resolvedIp also available
|
|
275
|
+
throw new BadRequestException({ message: err.message, reason: err.reason });
|
|
276
|
+
}
|
|
277
|
+
throw err;
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
244
281
|
### Secret handling
|
|
245
282
|
|
|
246
283
|
- Signing secrets are excluded from read queries (`listEndpoints`, `getEndpoint`)
|
package/dist/index.d.ts
CHANGED
|
@@ -20,9 +20,9 @@ export { PrismaEndpointRepository } from './adapters/prisma-endpoint.repository'
|
|
|
20
20
|
export { PrismaDeliveryRepository } from './adapters/prisma-delivery.repository';
|
|
21
21
|
export { FetchHttpClient } from './adapters/fetch-http-client';
|
|
22
22
|
export { PlaintextSecretVault } from './adapters/plaintext-secret-vault';
|
|
23
|
-
export type { WebhookModuleOptions, WebhookModuleAsyncOptions, WebhookOptionsFactory, DeliveryOptions, CircuitBreakerOptions, PollingOptions, DeliveryFailedContext, EndpointDisabledContext, } from './interfaces/webhook-options.interface';
|
|
23
|
+
export type { WebhookModuleOptions, WebhookModuleAsyncOptions, WebhookOptionsFactory, DeliveryOptions, CircuitBreakerOptions, PollingOptions, DeliveryFailedContext, DeliveryFailureKind, EndpointDisabledContext, } from './interfaces/webhook-options.interface';
|
|
24
24
|
export type { EndpointRecord, EndpointRecordWithSecret, CreateEndpointDto, UpdateEndpointDto, } from './interfaces/webhook-endpoint.interface';
|
|
25
25
|
export type { DeliveryStatus, DeliveryRecord, EventRecord, DeliveryResult, DeliveryLogFilters, } from './interfaces/webhook-delivery.interface';
|
|
26
26
|
export { WEBHOOK_MODULE_OPTIONS, WEBHOOK_EVENT_REPOSITORY, WEBHOOK_ENDPOINT_REPOSITORY, WEBHOOK_DELIVERY_REPOSITORY, WEBHOOK_HTTP_CLIENT, DEFAULT_BACKOFF_SCHEDULE, DEFAULT_DELIVERY_TIMEOUT, DEFAULT_MAX_RETRIES, DEFAULT_POLLING_INTERVAL, DEFAULT_POLLING_BATCH_SIZE, DEFAULT_CIRCUIT_BREAKER_THRESHOLD, DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MINUTES, DEFAULT_STALE_SENDING_MINUTES, } from './webhook.constants';
|
|
27
|
-
export { validateWebhookUrl, resolveAndValidateHost } from './webhook.url-validator';
|
|
27
|
+
export { validateWebhookUrl, resolveAndValidateHost, WebhookUrlValidationError, type WebhookUrlValidationReason, } from './webhook.url-validator';
|
|
28
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,kFAAkF;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,YAAY,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACrF,YAAY,EACV,yBAAyB,EACzB,eAAe,GAChB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAGhD,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,yCAAyC,CAAC;AAEjD,YAAY,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,wCAAwC,EACxC,6BAA6B,GAC9B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,kFAAkF;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,YAAY,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACrF,YAAY,EACV,yBAAyB,EACzB,eAAe,GAChB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAGhD,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,yCAAyC,CAAC;AAEjD,YAAY,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,wCAAwC,EACxC,6BAA6B,GAC9B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,0BAA0B,GAChC,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveAndValidateHost = exports.validateWebhookUrl = exports.DEFAULT_STALE_SENDING_MINUTES = exports.DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MINUTES = exports.DEFAULT_CIRCUIT_BREAKER_THRESHOLD = exports.DEFAULT_POLLING_BATCH_SIZE = exports.DEFAULT_POLLING_INTERVAL = exports.DEFAULT_MAX_RETRIES = exports.DEFAULT_DELIVERY_TIMEOUT = exports.DEFAULT_BACKOFF_SCHEDULE = exports.WEBHOOK_HTTP_CLIENT = exports.WEBHOOK_DELIVERY_REPOSITORY = exports.WEBHOOK_ENDPOINT_REPOSITORY = exports.WEBHOOK_EVENT_REPOSITORY = exports.WEBHOOK_MODULE_OPTIONS = exports.PlaintextSecretVault = exports.FetchHttpClient = exports.PrismaDeliveryRepository = exports.PrismaEndpointRepository = exports.PrismaEventRepository = exports.WebhookAdminService = exports.WebhookDeliveryAdminService = exports.WebhookEndpointAdminService = exports.WebhookEvent = exports.WebhookCircuitBreaker = exports.WebhookSigner = exports.WebhookRetryPolicy = exports.WebhookDispatcher = exports.WebhookDeliveryWorker = exports.WebhookService = exports.WebhookModule = void 0;
|
|
3
|
+
exports.WebhookUrlValidationError = exports.resolveAndValidateHost = exports.validateWebhookUrl = exports.DEFAULT_STALE_SENDING_MINUTES = exports.DEFAULT_CIRCUIT_BREAKER_COOLDOWN_MINUTES = exports.DEFAULT_CIRCUIT_BREAKER_THRESHOLD = exports.DEFAULT_POLLING_BATCH_SIZE = exports.DEFAULT_POLLING_INTERVAL = exports.DEFAULT_MAX_RETRIES = exports.DEFAULT_DELIVERY_TIMEOUT = exports.DEFAULT_BACKOFF_SCHEDULE = exports.WEBHOOK_HTTP_CLIENT = exports.WEBHOOK_DELIVERY_REPOSITORY = exports.WEBHOOK_ENDPOINT_REPOSITORY = exports.WEBHOOK_EVENT_REPOSITORY = exports.WEBHOOK_MODULE_OPTIONS = exports.PlaintextSecretVault = exports.FetchHttpClient = exports.PrismaDeliveryRepository = exports.PrismaEndpointRepository = exports.PrismaEventRepository = exports.WebhookAdminService = exports.WebhookDeliveryAdminService = exports.WebhookEndpointAdminService = exports.WebhookEvent = exports.WebhookCircuitBreaker = exports.WebhookSigner = exports.WebhookRetryPolicy = exports.WebhookDispatcher = exports.WebhookDeliveryWorker = exports.WebhookService = exports.WebhookModule = void 0;
|
|
4
4
|
// Module
|
|
5
5
|
var webhook_module_1 = require("./webhook.module");
|
|
6
6
|
Object.defineProperty(exports, "WebhookModule", { enumerable: true, get: function () { return webhook_module_1.WebhookModule; } });
|
|
@@ -56,4 +56,5 @@ Object.defineProperty(exports, "DEFAULT_STALE_SENDING_MINUTES", { enumerable: tr
|
|
|
56
56
|
var webhook_url_validator_1 = require("./webhook.url-validator");
|
|
57
57
|
Object.defineProperty(exports, "validateWebhookUrl", { enumerable: true, get: function () { return webhook_url_validator_1.validateWebhookUrl; } });
|
|
58
58
|
Object.defineProperty(exports, "resolveAndValidateHost", { enumerable: true, get: function () { return webhook_url_validator_1.resolveAndValidateHost; } });
|
|
59
|
+
Object.defineProperty(exports, "WebhookUrlValidationError", { enumerable: true, get: function () { return webhook_url_validator_1.WebhookUrlValidationError; } });
|
|
59
60
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAEtB,gBAAgB;AAChB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAC3B,mDAAwE;AAA/D,+GAAA,aAAa,OAAA;AACtB,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,iBAAiB;AACjB,mFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;AACpC,mFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;AACpC,kFAAkF;AAClF,iEAA8D;AAArD,4HAAA,mBAAmB,OAAA;AAY5B,mBAAmB;AACnB,8EAA2E;AAAlE,gIAAA,qBAAqB,OAAA;AAC9B,oFAAiF;AAAxE,sIAAA,wBAAwB,OAAA;AACjC,oFAAiF;AAAxE,sIAAA,wBAAwB,OAAA;AACjC,kEAA+D;AAAtD,oHAAA,eAAe,OAAA;AACxB,4EAAyE;AAAhE,8HAAA,oBAAoB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,mDAAiD;AAAxC,+GAAA,aAAa,OAAA;AAEtB,gBAAgB;AAChB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAC3B,mDAAwE;AAA/D,+GAAA,aAAa,OAAA;AACtB,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,iBAAiB;AACjB,mFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;AACpC,mFAA+E;AAAtE,6IAAA,2BAA2B,OAAA;AACpC,kFAAkF;AAClF,iEAA8D;AAArD,4HAAA,mBAAmB,OAAA;AAY5B,mBAAmB;AACnB,8EAA2E;AAAlE,gIAAA,qBAAqB,OAAA;AAC9B,oFAAiF;AAAxE,sIAAA,wBAAwB,OAAA;AACjC,oFAAiF;AAAxE,sIAAA,wBAAwB,OAAA;AACjC,kEAA+D;AAAtD,oHAAA,eAAe,OAAA;AACxB,4EAAyE;AAAhE,8HAAA,oBAAoB,OAAA;AA+B7B,qBAAqB;AACrB,yDAc6B;AAb3B,2HAAA,sBAAsB,OAAA;AACtB,6HAAA,wBAAwB,OAAA;AACxB,gIAAA,2BAA2B,OAAA;AAC3B,gIAAA,2BAA2B,OAAA;AAC3B,wHAAA,mBAAmB,OAAA;AACnB,6HAAA,wBAAwB,OAAA;AACxB,6HAAA,wBAAwB,OAAA;AACxB,wHAAA,mBAAmB,OAAA;AACnB,6HAAA,wBAAwB,OAAA;AACxB,+HAAA,0BAA0B,OAAA;AAC1B,sIAAA,iCAAiC,OAAA;AACjC,6IAAA,wCAAwC,OAAA;AACxC,kIAAA,6BAA6B,OAAA;AAG/B,iEAKiC;AAJ/B,2HAAA,kBAAkB,OAAA;AAClB,+HAAA,sBAAsB,OAAA;AACtB,kIAAA,yBAAyB,OAAA"}
|
|
@@ -4,6 +4,7 @@ import { WebhookEndpointRepository } from '../ports/webhook-endpoint.repository'
|
|
|
4
4
|
import { WebhookDeliveryRepository } from '../ports/webhook-delivery.repository';
|
|
5
5
|
import { WebhookHttpClient } from '../ports/webhook-http-client';
|
|
6
6
|
import { WebhookSecretVault } from '../ports/webhook-secret-vault';
|
|
7
|
+
import { WebhookUrlValidationReason } from '../webhook.url-validator';
|
|
7
8
|
export interface DeliveryOptions {
|
|
8
9
|
timeout?: number;
|
|
9
10
|
maxRetries?: number;
|
|
@@ -22,6 +23,13 @@ export interface PollingOptions {
|
|
|
22
23
|
/** Minutes before a SENDING delivery is considered stale and reset to PENDING. Default: 5 */
|
|
23
24
|
staleSendingMinutes?: number;
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Category of failure that caused the delivery to exhaust retries.
|
|
28
|
+
* - `url_validation`: SSRF defense rejected the URL (private/loopback/link-local/etc.)
|
|
29
|
+
* - `dispatch_error`: dispatcher threw an exception (timeout, ECONNREFUSED, etc.)
|
|
30
|
+
* - `http_error`: endpoint responded with a non-2xx status code
|
|
31
|
+
*/
|
|
32
|
+
export type DeliveryFailureKind = 'url_validation' | 'dispatch_error' | 'http_error';
|
|
25
33
|
export interface DeliveryFailedContext {
|
|
26
34
|
deliveryId: string;
|
|
27
35
|
endpointId: string;
|
|
@@ -32,6 +40,14 @@ export interface DeliveryFailedContext {
|
|
|
32
40
|
maxAttempts: number;
|
|
33
41
|
lastError: string | null;
|
|
34
42
|
responseStatus: number | null;
|
|
43
|
+
/** High-level classification. Omitted for backward compatibility when unknown. */
|
|
44
|
+
failureKind?: DeliveryFailureKind;
|
|
45
|
+
/** Set only when `failureKind === 'url_validation'` — structured reason from `WebhookUrlValidationError`. */
|
|
46
|
+
validationReason?: WebhookUrlValidationReason;
|
|
47
|
+
/** Set only when `failureKind === 'url_validation'` — URL that triggered validation failure. */
|
|
48
|
+
validationUrl?: string;
|
|
49
|
+
/** Set only when `failureKind === 'url_validation'` and DNS resolution was involved. */
|
|
50
|
+
resolvedIp?: string;
|
|
35
51
|
}
|
|
36
52
|
export interface EndpointDisabledContext {
|
|
37
53
|
endpointId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/webhook-options.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/webhook-options.interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.delivery-worker.d.ts","sourceRoot":"","sources":["../src/webhook.delivery-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAO5D,OAAO,
|
|
1
|
+
{"version":3,"file":"webhook.delivery-worker.d.ts","sourceRoot":"","sources":["../src/webhook.delivery-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAO5D,OAAO,EAEL,oBAAoB,EACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAEL,yBAAyB,EAC1B,MAAM,qCAAqC,CAAC;AAa7C,qBACa,qBAAsB,YAAW,eAAe;IAUzD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAd1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAK;gBAIV,YAAY,EAAE,yBAAyB,EACvC,UAAU,EAAE,iBAAiB,EAC7B,WAAW,EAAE,kBAAkB,EAC/B,cAAc,EAAE,qBAAqB,EAErC,OAAO,EAAE,oBAAoB;IAO1C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAmCb,eAAe;IAyF7B,OAAO,CAAC,sBAAsB;IAyBxB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAevC"}
|
|
@@ -19,6 +19,7 @@ const webhook_circuit_breaker_1 = require("./webhook.circuit-breaker");
|
|
|
19
19
|
const webhook_dispatcher_1 = require("./webhook.dispatcher");
|
|
20
20
|
const webhook_retry_policy_1 = require("./webhook.retry-policy");
|
|
21
21
|
const webhook_constants_1 = require("./webhook.constants");
|
|
22
|
+
const webhook_url_validator_1 = require("./webhook.url-validator");
|
|
22
23
|
let WebhookDeliveryWorker = WebhookDeliveryWorker_1 = class WebhookDeliveryWorker {
|
|
23
24
|
deliveryRepo;
|
|
24
25
|
dispatcher;
|
|
@@ -79,7 +80,7 @@ let WebhookDeliveryWorker = WebhookDeliveryWorker_1 = class WebhookDeliveryWorke
|
|
|
79
80
|
else if (newAttempts >= delivery.max_attempts) {
|
|
80
81
|
await this.deliveryRepo.markFailed(delivery.id, newAttempts, result);
|
|
81
82
|
this.logger.warn(`Delivery ${delivery.id} exhausted retries (${newAttempts}/${delivery.max_attempts})`);
|
|
82
|
-
this.fireDeliveryFailedHook(delivery, newAttempts, result.error ?? null, result.statusCode ?? null);
|
|
83
|
+
this.fireDeliveryFailedHook(delivery, newAttempts, result.error ?? null, result.statusCode ?? null, { failureKind: 'http_error' });
|
|
83
84
|
}
|
|
84
85
|
else {
|
|
85
86
|
const nextAt = this.retryPolicy.nextAttemptAt(newAttempts);
|
|
@@ -106,7 +107,15 @@ let WebhookDeliveryWorker = WebhookDeliveryWorker_1 = class WebhookDeliveryWorke
|
|
|
106
107
|
if (newAttempts >= delivery.max_attempts) {
|
|
107
108
|
await this.deliveryRepo.markFailed(delivery.id, newAttempts, errorResult);
|
|
108
109
|
this.logger.warn(`Delivery ${delivery.id} exhausted retries on exception (${newAttempts}/${delivery.max_attempts})`);
|
|
109
|
-
|
|
110
|
+
const meta = error instanceof webhook_url_validator_1.WebhookUrlValidationError
|
|
111
|
+
? {
|
|
112
|
+
failureKind: 'url_validation',
|
|
113
|
+
validationReason: error.reason,
|
|
114
|
+
validationUrl: error.url ?? delivery.url,
|
|
115
|
+
resolvedIp: error.resolvedIp,
|
|
116
|
+
}
|
|
117
|
+
: { failureKind: 'dispatch_error' };
|
|
118
|
+
this.fireDeliveryFailedHook(delivery, newAttempts, errorResult.error ?? null, null, meta);
|
|
110
119
|
}
|
|
111
120
|
else {
|
|
112
121
|
const nextAt = this.retryPolicy.nextAttemptAt(newAttempts);
|
|
@@ -121,7 +130,7 @@ let WebhookDeliveryWorker = WebhookDeliveryWorker_1 = class WebhookDeliveryWorke
|
|
|
121
130
|
this.activeDeliveries--;
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
|
-
fireDeliveryFailedHook(delivery, attempts, lastError, responseStatus) {
|
|
133
|
+
fireDeliveryFailedHook(delivery, attempts, lastError, responseStatus, meta = {}) {
|
|
125
134
|
if (!this.options.onDeliveryFailed)
|
|
126
135
|
return;
|
|
127
136
|
void Promise.resolve(this.options.onDeliveryFailed({
|
|
@@ -133,6 +142,7 @@ let WebhookDeliveryWorker = WebhookDeliveryWorker_1 = class WebhookDeliveryWorke
|
|
|
133
142
|
maxAttempts: delivery.max_attempts,
|
|
134
143
|
lastError,
|
|
135
144
|
responseStatus,
|
|
145
|
+
...meta,
|
|
136
146
|
})).catch((hookError) => {
|
|
137
147
|
this.logger.error(`onDeliveryFailed callback error: ${hookError}`);
|
|
138
148
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.delivery-worker.js","sourceRoot":"","sources":["../src/webhook.delivery-worker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAA6E;AAC7E,uEAAkE;AAClE,6DAAyD;AACzD,iEAA4D;AAC5D,2DAK6B;
|
|
1
|
+
{"version":3,"file":"webhook.delivery-worker.js","sourceRoot":"","sources":["../src/webhook.delivery-worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export type WebhookUrlValidationReason = 'parse' | 'scheme' | 'blocked_hostname' | 'loopback' | 'private' | 'link_local' | 'invalid_target';
|
|
2
|
+
export declare class WebhookUrlValidationError extends Error {
|
|
3
|
+
readonly name = "WebhookUrlValidationError";
|
|
4
|
+
readonly reason: WebhookUrlValidationReason;
|
|
5
|
+
readonly url?: string;
|
|
6
|
+
readonly resolvedIp?: string;
|
|
7
|
+
constructor(message: string, reason: WebhookUrlValidationReason, url?: string, resolvedIp?: string);
|
|
8
|
+
}
|
|
1
9
|
export declare function validateWebhookUrl(url: string): Promise<void>;
|
|
2
|
-
export declare function resolveAndValidateHost(hostname: string): Promise<void>;
|
|
10
|
+
export declare function resolveAndValidateHost(hostname: string, url?: string): Promise<void>;
|
|
3
11
|
//# sourceMappingURL=webhook.url-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.url-validator.d.ts","sourceRoot":"","sources":["../src/webhook.url-validator.ts"],"names":[],"mappings":"AAUA,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"webhook.url-validator.d.ts","sourceRoot":"","sources":["../src/webhook.url-validator.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,0BAA0B,GAClC,OAAO,GACP,QAAQ,GACR,kBAAkB,GAClB,UAAU,GACV,SAAS,GACT,YAAY,GACZ,gBAAgB,CAAC;AAErB,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,0BAA0B,EAClC,GAAG,CAAC,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM;CAQtB;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCnE;AA+GD,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAwBf"}
|
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.WebhookUrlValidationError = void 0;
|
|
36
37
|
exports.validateWebhookUrl = validateWebhookUrl;
|
|
37
38
|
exports.resolveAndValidateHost = resolveAndValidateHost;
|
|
38
39
|
const net = __importStar(require("net"));
|
|
@@ -43,57 +44,71 @@ const BLOCKED_HOSTNAMES = new Set([
|
|
|
43
44
|
'ip6-localhost',
|
|
44
45
|
'ip6-loopback',
|
|
45
46
|
]);
|
|
47
|
+
class WebhookUrlValidationError extends Error {
|
|
48
|
+
name = 'WebhookUrlValidationError';
|
|
49
|
+
reason;
|
|
50
|
+
url;
|
|
51
|
+
resolvedIp;
|
|
52
|
+
constructor(message, reason, url, resolvedIp) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.reason = reason;
|
|
55
|
+
this.url = url;
|
|
56
|
+
this.resolvedIp = resolvedIp;
|
|
57
|
+
Object.setPrototypeOf(this, WebhookUrlValidationError.prototype);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.WebhookUrlValidationError = WebhookUrlValidationError;
|
|
46
61
|
async function validateWebhookUrl(url) {
|
|
47
62
|
let parsed;
|
|
48
63
|
try {
|
|
49
64
|
parsed = new URL(url);
|
|
50
65
|
}
|
|
51
66
|
catch {
|
|
52
|
-
throw new
|
|
67
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: unable to parse "${url}"`, 'parse', url);
|
|
53
68
|
}
|
|
54
69
|
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
55
|
-
throw new
|
|
70
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: scheme must be http or https, got "${parsed.protocol}"`, 'scheme', url);
|
|
56
71
|
}
|
|
57
72
|
const hostname = parsed.hostname.toLowerCase();
|
|
58
73
|
if (BLOCKED_HOSTNAMES.has(hostname)) {
|
|
59
|
-
throw new
|
|
74
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${hostname}" is not allowed (loopback address)`, 'blocked_hostname', url);
|
|
60
75
|
}
|
|
61
76
|
if (net.isIPv4(hostname)) {
|
|
62
|
-
validateIPv4(hostname);
|
|
77
|
+
validateIPv4(hostname, url);
|
|
63
78
|
}
|
|
64
79
|
else if (net.isIPv6(hostname) || hostname.startsWith('[')) {
|
|
65
80
|
const cleanIp = hostname.replace(/^\[|\]$/g, '');
|
|
66
|
-
validateIPv6(cleanIp);
|
|
81
|
+
validateIPv6(cleanIp, url);
|
|
67
82
|
}
|
|
68
83
|
else {
|
|
69
84
|
// Hostname — resolve DNS and validate all resolved IPs
|
|
70
|
-
await resolveAndValidateHost(hostname);
|
|
85
|
+
await resolveAndValidateHost(hostname, url);
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
|
-
function validateIPv4(ip) {
|
|
88
|
+
function validateIPv4(ip, url) {
|
|
74
89
|
const parts = ip.split('.').map(Number);
|
|
75
90
|
if (parts[0] === 127) {
|
|
76
|
-
throw new
|
|
91
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a loopback address`, 'loopback', url, ip);
|
|
77
92
|
}
|
|
78
93
|
if (parts[0] === 10) {
|
|
79
|
-
throw new
|
|
94
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a private address`, 'private', url, ip);
|
|
80
95
|
}
|
|
81
96
|
if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) {
|
|
82
|
-
throw new
|
|
97
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a private address`, 'private', url, ip);
|
|
83
98
|
}
|
|
84
99
|
if (parts[0] === 192 && parts[1] === 168) {
|
|
85
|
-
throw new
|
|
100
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a private address`, 'private', url, ip);
|
|
86
101
|
}
|
|
87
102
|
if (parts[0] === 169 && parts[1] === 254) {
|
|
88
|
-
throw new
|
|
103
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a link-local/metadata address`, 'link_local', url, ip);
|
|
89
104
|
}
|
|
90
105
|
if (parts[0] === 0) {
|
|
91
|
-
throw new
|
|
106
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is not a valid target`, 'invalid_target', url, ip);
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
|
-
function validateIPv6(ip) {
|
|
109
|
+
function validateIPv6(ip, url) {
|
|
95
110
|
if (ip === '::1') {
|
|
96
|
-
throw new
|
|
111
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a loopback address`, 'loopback', url, ip);
|
|
97
112
|
}
|
|
98
113
|
const lowerIp = ip.toLowerCase();
|
|
99
114
|
// IPv4-mapped IPv6 — ::ffff:x.x.x.x or ::ffff:HHHH:HHHH (hex form)
|
|
@@ -116,19 +131,19 @@ function validateIPv6(ip) {
|
|
|
116
131
|
return; // Unknown format, let it through (conservative)
|
|
117
132
|
}
|
|
118
133
|
}
|
|
119
|
-
validateIPv4(ipv4);
|
|
134
|
+
validateIPv4(ipv4, url);
|
|
120
135
|
return;
|
|
121
136
|
}
|
|
122
137
|
const firstSegment = ip.split(':')[0].toLowerCase();
|
|
123
138
|
if (firstSegment.startsWith('fc') || firstSegment.startsWith('fd')) {
|
|
124
|
-
throw new
|
|
139
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a private address`, 'private', url, ip);
|
|
125
140
|
}
|
|
126
141
|
if (firstSegment.startsWith('fe8') || firstSegment.startsWith('fe9') ||
|
|
127
142
|
firstSegment.startsWith('fea') || firstSegment.startsWith('feb')) {
|
|
128
|
-
throw new
|
|
143
|
+
throw new WebhookUrlValidationError(`Invalid webhook URL: "${ip}" is a link-local address`, 'link_local', url, ip);
|
|
129
144
|
}
|
|
130
145
|
}
|
|
131
|
-
async function resolveAndValidateHost(hostname) {
|
|
146
|
+
async function resolveAndValidateHost(hostname, url) {
|
|
132
147
|
let addresses = [];
|
|
133
148
|
try {
|
|
134
149
|
const ipv4 = await dns.promises.resolve4(hostname);
|
|
@@ -146,10 +161,10 @@ async function resolveAndValidateHost(hostname) {
|
|
|
146
161
|
}
|
|
147
162
|
for (const ip of addresses) {
|
|
148
163
|
if (net.isIPv4(ip)) {
|
|
149
|
-
validateIPv4(ip); // throws if private
|
|
164
|
+
validateIPv4(ip, url); // throws if private
|
|
150
165
|
}
|
|
151
166
|
else if (net.isIPv6(ip)) {
|
|
152
|
-
validateIPv6(ip); // throws if private
|
|
167
|
+
validateIPv6(ip, url); // throws if private
|
|
153
168
|
}
|
|
154
169
|
}
|
|
155
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.url-validator.js","sourceRoot":"","sources":["../src/webhook.url-validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webhook.url-validator.js","sourceRoot":"","sources":["../src/webhook.url-validator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,gDAuCC;AA+GD,wDA2BC;AAxND,yCAA2B;AAC3B,yCAA2B;AAE3B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,WAAW;IACX,uBAAuB;IACvB,eAAe;IACf,cAAc;CACf,CAAC,CAAC;AAWH,MAAa,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,2BAA2B,CAAC;IACnC,MAAM,CAA6B;IACnC,GAAG,CAAU;IACb,UAAU,CAAU;IAE7B,YACE,OAAe,EACf,MAAkC,EAClC,GAAY,EACZ,UAAmB;QAEnB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IACnE,CAAC;CACF;AAlBD,8DAkBC;AAEM,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAClD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,yBAAyB,CACjC,yCAAyC,GAAG,GAAG,EAC/C,OAAO,EACP,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,yBAAyB,CACjC,2DAA2D,MAAM,CAAC,QAAQ,GAAG,EAC7E,QAAQ,EACR,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAE/C,IAAI,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,QAAQ,qCAAqC,EACtE,kBAAkB,EAClB,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACjD,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,uDAAuD;QACvD,MAAM,sBAAsB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAU,EAAE,GAAY;IAC5C,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAExC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACrB,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,yBAAyB,EACpD,UAAU,EACV,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,wBAAwB,EACnD,SAAS,EACT,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,wBAAwB,EACnD,SAAS,EACT,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,wBAAwB,EACnD,SAAS,EACT,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,oCAAoC,EAC/D,YAAY,EACZ,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,yBAAyB,EACpD,gBAAgB,EAChB,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAU,EAAE,GAAY;IAC5C,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,yBAAyB,EACpD,UAAU,EACV,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAEjC,mEAAmE;IACnE,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QACjE,IAAI,IAAY,CAAC;QAEjB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,uBAAuB;YACvB,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,gDAAgD;YAC1D,CAAC;QACH,CAAC;QAED,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,wBAAwB,EACnD,SAAS,EACT,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC;QAChE,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,EAAE,2BAA2B,EACtD,YAAY,EACZ,GAAG,EACH,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,GAAY;IAEZ,IAAI,SAAS,GAAa,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACnB,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;QAC7C,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1B,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;QAC7C,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestarc/webhook",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Outbound webhook delivery for NestJS — HMAC signing, exponential retry, circuit breaker, delivery logs, fan-out, Standard Webhooks compatible",
|
|
5
5
|
"author": "nestarc",
|
|
6
6
|
"license": "MIT",
|