@dudousxd/nestjs-notifications-webhook 0.5.0 → 0.5.2
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.cjs +23 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -47
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -121,7 +121,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
121
121
|
__name(_ts_param, "_ts_param");
|
|
122
122
|
var DEFAULT_SIGNATURE_HEADER = "X-Signature-256";
|
|
123
123
|
var Webhook = (0, import_nestjs_notifications_core.createChannel)("webhook");
|
|
124
|
-
var WebhookChannel = class {
|
|
124
|
+
var WebhookChannel = class extends import_nestjs_notifications_core.BaseChannel {
|
|
125
125
|
static {
|
|
126
126
|
__name(this, "WebhookChannel");
|
|
127
127
|
}
|
|
@@ -129,21 +129,11 @@ var WebhookChannel = class {
|
|
|
129
129
|
resolveOptions;
|
|
130
130
|
channel = "webhook";
|
|
131
131
|
constructor(options, resolveOptions) {
|
|
132
|
-
this.options = options;
|
|
133
|
-
this.resolveOptions = resolveOptions;
|
|
132
|
+
super(), this.options = options, this.resolveOptions = resolveOptions;
|
|
134
133
|
}
|
|
135
134
|
async send(notifiable, notification, context) {
|
|
136
|
-
const options =
|
|
137
|
-
const
|
|
138
|
-
if (!handler) {
|
|
139
|
-
const name = notification.constructor.notificationName ?? notification.constructor.name;
|
|
140
|
-
throw new import_nestjs_notifications_core.MissingChannelMethodError("webhook", "toWebhook()", name);
|
|
141
|
-
}
|
|
142
|
-
const result = handler({
|
|
143
|
-
notifiable,
|
|
144
|
-
localization: context?.localization,
|
|
145
|
-
tenant: context?.tenant
|
|
146
|
-
});
|
|
135
|
+
const options = this.forTenant(this.options, context, this.resolveOptions);
|
|
136
|
+
const result = this.buildPayload(notification, notifiable, "toWebhook", context);
|
|
147
137
|
const message = result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);
|
|
148
138
|
const request = message.toRequest();
|
|
149
139
|
const route = (0, import_nestjs_notifications_core.routeFor)(notifiable, "webhook", notification);
|
|
@@ -151,27 +141,19 @@ var WebhookChannel = class {
|
|
|
151
141
|
if (!url) {
|
|
152
142
|
throw new Error('The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), return one from routeNotificationFor("webhook"), or set url in forRoot().');
|
|
153
143
|
}
|
|
154
|
-
await this.post(options, url, request.method, request.body, request.headers);
|
|
155
|
-
}
|
|
156
|
-
async post(options, url, method, body, messageHeaders) {
|
|
157
|
-
const payload = JSON.stringify(body);
|
|
158
144
|
const headers = {
|
|
159
145
|
...options.headers,
|
|
160
|
-
...
|
|
161
|
-
"Content-Type": "application/json"
|
|
146
|
+
...request.headers
|
|
162
147
|
};
|
|
163
148
|
if (options.secret) {
|
|
164
|
-
const signature = (0, import_node_crypto.createHmac)("sha256", options.secret).update(
|
|
149
|
+
const signature = (0, import_node_crypto.createHmac)("sha256", options.secret).update(JSON.stringify(request.body)).digest("hex");
|
|
165
150
|
headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;
|
|
166
151
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
152
|
+
await (0, import_nestjs_notifications_core.postJson)(url, request.body, {
|
|
153
|
+
label: "Webhook",
|
|
154
|
+
method: request.method,
|
|
155
|
+
headers
|
|
171
156
|
});
|
|
172
|
-
if (!response.ok) {
|
|
173
|
-
throw new Error(`Webhook request to ${url} failed with status ${response.status}.`);
|
|
174
|
-
}
|
|
175
157
|
}
|
|
176
158
|
};
|
|
177
159
|
WebhookChannel = _ts_decorate([
|
|
@@ -187,6 +169,7 @@ WebhookChannel = _ts_decorate([
|
|
|
187
169
|
], WebhookChannel);
|
|
188
170
|
|
|
189
171
|
// src/webhook.module.ts
|
|
172
|
+
var import_nestjs_notifications_core2 = require("@dudousxd/nestjs-notifications-core");
|
|
190
173
|
var import_common2 = require("@nestjs/common");
|
|
191
174
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
192
175
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -210,25 +193,19 @@ var WebhookChannelModule = class _WebhookChannelModule {
|
|
|
210
193
|
headers: options.headers
|
|
211
194
|
} : {}
|
|
212
195
|
};
|
|
213
|
-
|
|
214
|
-
{
|
|
215
|
-
provide: WEBHOOK_OPTIONS,
|
|
216
|
-
useValue: webhookOptions
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
provide: WEBHOOK_OPTIONS_RESOLVER,
|
|
220
|
-
useValue: options.resolveOptions ?? null
|
|
221
|
-
},
|
|
222
|
-
WebhookChannel
|
|
223
|
-
];
|
|
224
|
-
return {
|
|
196
|
+
return (0, import_nestjs_notifications_core2.defineChannelModule)({
|
|
225
197
|
module: _WebhookChannelModule,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
198
|
+
channel: WebhookChannel,
|
|
199
|
+
optionsToken: WEBHOOK_OPTIONS,
|
|
200
|
+
options: webhookOptions,
|
|
201
|
+
resolver: {
|
|
202
|
+
token: WEBHOOK_OPTIONS_RESOLVER,
|
|
203
|
+
value: options.resolveOptions
|
|
204
|
+
},
|
|
205
|
+
...options.global !== void 0 ? {
|
|
206
|
+
global: options.global
|
|
207
|
+
} : {}
|
|
208
|
+
});
|
|
232
209
|
}
|
|
233
210
|
};
|
|
234
211
|
WebhookChannelModule = _ts_decorate2([
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/webhook-message.ts","../src/webhook.channel.ts","../src/tokens.ts","../src/webhook.module.ts"],"sourcesContent":["export {\n WebhookMessage,\n type WebhookMethod,\n type WebhookRequest,\n} from './webhook-message';\nexport {\n Webhook,\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookNotification,\n type WebhookOptionsResolver,\n} from './webhook.channel';\nexport {\n WebhookChannelModule,\n type WebhookChannelModuleOptions,\n} from './webhook.module';\nexport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\n","/** The HTTP method used for a webhook request. */\nexport type WebhookMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'GET';\n\n/** The resolved request description produced by {@link WebhookMessage.toRequest}. */\nexport interface WebhookRequest {\n /** Target URL, when set on the message; otherwise resolved by the channel. */\n url?: string | undefined;\n method: WebhookMethod;\n headers: Record<string, string>;\n /** The JSON body to send (a plain object). */\n body: Record<string, unknown>;\n}\n\n/**\n * A fluent builder for a webhook request.\n *\n * ```ts\n * new WebhookMessage()\n * .url('https://example.com/hooks/orders')\n * .header('X-Signature', sign(payload))\n * .payload({ event: 'order.paid', id: 42 });\n * ```\n */\nexport class WebhookMessage {\n private _url?: string;\n private _method: WebhookMethod = 'POST';\n private _headers: Record<string, string> = {};\n private _payload: Record<string, unknown> = {};\n\n /** Set the target URL (overrides the route and configured default). */\n url(u: string): this {\n this._url = u;\n return this;\n }\n\n /** Set the JSON body to send. */\n payload(obj: Record<string, unknown>): this {\n this._payload = obj;\n return this;\n }\n\n /** Set a single request header. */\n header(key: string, value: string): this {\n this._headers[key] = value;\n return this;\n }\n\n /** Merge multiple request headers. */\n headers(obj: Record<string, string>): this {\n this._headers = { ...this._headers, ...obj };\n return this;\n }\n\n /** Set the HTTP method (default `POST`). */\n method(m: WebhookMethod): this {\n this._method = m;\n return this;\n }\n\n get urlValue(): string | undefined {\n return this._url;\n }\n\n get methodValue(): WebhookMethod {\n return this._method;\n }\n\n get headerValues(): Record<string, string> {\n return this._headers;\n }\n\n get payloadValue(): Record<string, unknown> {\n return this._payload;\n }\n\n /** Serialize to a {@link WebhookRequest}. */\n toRequest(): WebhookRequest {\n return {\n url: this._url,\n method: this._method,\n headers: { ...this._headers },\n body: this._payload,\n };\n }\n}\n","import { createHmac } from 'node:crypto';\nimport {\n type ChannelContext,\n type ChannelDriver,\n type DeliveryContext,\n MissingChannelMethodError,\n type Notifiable,\n type Notification,\n createChannel,\n getHandler,\n routeFor,\n} from '@dudousxd/nestjs-notifications-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport { WebhookMessage } from './webhook-message';\nimport type { WebhookMethod } from './webhook-message';\n\nconst DEFAULT_SIGNATURE_HEADER = 'X-Signature-256';\n\n/** Channel handle: use as `@Webhook()` on a payload method, or as a token in `via()`. */\nexport const Webhook = createChannel('webhook');\n\n/** Resolved runtime options for the webhook channel. */\nexport interface WebhookChannelOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * HMAC-SHA256 secret. When set, the request is signed: the header (default\n * `X-Signature-256`) is set to `sha256=<hex digest of the raw JSON body>`, so the receiver\n * can verify authenticity. Per-tenant secrets work via `resolveOptions`.\n */\n secret?: string;\n /** Header name for the signature. Default `X-Signature-256`. */\n signatureHeader?: string;\n}\n\n/**\n * Implement this on a notification to define its webhook payload. Returning a plain\n * object is treated as the JSON body to POST; return a {@link WebhookMessage} for full\n * control over the url, method and headers.\n */\nexport interface WebhookNotification extends Notification {\n toWebhook(ctx: ChannelContext): WebhookMessage | Record<string, unknown>;\n}\n\n/** Resolves per-tenant {@link WebhookChannelOptions} from a tenant id. */\nexport type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;\n\n/**\n * Delivers a notification by sending an HTTP request (JSON body) to a webhook endpoint.\n * The target URL comes from the {@link WebhookMessage}, else from\n * `routeNotificationFor('webhook')` (a URL string), else from the configured default.\n */\n@Injectable()\nexport class WebhookChannel implements ChannelDriver {\n readonly channel = 'webhook';\n\n constructor(\n @Inject(WEBHOOK_OPTIONS)\n private readonly options: WebhookChannelOptions,\n @Optional()\n @Inject(WEBHOOK_OPTIONS_RESOLVER)\n private readonly resolveOptions?: WebhookOptionsResolver,\n ) {}\n\n async send(\n notifiable: Notifiable,\n notification: Notification,\n context?: DeliveryContext,\n ): Promise<void> {\n const options =\n context?.tenant && this.resolveOptions ? this.resolveOptions(context.tenant) : this.options;\n\n const handler = getHandler(notification, 'webhook', 'toWebhook');\n if (!handler) {\n const name =\n (notification.constructor as { notificationName?: string }).notificationName ??\n notification.constructor.name;\n throw new MissingChannelMethodError('webhook', 'toWebhook()', name);\n }\n\n const result = handler({\n notifiable,\n localization: context?.localization,\n tenant: context?.tenant,\n }) as WebhookMessage | Record<string, unknown>;\n const message =\n result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);\n const request = message.toRequest();\n\n const route = routeFor(notifiable, 'webhook', notification);\n const url = request.url ?? (typeof route === 'string' ? route : undefined) ?? options.url;\n\n if (!url) {\n throw new Error(\n 'The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), ' +\n 'return one from routeNotificationFor(\"webhook\"), or set url in forRoot().',\n );\n }\n\n await this.post(options, url, request.method, request.body, request.headers);\n }\n\n private async post(\n options: WebhookChannelOptions,\n url: string,\n method: WebhookMethod,\n body: Record<string, unknown>,\n messageHeaders: Record<string, string>,\n ): Promise<void> {\n const payload = JSON.stringify(body);\n const headers: Record<string, string> = {\n ...options.headers,\n ...messageHeaders,\n 'Content-Type': 'application/json',\n };\n\n if (options.secret) {\n const signature = createHmac('sha256', options.secret).update(payload).digest('hex');\n headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: payload,\n });\n\n if (!response.ok) {\n throw new Error(`Webhook request to ${url} failed with status ${response.status}.`);\n }\n }\n}\n","/** DI token for the resolved {@link WebhookChannelOptions} (default url, headers). */\nexport const WEBHOOK_OPTIONS = Symbol('WEBHOOK_OPTIONS');\n\n/** DI token for the optional per-tenant {@link WebhookChannelOptions} resolver. */\nexport const WEBHOOK_OPTIONS_RESOLVER = Symbol('WEBHOOK_OPTIONS_RESOLVER');\n","import { type DynamicModule, Module, type Provider } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport {\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookOptionsResolver,\n} from './webhook.channel';\n\nexport interface WebhookChannelModuleOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * Optional per-tenant options resolver. When a notification is delivered with a\n * `context.tenant`, the returned options are used instead of the defaults.\n */\n resolveOptions?: WebhookOptionsResolver;\n /** Register globally so the channel is discoverable app-wide. Default true. */\n global?: boolean;\n}\n\n/**\n * Registers the webhook channel.\n *\n * ```ts\n * WebhookChannelModule.forRoot({ url: 'https://example.com/hooks/notifications' });\n * ```\n */\n@Module({})\nexport class WebhookChannelModule {\n static forRoot(options: WebhookChannelModuleOptions = {}): DynamicModule {\n const webhookOptions: WebhookChannelOptions = {\n // Set each field only when provided (exactOptionalPropertyTypes); the channel resolves a\n // per-notifiable URL and default headers when these are absent.\n ...(options.url !== undefined ? { url: options.url } : {}),\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n };\n\n const providers: Provider[] = [\n { provide: WEBHOOK_OPTIONS, useValue: webhookOptions },\n { provide: WEBHOOK_OPTIONS_RESOLVER, useValue: options.resolveOptions ?? null },\n WebhookChannel,\n ];\n\n return {\n module: WebhookChannelModule,\n global: options.global ?? true,\n providers,\n exports: [WebhookChannel],\n };\n }\n}\n"],"mappings":"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","names":["WebhookMessage","_url","_method","_headers","_payload","url","u","payload","obj","header","key","value","headers","method","m","urlValue","methodValue","headerValues","payloadValue","toRequest","body","WEBHOOK_OPTIONS","Symbol","WEBHOOK_OPTIONS_RESOLVER","DEFAULT_SIGNATURE_HEADER","Webhook","createChannel","WebhookChannel","channel","options","resolveOptions","send","notifiable","notification","context","tenant","handler","getHandler","name","notificationName","MissingChannelMethodError","result","localization","message","WebhookMessage","payload","request","toRequest","route","routeFor","url","undefined","Error","post","method","body","headers","messageHeaders","JSON","stringify","secret","signature","createHmac","update","digest","signatureHeader","response","fetch","ok","status","import_common","WebhookChannelModule","forRoot","options","webhookOptions","url","undefined","headers","providers","provide","WEBHOOK_OPTIONS","useValue","WEBHOOK_OPTIONS_RESOLVER","resolveOptions","WebhookChannel","module","global","exports"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/webhook-message.ts","../src/webhook.channel.ts","../src/tokens.ts","../src/webhook.module.ts"],"sourcesContent":["export {\n WebhookMessage,\n type WebhookMethod,\n type WebhookRequest,\n} from './webhook-message';\nexport {\n Webhook,\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookNotification,\n type WebhookOptionsResolver,\n} from './webhook.channel';\nexport {\n WebhookChannelModule,\n type WebhookChannelModuleOptions,\n} from './webhook.module';\nexport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\n","/** The HTTP method used for a webhook request. */\nexport type WebhookMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'GET';\n\n/** The resolved request description produced by {@link WebhookMessage.toRequest}. */\nexport interface WebhookRequest {\n /** Target URL, when set on the message; otherwise resolved by the channel. */\n url?: string | undefined;\n method: WebhookMethod;\n headers: Record<string, string>;\n /** The JSON body to send (a plain object). */\n body: Record<string, unknown>;\n}\n\n/**\n * A fluent builder for a webhook request.\n *\n * ```ts\n * new WebhookMessage()\n * .url('https://example.com/hooks/orders')\n * .header('X-Signature', sign(payload))\n * .payload({ event: 'order.paid', id: 42 });\n * ```\n */\nexport class WebhookMessage {\n private _url?: string;\n private _method: WebhookMethod = 'POST';\n private _headers: Record<string, string> = {};\n private _payload: Record<string, unknown> = {};\n\n /** Set the target URL (overrides the route and configured default). */\n url(u: string): this {\n this._url = u;\n return this;\n }\n\n /** Set the JSON body to send. */\n payload(obj: Record<string, unknown>): this {\n this._payload = obj;\n return this;\n }\n\n /** Set a single request header. */\n header(key: string, value: string): this {\n this._headers[key] = value;\n return this;\n }\n\n /** Merge multiple request headers. */\n headers(obj: Record<string, string>): this {\n this._headers = { ...this._headers, ...obj };\n return this;\n }\n\n /** Set the HTTP method (default `POST`). */\n method(m: WebhookMethod): this {\n this._method = m;\n return this;\n }\n\n get urlValue(): string | undefined {\n return this._url;\n }\n\n get methodValue(): WebhookMethod {\n return this._method;\n }\n\n get headerValues(): Record<string, string> {\n return this._headers;\n }\n\n get payloadValue(): Record<string, unknown> {\n return this._payload;\n }\n\n /** Serialize to a {@link WebhookRequest}. */\n toRequest(): WebhookRequest {\n return {\n url: this._url,\n method: this._method,\n headers: { ...this._headers },\n body: this._payload,\n };\n }\n}\n","import { createHmac } from 'node:crypto';\nimport {\n BaseChannel,\n type ChannelContext,\n type DeliveryContext,\n type Notifiable,\n type Notification,\n createChannel,\n postJson,\n routeFor,\n} from '@dudousxd/nestjs-notifications-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport { WebhookMessage } from './webhook-message';\n\nconst DEFAULT_SIGNATURE_HEADER = 'X-Signature-256';\n\n/** Channel handle: use as `@Webhook()` on a payload method, or as a token in `via()`. */\nexport const Webhook = createChannel('webhook');\n\n/** Resolved runtime options for the webhook channel. */\nexport interface WebhookChannelOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * HMAC-SHA256 secret. When set, the request is signed: the header (default\n * `X-Signature-256`) is set to `sha256=<hex digest of the raw JSON body>`, so the receiver\n * can verify authenticity. Per-tenant secrets work via `resolveOptions`.\n */\n secret?: string;\n /** Header name for the signature. Default `X-Signature-256`. */\n signatureHeader?: string;\n}\n\n/**\n * Implement this on a notification to define its webhook payload. Returning a plain\n * object is treated as the JSON body to POST; return a {@link WebhookMessage} for full\n * control over the url, method and headers.\n */\nexport interface WebhookNotification extends Notification {\n toWebhook(ctx: ChannelContext): WebhookMessage | Record<string, unknown>;\n}\n\n/** Resolves per-tenant {@link WebhookChannelOptions} from a tenant id. */\nexport type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;\n\n/**\n * Delivers a notification by sending an HTTP request (JSON body) to a webhook endpoint.\n * The target URL comes from the {@link WebhookMessage}, else from\n * `routeNotificationFor('webhook')` (a URL string), else from the configured default.\n */\n@Injectable()\nexport class WebhookChannel extends BaseChannel {\n readonly channel = 'webhook';\n\n constructor(\n @Inject(WEBHOOK_OPTIONS)\n private readonly options: WebhookChannelOptions,\n @Optional()\n @Inject(WEBHOOK_OPTIONS_RESOLVER)\n private readonly resolveOptions?: WebhookOptionsResolver,\n ) {\n super();\n }\n\n async send(\n notifiable: Notifiable,\n notification: Notification,\n context?: DeliveryContext,\n ): Promise<void> {\n const options = this.forTenant(this.options, context, this.resolveOptions);\n const result = this.buildPayload<WebhookMessage | Record<string, unknown>>(\n notification,\n notifiable,\n 'toWebhook',\n context,\n );\n const message =\n result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);\n const request = message.toRequest();\n\n const route = routeFor(notifiable, 'webhook', notification);\n const url = request.url ?? (typeof route === 'string' ? route : undefined) ?? options.url;\n\n if (!url) {\n throw new Error(\n 'The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), ' +\n 'return one from routeNotificationFor(\"webhook\"), or set url in forRoot().',\n );\n }\n\n const headers: Record<string, string> = { ...options.headers, ...request.headers };\n if (options.secret) {\n const signature = createHmac('sha256', options.secret)\n .update(JSON.stringify(request.body))\n .digest('hex');\n headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;\n }\n\n await postJson(url, request.body, { label: 'Webhook', method: request.method, headers });\n }\n}\n","/** DI token for the resolved {@link WebhookChannelOptions} (default url, headers). */\nexport const WEBHOOK_OPTIONS = Symbol('WEBHOOK_OPTIONS');\n\n/** DI token for the optional per-tenant {@link WebhookChannelOptions} resolver. */\nexport const WEBHOOK_OPTIONS_RESOLVER = Symbol('WEBHOOK_OPTIONS_RESOLVER');\n","import { defineChannelModule } from '@dudousxd/nestjs-notifications-core';\nimport { type DynamicModule, Module } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport {\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookOptionsResolver,\n} from './webhook.channel';\n\nexport interface WebhookChannelModuleOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * Optional per-tenant options resolver. When a notification is delivered with a\n * `context.tenant`, the returned options are used instead of the defaults.\n */\n resolveOptions?: WebhookOptionsResolver;\n /** Register globally so the channel is discoverable app-wide. Default true. */\n global?: boolean;\n}\n\n/**\n * Registers the webhook channel.\n *\n * ```ts\n * WebhookChannelModule.forRoot({ url: 'https://example.com/hooks/notifications' });\n * ```\n */\n@Module({})\nexport class WebhookChannelModule {\n static forRoot(options: WebhookChannelModuleOptions = {}): DynamicModule {\n const webhookOptions: WebhookChannelOptions = {\n // Set each field only when provided (exactOptionalPropertyTypes); the channel resolves a\n // per-notifiable URL and default headers when these are absent.\n ...(options.url !== undefined ? { url: options.url } : {}),\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n };\n\n return defineChannelModule({\n module: WebhookChannelModule,\n channel: WebhookChannel,\n optionsToken: WEBHOOK_OPTIONS,\n options: webhookOptions,\n resolver: { token: WEBHOOK_OPTIONS_RESOLVER, value: options.resolveOptions },\n ...(options.global !== undefined ? { global: options.global } : {}),\n });\n }\n}\n"],"mappings":"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","names":["WebhookMessage","_url","_method","_headers","_payload","url","u","payload","obj","header","key","value","headers","method","m","urlValue","methodValue","headerValues","payloadValue","toRequest","body","WEBHOOK_OPTIONS","Symbol","WEBHOOK_OPTIONS_RESOLVER","DEFAULT_SIGNATURE_HEADER","Webhook","createChannel","WebhookChannel","BaseChannel","channel","options","resolveOptions","send","notifiable","notification","context","forTenant","result","buildPayload","message","WebhookMessage","payload","request","toRequest","route","routeFor","url","undefined","Error","headers","secret","signature","createHmac","update","JSON","stringify","body","digest","signatureHeader","postJson","label","method","import_nestjs_notifications_core","import_common","WebhookChannelModule","forRoot","options","webhookOptions","url","undefined","headers","defineChannelModule","module","channel","WebhookChannel","optionsToken","WEBHOOK_OPTIONS","resolver","token","WEBHOOK_OPTIONS_RESOLVER","value","resolveOptions","global"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _dudousxd_nestjs_notifications_core from '@dudousxd/nestjs-notifications-core';
|
|
2
|
-
import {
|
|
2
|
+
import { BaseChannel, Notifiable, Notification, DeliveryContext, ChannelContext } from '@dudousxd/nestjs-notifications-core';
|
|
3
3
|
import { DynamicModule } from '@nestjs/common';
|
|
4
4
|
|
|
5
5
|
/** The HTTP method used for a webhook request. */
|
|
@@ -78,13 +78,12 @@ type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;
|
|
|
78
78
|
* The target URL comes from the {@link WebhookMessage}, else from
|
|
79
79
|
* `routeNotificationFor('webhook')` (a URL string), else from the configured default.
|
|
80
80
|
*/
|
|
81
|
-
declare class WebhookChannel
|
|
81
|
+
declare class WebhookChannel extends BaseChannel {
|
|
82
82
|
private readonly options;
|
|
83
83
|
private readonly resolveOptions?;
|
|
84
84
|
readonly channel = "webhook";
|
|
85
85
|
constructor(options: WebhookChannelOptions, resolveOptions?: WebhookOptionsResolver | undefined);
|
|
86
86
|
send(notifiable: Notifiable, notification: Notification, context?: DeliveryContext): Promise<void>;
|
|
87
|
-
private post;
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
interface WebhookChannelModuleOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _dudousxd_nestjs_notifications_core from '@dudousxd/nestjs-notifications-core';
|
|
2
|
-
import {
|
|
2
|
+
import { BaseChannel, Notifiable, Notification, DeliveryContext, ChannelContext } from '@dudousxd/nestjs-notifications-core';
|
|
3
3
|
import { DynamicModule } from '@nestjs/common';
|
|
4
4
|
|
|
5
5
|
/** The HTTP method used for a webhook request. */
|
|
@@ -78,13 +78,12 @@ type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;
|
|
|
78
78
|
* The target URL comes from the {@link WebhookMessage}, else from
|
|
79
79
|
* `routeNotificationFor('webhook')` (a URL string), else from the configured default.
|
|
80
80
|
*/
|
|
81
|
-
declare class WebhookChannel
|
|
81
|
+
declare class WebhookChannel extends BaseChannel {
|
|
82
82
|
private readonly options;
|
|
83
83
|
private readonly resolveOptions?;
|
|
84
84
|
readonly channel = "webhook";
|
|
85
85
|
constructor(options: WebhookChannelOptions, resolveOptions?: WebhookOptionsResolver | undefined);
|
|
86
86
|
send(notifiable: Notifiable, notification: Notification, context?: DeliveryContext): Promise<void>;
|
|
87
|
-
private post;
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
interface WebhookChannelModuleOptions {
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var WebhookMessage = class {
|
|
|
65
65
|
|
|
66
66
|
// src/webhook.channel.ts
|
|
67
67
|
import { createHmac } from "crypto";
|
|
68
|
-
import {
|
|
68
|
+
import { BaseChannel, createChannel, postJson, routeFor } from "@dudousxd/nestjs-notifications-core";
|
|
69
69
|
import { Inject, Injectable, Optional } from "@nestjs/common";
|
|
70
70
|
|
|
71
71
|
// src/tokens.ts
|
|
@@ -92,7 +92,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
92
92
|
__name(_ts_param, "_ts_param");
|
|
93
93
|
var DEFAULT_SIGNATURE_HEADER = "X-Signature-256";
|
|
94
94
|
var Webhook = createChannel("webhook");
|
|
95
|
-
var WebhookChannel = class {
|
|
95
|
+
var WebhookChannel = class extends BaseChannel {
|
|
96
96
|
static {
|
|
97
97
|
__name(this, "WebhookChannel");
|
|
98
98
|
}
|
|
@@ -100,21 +100,11 @@ var WebhookChannel = class {
|
|
|
100
100
|
resolveOptions;
|
|
101
101
|
channel = "webhook";
|
|
102
102
|
constructor(options, resolveOptions) {
|
|
103
|
-
this.options = options;
|
|
104
|
-
this.resolveOptions = resolveOptions;
|
|
103
|
+
super(), this.options = options, this.resolveOptions = resolveOptions;
|
|
105
104
|
}
|
|
106
105
|
async send(notifiable, notification, context) {
|
|
107
|
-
const options =
|
|
108
|
-
const
|
|
109
|
-
if (!handler) {
|
|
110
|
-
const name = notification.constructor.notificationName ?? notification.constructor.name;
|
|
111
|
-
throw new MissingChannelMethodError("webhook", "toWebhook()", name);
|
|
112
|
-
}
|
|
113
|
-
const result = handler({
|
|
114
|
-
notifiable,
|
|
115
|
-
localization: context?.localization,
|
|
116
|
-
tenant: context?.tenant
|
|
117
|
-
});
|
|
106
|
+
const options = this.forTenant(this.options, context, this.resolveOptions);
|
|
107
|
+
const result = this.buildPayload(notification, notifiable, "toWebhook", context);
|
|
118
108
|
const message = result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);
|
|
119
109
|
const request = message.toRequest();
|
|
120
110
|
const route = routeFor(notifiable, "webhook", notification);
|
|
@@ -122,27 +112,19 @@ var WebhookChannel = class {
|
|
|
122
112
|
if (!url) {
|
|
123
113
|
throw new Error('The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), return one from routeNotificationFor("webhook"), or set url in forRoot().');
|
|
124
114
|
}
|
|
125
|
-
await this.post(options, url, request.method, request.body, request.headers);
|
|
126
|
-
}
|
|
127
|
-
async post(options, url, method, body, messageHeaders) {
|
|
128
|
-
const payload = JSON.stringify(body);
|
|
129
115
|
const headers = {
|
|
130
116
|
...options.headers,
|
|
131
|
-
...
|
|
132
|
-
"Content-Type": "application/json"
|
|
117
|
+
...request.headers
|
|
133
118
|
};
|
|
134
119
|
if (options.secret) {
|
|
135
|
-
const signature = createHmac("sha256", options.secret).update(
|
|
120
|
+
const signature = createHmac("sha256", options.secret).update(JSON.stringify(request.body)).digest("hex");
|
|
136
121
|
headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;
|
|
137
122
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
123
|
+
await postJson(url, request.body, {
|
|
124
|
+
label: "Webhook",
|
|
125
|
+
method: request.method,
|
|
126
|
+
headers
|
|
142
127
|
});
|
|
143
|
-
if (!response.ok) {
|
|
144
|
-
throw new Error(`Webhook request to ${url} failed with status ${response.status}.`);
|
|
145
|
-
}
|
|
146
128
|
}
|
|
147
129
|
};
|
|
148
130
|
WebhookChannel = _ts_decorate([
|
|
@@ -158,6 +140,7 @@ WebhookChannel = _ts_decorate([
|
|
|
158
140
|
], WebhookChannel);
|
|
159
141
|
|
|
160
142
|
// src/webhook.module.ts
|
|
143
|
+
import { defineChannelModule } from "@dudousxd/nestjs-notifications-core";
|
|
161
144
|
import { Module } from "@nestjs/common";
|
|
162
145
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
163
146
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -181,25 +164,19 @@ var WebhookChannelModule = class _WebhookChannelModule {
|
|
|
181
164
|
headers: options.headers
|
|
182
165
|
} : {}
|
|
183
166
|
};
|
|
184
|
-
|
|
185
|
-
{
|
|
186
|
-
provide: WEBHOOK_OPTIONS,
|
|
187
|
-
useValue: webhookOptions
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
provide: WEBHOOK_OPTIONS_RESOLVER,
|
|
191
|
-
useValue: options.resolveOptions ?? null
|
|
192
|
-
},
|
|
193
|
-
WebhookChannel
|
|
194
|
-
];
|
|
195
|
-
return {
|
|
167
|
+
return defineChannelModule({
|
|
196
168
|
module: _WebhookChannelModule,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
169
|
+
channel: WebhookChannel,
|
|
170
|
+
optionsToken: WEBHOOK_OPTIONS,
|
|
171
|
+
options: webhookOptions,
|
|
172
|
+
resolver: {
|
|
173
|
+
token: WEBHOOK_OPTIONS_RESOLVER,
|
|
174
|
+
value: options.resolveOptions
|
|
175
|
+
},
|
|
176
|
+
...options.global !== void 0 ? {
|
|
177
|
+
global: options.global
|
|
178
|
+
} : {}
|
|
179
|
+
});
|
|
203
180
|
}
|
|
204
181
|
};
|
|
205
182
|
WebhookChannelModule = _ts_decorate2([
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/webhook-message.ts","../src/webhook.channel.ts","../src/tokens.ts","../src/webhook.module.ts"],"sourcesContent":["/** The HTTP method used for a webhook request. */\nexport type WebhookMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'GET';\n\n/** The resolved request description produced by {@link WebhookMessage.toRequest}. */\nexport interface WebhookRequest {\n /** Target URL, when set on the message; otherwise resolved by the channel. */\n url?: string | undefined;\n method: WebhookMethod;\n headers: Record<string, string>;\n /** The JSON body to send (a plain object). */\n body: Record<string, unknown>;\n}\n\n/**\n * A fluent builder for a webhook request.\n *\n * ```ts\n * new WebhookMessage()\n * .url('https://example.com/hooks/orders')\n * .header('X-Signature', sign(payload))\n * .payload({ event: 'order.paid', id: 42 });\n * ```\n */\nexport class WebhookMessage {\n private _url?: string;\n private _method: WebhookMethod = 'POST';\n private _headers: Record<string, string> = {};\n private _payload: Record<string, unknown> = {};\n\n /** Set the target URL (overrides the route and configured default). */\n url(u: string): this {\n this._url = u;\n return this;\n }\n\n /** Set the JSON body to send. */\n payload(obj: Record<string, unknown>): this {\n this._payload = obj;\n return this;\n }\n\n /** Set a single request header. */\n header(key: string, value: string): this {\n this._headers[key] = value;\n return this;\n }\n\n /** Merge multiple request headers. */\n headers(obj: Record<string, string>): this {\n this._headers = { ...this._headers, ...obj };\n return this;\n }\n\n /** Set the HTTP method (default `POST`). */\n method(m: WebhookMethod): this {\n this._method = m;\n return this;\n }\n\n get urlValue(): string | undefined {\n return this._url;\n }\n\n get methodValue(): WebhookMethod {\n return this._method;\n }\n\n get headerValues(): Record<string, string> {\n return this._headers;\n }\n\n get payloadValue(): Record<string, unknown> {\n return this._payload;\n }\n\n /** Serialize to a {@link WebhookRequest}. */\n toRequest(): WebhookRequest {\n return {\n url: this._url,\n method: this._method,\n headers: { ...this._headers },\n body: this._payload,\n };\n }\n}\n","import { createHmac } from 'node:crypto';\nimport {\n type ChannelContext,\n type ChannelDriver,\n type DeliveryContext,\n MissingChannelMethodError,\n type Notifiable,\n type Notification,\n createChannel,\n getHandler,\n routeFor,\n} from '@dudousxd/nestjs-notifications-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport { WebhookMessage } from './webhook-message';\nimport type { WebhookMethod } from './webhook-message';\n\nconst DEFAULT_SIGNATURE_HEADER = 'X-Signature-256';\n\n/** Channel handle: use as `@Webhook()` on a payload method, or as a token in `via()`. */\nexport const Webhook = createChannel('webhook');\n\n/** Resolved runtime options for the webhook channel. */\nexport interface WebhookChannelOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * HMAC-SHA256 secret. When set, the request is signed: the header (default\n * `X-Signature-256`) is set to `sha256=<hex digest of the raw JSON body>`, so the receiver\n * can verify authenticity. Per-tenant secrets work via `resolveOptions`.\n */\n secret?: string;\n /** Header name for the signature. Default `X-Signature-256`. */\n signatureHeader?: string;\n}\n\n/**\n * Implement this on a notification to define its webhook payload. Returning a plain\n * object is treated as the JSON body to POST; return a {@link WebhookMessage} for full\n * control over the url, method and headers.\n */\nexport interface WebhookNotification extends Notification {\n toWebhook(ctx: ChannelContext): WebhookMessage | Record<string, unknown>;\n}\n\n/** Resolves per-tenant {@link WebhookChannelOptions} from a tenant id. */\nexport type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;\n\n/**\n * Delivers a notification by sending an HTTP request (JSON body) to a webhook endpoint.\n * The target URL comes from the {@link WebhookMessage}, else from\n * `routeNotificationFor('webhook')` (a URL string), else from the configured default.\n */\n@Injectable()\nexport class WebhookChannel implements ChannelDriver {\n readonly channel = 'webhook';\n\n constructor(\n @Inject(WEBHOOK_OPTIONS)\n private readonly options: WebhookChannelOptions,\n @Optional()\n @Inject(WEBHOOK_OPTIONS_RESOLVER)\n private readonly resolveOptions?: WebhookOptionsResolver,\n ) {}\n\n async send(\n notifiable: Notifiable,\n notification: Notification,\n context?: DeliveryContext,\n ): Promise<void> {\n const options =\n context?.tenant && this.resolveOptions ? this.resolveOptions(context.tenant) : this.options;\n\n const handler = getHandler(notification, 'webhook', 'toWebhook');\n if (!handler) {\n const name =\n (notification.constructor as { notificationName?: string }).notificationName ??\n notification.constructor.name;\n throw new MissingChannelMethodError('webhook', 'toWebhook()', name);\n }\n\n const result = handler({\n notifiable,\n localization: context?.localization,\n tenant: context?.tenant,\n }) as WebhookMessage | Record<string, unknown>;\n const message =\n result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);\n const request = message.toRequest();\n\n const route = routeFor(notifiable, 'webhook', notification);\n const url = request.url ?? (typeof route === 'string' ? route : undefined) ?? options.url;\n\n if (!url) {\n throw new Error(\n 'The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), ' +\n 'return one from routeNotificationFor(\"webhook\"), or set url in forRoot().',\n );\n }\n\n await this.post(options, url, request.method, request.body, request.headers);\n }\n\n private async post(\n options: WebhookChannelOptions,\n url: string,\n method: WebhookMethod,\n body: Record<string, unknown>,\n messageHeaders: Record<string, string>,\n ): Promise<void> {\n const payload = JSON.stringify(body);\n const headers: Record<string, string> = {\n ...options.headers,\n ...messageHeaders,\n 'Content-Type': 'application/json',\n };\n\n if (options.secret) {\n const signature = createHmac('sha256', options.secret).update(payload).digest('hex');\n headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: payload,\n });\n\n if (!response.ok) {\n throw new Error(`Webhook request to ${url} failed with status ${response.status}.`);\n }\n }\n}\n","/** DI token for the resolved {@link WebhookChannelOptions} (default url, headers). */\nexport const WEBHOOK_OPTIONS = Symbol('WEBHOOK_OPTIONS');\n\n/** DI token for the optional per-tenant {@link WebhookChannelOptions} resolver. */\nexport const WEBHOOK_OPTIONS_RESOLVER = Symbol('WEBHOOK_OPTIONS_RESOLVER');\n","import { type DynamicModule, Module, type Provider } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport {\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookOptionsResolver,\n} from './webhook.channel';\n\nexport interface WebhookChannelModuleOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * Optional per-tenant options resolver. When a notification is delivered with a\n * `context.tenant`, the returned options are used instead of the defaults.\n */\n resolveOptions?: WebhookOptionsResolver;\n /** Register globally so the channel is discoverable app-wide. Default true. */\n global?: boolean;\n}\n\n/**\n * Registers the webhook channel.\n *\n * ```ts\n * WebhookChannelModule.forRoot({ url: 'https://example.com/hooks/notifications' });\n * ```\n */\n@Module({})\nexport class WebhookChannelModule {\n static forRoot(options: WebhookChannelModuleOptions = {}): DynamicModule {\n const webhookOptions: WebhookChannelOptions = {\n // Set each field only when provided (exactOptionalPropertyTypes); the channel resolves a\n // per-notifiable URL and default headers when these are absent.\n ...(options.url !== undefined ? { url: options.url } : {}),\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n };\n\n const providers: Provider[] = [\n { provide: WEBHOOK_OPTIONS, useValue: webhookOptions },\n { provide: WEBHOOK_OPTIONS_RESOLVER, useValue: options.resolveOptions ?? null },\n WebhookChannel,\n ];\n\n return {\n module: WebhookChannelModule,\n global: options.global ?? true,\n providers,\n exports: [WebhookChannel],\n };\n }\n}\n"],"mappings":";;;;AAuBO,IAAMA,iBAAN,MAAMA;EAvBb,OAuBaA;;;EACHC;EACAC,UAAyB;EACzBC,WAAmC,CAAC;EACpCC,WAAoC,CAAC;;EAG7CC,IAAIC,GAAiB;AACnB,SAAKL,OAAOK;AACZ,WAAO;EACT;;EAGAC,QAAQC,KAAoC;AAC1C,SAAKJ,WAAWI;AAChB,WAAO;EACT;;EAGAC,OAAOC,KAAaC,OAAqB;AACvC,SAAKR,SAASO,GAAAA,IAAOC;AACrB,WAAO;EACT;;EAGAC,QAAQJ,KAAmC;AACzC,SAAKL,WAAW;MAAE,GAAG,KAAKA;MAAU,GAAGK;IAAI;AAC3C,WAAO;EACT;;EAGAK,OAAOC,GAAwB;AAC7B,SAAKZ,UAAUY;AACf,WAAO;EACT;EAEA,IAAIC,WAA+B;AACjC,WAAO,KAAKd;EACd;EAEA,IAAIe,cAA6B;AAC/B,WAAO,KAAKd;EACd;EAEA,IAAIe,eAAuC;AACzC,WAAO,KAAKd;EACd;EAEA,IAAIe,eAAwC;AAC1C,WAAO,KAAKd;EACd;;EAGAe,YAA4B;AAC1B,WAAO;MACLd,KAAK,KAAKJ;MACVY,QAAQ,KAAKX;MACbU,SAAS;QAAE,GAAG,KAAKT;MAAS;MAC5BiB,MAAM,KAAKhB;IACb;EACF;AACF;;;ACpFA,SAASiB,kBAAkB;AAC3B,SAIEC,2BAGAC,eACAC,YACAC,gBACK;AACP,SAASC,QAAQC,YAAYC,gBAAgB;;;ACXtC,IAAMC,kBAAkBC,uBAAO,iBAAA;AAG/B,IAAMC,2BAA2BD,uBAAO,0BAAA;;;;;;;;;;;;;;;;;;;;ADa/C,IAAME,2BAA2B;AAG1B,IAAMC,UAAUC,cAAc,SAAA;AAoC9B,IAAMC,iBAAN,MAAMA;SAAAA;;;;;EACFC,UAAU;EAEnB,YAEmBC,SAGAC,gBACjB;SAJiBD,UAAAA;SAGAC,iBAAAA;EAChB;EAEH,MAAMC,KACJC,YACAC,cACAC,SACe;AACf,UAAML,UACJK,SAASC,UAAU,KAAKL,iBAAiB,KAAKA,eAAeI,QAAQC,MAAM,IAAI,KAAKN;AAEtF,UAAMO,UAAUC,WAAWJ,cAAc,WAAW,WAAA;AACpD,QAAI,CAACG,SAAS;AACZ,YAAME,OACHL,aAAa,YAA8CM,oBAC5DN,aAAa,YAAYK;AAC3B,YAAM,IAAIE,0BAA0B,WAAW,eAAeF,IAAAA;IAChE;AAEA,UAAMG,SAASL,QAAQ;MACrBJ;MACAU,cAAcR,SAASQ;MACvBP,QAAQD,SAASC;IACnB,CAAA;AACA,UAAMQ,UACJF,kBAAkBG,iBAAiBH,SAAS,IAAIG,eAAAA,EAAiBC,QAAQJ,MAAAA;AAC3E,UAAMK,UAAUH,QAAQI,UAAS;AAEjC,UAAMC,QAAQC,SAASjB,YAAY,WAAWC,YAAAA;AAC9C,UAAMiB,MAAMJ,QAAQI,QAAQ,OAAOF,UAAU,WAAWA,QAAQG,WAActB,QAAQqB;AAEtF,QAAI,CAACA,KAAK;AACR,YAAM,IAAIE,MACR,6JACE;IAEN;AAEA,UAAM,KAAKC,KAAKxB,SAASqB,KAAKJ,QAAQQ,QAAQR,QAAQS,MAAMT,QAAQU,OAAO;EAC7E;EAEA,MAAcH,KACZxB,SACAqB,KACAI,QACAC,MACAE,gBACe;AACf,UAAMZ,UAAUa,KAAKC,UAAUJ,IAAAA;AAC/B,UAAMC,UAAkC;MACtC,GAAG3B,QAAQ2B;MACX,GAAGC;MACH,gBAAgB;IAClB;AAEA,QAAI5B,QAAQ+B,QAAQ;AAClB,YAAMC,YAAYC,WAAW,UAAUjC,QAAQ+B,MAAM,EAAEG,OAAOlB,OAAAA,EAASmB,OAAO,KAAA;AAC9ER,cAAQ3B,QAAQoC,mBAAmBzC,wBAAAA,IAA4B,UAAUqC,SAAAA;IAC3E;AAEA,UAAMK,WAAW,MAAMC,MAAMjB,KAAK;MAChCI;MACAE;MACAD,MAAMV;IACR,CAAA;AAEA,QAAI,CAACqB,SAASE,IAAI;AAChB,YAAM,IAAIhB,MAAM,sBAAsBF,GAAAA,uBAA0BgB,SAASG,MAAM,GAAG;IACpF;EACF;AACF;;;;;;;;;;;;;;AEtIA,SAA6BC,cAA6B;;;;;;;;AA8BnD,IAAMC,uBAAN,MAAMA,sBAAAA;SAAAA;;;EACX,OAAOC,QAAQC,UAAuC,CAAC,GAAkB;AACvE,UAAMC,iBAAwC;;;MAG5C,GAAID,QAAQE,QAAQC,SAAY;QAAED,KAAKF,QAAQE;MAAI,IAAI,CAAC;MACxD,GAAIF,QAAQI,YAAYD,SAAY;QAAEC,SAASJ,QAAQI;MAAQ,IAAI,CAAC;IACtE;AAEA,UAAMC,YAAwB;MAC5B;QAAEC,SAASC;QAAiBC,UAAUP;MAAe;MACrD;QAAEK,SAASG;QAA0BD,UAAUR,QAAQU,kBAAkB;MAAK;MAC9EC;;AAGF,WAAO;MACLC,QAAQd;MACRe,QAAQb,QAAQa,UAAU;MAC1BR;MACAS,SAAS;QAACH;;IACZ;EACF;AACF;;;;","names":["WebhookMessage","_url","_method","_headers","_payload","url","u","payload","obj","header","key","value","headers","method","m","urlValue","methodValue","headerValues","payloadValue","toRequest","body","createHmac","MissingChannelMethodError","createChannel","getHandler","routeFor","Inject","Injectable","Optional","WEBHOOK_OPTIONS","Symbol","WEBHOOK_OPTIONS_RESOLVER","DEFAULT_SIGNATURE_HEADER","Webhook","createChannel","WebhookChannel","channel","options","resolveOptions","send","notifiable","notification","context","tenant","handler","getHandler","name","notificationName","MissingChannelMethodError","result","localization","message","WebhookMessage","payload","request","toRequest","route","routeFor","url","undefined","Error","post","method","body","headers","messageHeaders","JSON","stringify","secret","signature","createHmac","update","digest","signatureHeader","response","fetch","ok","status","Module","WebhookChannelModule","forRoot","options","webhookOptions","url","undefined","headers","providers","provide","WEBHOOK_OPTIONS","useValue","WEBHOOK_OPTIONS_RESOLVER","resolveOptions","WebhookChannel","module","global","exports"]}
|
|
1
|
+
{"version":3,"sources":["../src/webhook-message.ts","../src/webhook.channel.ts","../src/tokens.ts","../src/webhook.module.ts"],"sourcesContent":["/** The HTTP method used for a webhook request. */\nexport type WebhookMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'GET';\n\n/** The resolved request description produced by {@link WebhookMessage.toRequest}. */\nexport interface WebhookRequest {\n /** Target URL, when set on the message; otherwise resolved by the channel. */\n url?: string | undefined;\n method: WebhookMethod;\n headers: Record<string, string>;\n /** The JSON body to send (a plain object). */\n body: Record<string, unknown>;\n}\n\n/**\n * A fluent builder for a webhook request.\n *\n * ```ts\n * new WebhookMessage()\n * .url('https://example.com/hooks/orders')\n * .header('X-Signature', sign(payload))\n * .payload({ event: 'order.paid', id: 42 });\n * ```\n */\nexport class WebhookMessage {\n private _url?: string;\n private _method: WebhookMethod = 'POST';\n private _headers: Record<string, string> = {};\n private _payload: Record<string, unknown> = {};\n\n /** Set the target URL (overrides the route and configured default). */\n url(u: string): this {\n this._url = u;\n return this;\n }\n\n /** Set the JSON body to send. */\n payload(obj: Record<string, unknown>): this {\n this._payload = obj;\n return this;\n }\n\n /** Set a single request header. */\n header(key: string, value: string): this {\n this._headers[key] = value;\n return this;\n }\n\n /** Merge multiple request headers. */\n headers(obj: Record<string, string>): this {\n this._headers = { ...this._headers, ...obj };\n return this;\n }\n\n /** Set the HTTP method (default `POST`). */\n method(m: WebhookMethod): this {\n this._method = m;\n return this;\n }\n\n get urlValue(): string | undefined {\n return this._url;\n }\n\n get methodValue(): WebhookMethod {\n return this._method;\n }\n\n get headerValues(): Record<string, string> {\n return this._headers;\n }\n\n get payloadValue(): Record<string, unknown> {\n return this._payload;\n }\n\n /** Serialize to a {@link WebhookRequest}. */\n toRequest(): WebhookRequest {\n return {\n url: this._url,\n method: this._method,\n headers: { ...this._headers },\n body: this._payload,\n };\n }\n}\n","import { createHmac } from 'node:crypto';\nimport {\n BaseChannel,\n type ChannelContext,\n type DeliveryContext,\n type Notifiable,\n type Notification,\n createChannel,\n postJson,\n routeFor,\n} from '@dudousxd/nestjs-notifications-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport { WebhookMessage } from './webhook-message';\n\nconst DEFAULT_SIGNATURE_HEADER = 'X-Signature-256';\n\n/** Channel handle: use as `@Webhook()` on a payload method, or as a token in `via()`. */\nexport const Webhook = createChannel('webhook');\n\n/** Resolved runtime options for the webhook channel. */\nexport interface WebhookChannelOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * HMAC-SHA256 secret. When set, the request is signed: the header (default\n * `X-Signature-256`) is set to `sha256=<hex digest of the raw JSON body>`, so the receiver\n * can verify authenticity. Per-tenant secrets work via `resolveOptions`.\n */\n secret?: string;\n /** Header name for the signature. Default `X-Signature-256`. */\n signatureHeader?: string;\n}\n\n/**\n * Implement this on a notification to define its webhook payload. Returning a plain\n * object is treated as the JSON body to POST; return a {@link WebhookMessage} for full\n * control over the url, method and headers.\n */\nexport interface WebhookNotification extends Notification {\n toWebhook(ctx: ChannelContext): WebhookMessage | Record<string, unknown>;\n}\n\n/** Resolves per-tenant {@link WebhookChannelOptions} from a tenant id. */\nexport type WebhookOptionsResolver = (tenant: string) => WebhookChannelOptions;\n\n/**\n * Delivers a notification by sending an HTTP request (JSON body) to a webhook endpoint.\n * The target URL comes from the {@link WebhookMessage}, else from\n * `routeNotificationFor('webhook')` (a URL string), else from the configured default.\n */\n@Injectable()\nexport class WebhookChannel extends BaseChannel {\n readonly channel = 'webhook';\n\n constructor(\n @Inject(WEBHOOK_OPTIONS)\n private readonly options: WebhookChannelOptions,\n @Optional()\n @Inject(WEBHOOK_OPTIONS_RESOLVER)\n private readonly resolveOptions?: WebhookOptionsResolver,\n ) {\n super();\n }\n\n async send(\n notifiable: Notifiable,\n notification: Notification,\n context?: DeliveryContext,\n ): Promise<void> {\n const options = this.forTenant(this.options, context, this.resolveOptions);\n const result = this.buildPayload<WebhookMessage | Record<string, unknown>>(\n notification,\n notifiable,\n 'toWebhook',\n context,\n );\n const message =\n result instanceof WebhookMessage ? result : new WebhookMessage().payload(result);\n const request = message.toRequest();\n\n const route = routeFor(notifiable, 'webhook', notification);\n const url = request.url ?? (typeof route === 'string' ? route : undefined) ?? options.url;\n\n if (!url) {\n throw new Error(\n 'The webhook channel needs a target URL. Set one on the WebhookMessage via .url(), ' +\n 'return one from routeNotificationFor(\"webhook\"), or set url in forRoot().',\n );\n }\n\n const headers: Record<string, string> = { ...options.headers, ...request.headers };\n if (options.secret) {\n const signature = createHmac('sha256', options.secret)\n .update(JSON.stringify(request.body))\n .digest('hex');\n headers[options.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = `sha256=${signature}`;\n }\n\n await postJson(url, request.body, { label: 'Webhook', method: request.method, headers });\n }\n}\n","/** DI token for the resolved {@link WebhookChannelOptions} (default url, headers). */\nexport const WEBHOOK_OPTIONS = Symbol('WEBHOOK_OPTIONS');\n\n/** DI token for the optional per-tenant {@link WebhookChannelOptions} resolver. */\nexport const WEBHOOK_OPTIONS_RESOLVER = Symbol('WEBHOOK_OPTIONS_RESOLVER');\n","import { defineChannelModule } from '@dudousxd/nestjs-notifications-core';\nimport { type DynamicModule, Module } from '@nestjs/common';\nimport { WEBHOOK_OPTIONS, WEBHOOK_OPTIONS_RESOLVER } from './tokens';\nimport {\n WebhookChannel,\n type WebhookChannelOptions,\n type WebhookOptionsResolver,\n} from './webhook.channel';\n\nexport interface WebhookChannelModuleOptions {\n /** Default URL used when neither the message nor the route supplies one. */\n url?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /**\n * Optional per-tenant options resolver. When a notification is delivered with a\n * `context.tenant`, the returned options are used instead of the defaults.\n */\n resolveOptions?: WebhookOptionsResolver;\n /** Register globally so the channel is discoverable app-wide. Default true. */\n global?: boolean;\n}\n\n/**\n * Registers the webhook channel.\n *\n * ```ts\n * WebhookChannelModule.forRoot({ url: 'https://example.com/hooks/notifications' });\n * ```\n */\n@Module({})\nexport class WebhookChannelModule {\n static forRoot(options: WebhookChannelModuleOptions = {}): DynamicModule {\n const webhookOptions: WebhookChannelOptions = {\n // Set each field only when provided (exactOptionalPropertyTypes); the channel resolves a\n // per-notifiable URL and default headers when these are absent.\n ...(options.url !== undefined ? { url: options.url } : {}),\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n };\n\n return defineChannelModule({\n module: WebhookChannelModule,\n channel: WebhookChannel,\n optionsToken: WEBHOOK_OPTIONS,\n options: webhookOptions,\n resolver: { token: WEBHOOK_OPTIONS_RESOLVER, value: options.resolveOptions },\n ...(options.global !== undefined ? { global: options.global } : {}),\n });\n }\n}\n"],"mappings":"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","names":["WebhookMessage","_url","_method","_headers","_payload","url","u","payload","obj","header","key","value","headers","method","m","urlValue","methodValue","headerValues","payloadValue","toRequest","body","createHmac","BaseChannel","createChannel","postJson","routeFor","Inject","Injectable","Optional","WEBHOOK_OPTIONS","Symbol","WEBHOOK_OPTIONS_RESOLVER","DEFAULT_SIGNATURE_HEADER","Webhook","createChannel","WebhookChannel","BaseChannel","channel","options","resolveOptions","send","notifiable","notification","context","forTenant","result","buildPayload","message","WebhookMessage","payload","request","toRequest","route","routeFor","url","undefined","Error","headers","secret","signature","createHmac","update","JSON","stringify","body","digest","signatureHeader","postJson","label","method","defineChannelModule","Module","WebhookChannelModule","forRoot","options","webhookOptions","url","undefined","headers","defineChannelModule","module","channel","WebhookChannel","optionsToken","WEBHOOK_OPTIONS","resolver","token","WEBHOOK_OPTIONS_RESOLVER","value","resolveOptions","global"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-notifications-webhook",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Webhook channel for nestjs-notifications — deliver notifications by POSTing JSON to an HTTP endpoint",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Davide Carvalho",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
],
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"@dudousxd/nestjs-notifications-core": ">=0.1.0 <1.0.0",
|
|
20
|
-
"@nestjs/common": "^10.0.0 || ^11.0.0"
|
|
20
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0 || ^12.0.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@nestjs/common": "
|
|
23
|
+
"@nestjs/common": "12.0.1",
|
|
24
24
|
"reflect-metadata": "0.2.2",
|
|
25
25
|
"typescript": "5.9.3",
|
|
26
|
-
"@dudousxd/nestjs-notifications-core": "^0.
|
|
26
|
+
"@dudousxd/nestjs-notifications-core": "^0.9.1"
|
|
27
27
|
},
|
|
28
28
|
"module": "./dist/index.js",
|
|
29
29
|
"exports": {
|