@hostwebhook/node 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -5
- package/dist/index.js +48 -1
- package/dist/index.mjs +48 -1
- package/package.json +1 -1
- package/dist/index.d.mts +0 -316
- package/dist/index.d.ts +0 -316
package/README.md
CHANGED
|
@@ -92,19 +92,20 @@ Options: `verify(payload, headers, secret, { maxAgeSec: 300 })` — default 300s
|
|
|
92
92
|
|
|
93
93
|
Send webhook payloads through HostWebhook for reliable delivery with retries and monitoring.
|
|
94
94
|
|
|
95
|
-
###
|
|
95
|
+
### Fire & forget (default)
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
98
|
import { HostWebhook } from '@hostwebhook/node';
|
|
99
99
|
|
|
100
100
|
const hw = new HostWebhook({ token: 'your_ingress_token' });
|
|
101
101
|
|
|
102
|
+
// Returns immediately with the event ID — you don't know what happened in the pipeline
|
|
102
103
|
const { eventId } = await hw.send({ event: 'order.created', orderId: '123' });
|
|
103
104
|
```
|
|
104
105
|
|
|
105
|
-
### Wait for pipeline result (
|
|
106
|
+
### Wait for pipeline result (blocking)
|
|
106
107
|
|
|
107
|
-
Use `waitForResult` to wait for the full pipeline to complete. The SDK opens an SSE stream behind the scenes and returns the result with all pipeline steps.
|
|
108
|
+
Use `waitForResult` to wait for the full pipeline to complete. The SDK opens an SSE stream behind the scenes and returns the result with all pipeline steps. **This blocks until the pipeline finishes** (~120s max).
|
|
108
109
|
|
|
109
110
|
```ts
|
|
110
111
|
const result = await hw.send(
|
|
@@ -117,7 +118,34 @@ console.log(result.steps); // array of pipeline steps with nodeType, statu
|
|
|
117
118
|
console.log(result.response); // response body from target URL
|
|
118
119
|
```
|
|
119
120
|
|
|
120
|
-
|
|
121
|
+
### Non-blocking result (recommended for UIs)
|
|
122
|
+
|
|
123
|
+
Use `onResult` to get the pipeline result in a background callback. `send()` returns immediately so your UI never blocks. Perfect for forms and user-facing apps.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const { eventId } = await hw.send(
|
|
127
|
+
{ event: 'order.created', orderId: '123' },
|
|
128
|
+
{
|
|
129
|
+
onResult: (result) => {
|
|
130
|
+
// Fires when the pipeline completes (via SSE in background)
|
|
131
|
+
if (result.awaitingApproval) {
|
|
132
|
+
showToast('Awaiting approval from ' + result.approvalNodeName);
|
|
133
|
+
} else if (result.syncStatus === 200) {
|
|
134
|
+
showToast('Delivered successfully');
|
|
135
|
+
} else {
|
|
136
|
+
showToast('Pipeline failed: ' + result.error);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
onStep: (step) => {
|
|
140
|
+
// Optional: fires for each pipeline node as it executes
|
|
141
|
+
updateProgress(step.nodeName, step.status);
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
// UI shows "Sent!" immediately here — never blocks
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
> **Important:** `onResult` requires the endpoint to be in **None** response mode (async). In Sync mode, the server holds the HTTP connection open until the pipeline completes, which blocks `send()` regardless of callbacks. See [Choosing the right mode](#choosing-the-right-mode) below.
|
|
121
149
|
|
|
122
150
|
### Deduplication detection
|
|
123
151
|
|
|
@@ -151,6 +179,32 @@ const { eventId } = await send(
|
|
|
151
179
|
);
|
|
152
180
|
```
|
|
153
181
|
|
|
182
|
+
## Choosing the right mode
|
|
183
|
+
|
|
184
|
+
Your endpoint has a **Response Mode** setting (None or Sync) that affects how `send()` behaves:
|
|
185
|
+
|
|
186
|
+
| Scenario | Endpoint mode | SDK option | Behavior |
|
|
187
|
+
|----------|--------------|------------|----------|
|
|
188
|
+
| **Forms / UIs** | None | `onResult` | `send()` returns instantly. Pipeline result arrives in background callback. **UI never blocks.** |
|
|
189
|
+
| **Backend scripts** | None | `waitForResult` | `send()` blocks until pipeline completes via SSE (~120s max). |
|
|
190
|
+
| **API proxy / Stripe** | Sync | *(none)* | `send()` blocks until pipeline completes via HTTP (~120s max). Result is inline in the response. |
|
|
191
|
+
| **Testing (Postman)** | Sync | *(none)* | Single request, response includes full pipeline result. |
|
|
192
|
+
|
|
193
|
+
> **Warning: Never use Sync mode for user-facing forms or UIs.** Sync mode holds the HTTP connection open on the server, which blocks `send()` and freezes the UI until the pipeline completes. If the pipeline has approval nodes, merge nodes, or long delays, the SDK will timeout. Use **None** mode with `onResult` instead — the user sees "Sent!" immediately and the pipeline result arrives in the background.
|
|
194
|
+
|
|
195
|
+
### When to use Sync mode
|
|
196
|
+
|
|
197
|
+
- The caller is a **server or script**, not a human looking at a UI
|
|
198
|
+
- The caller **needs the pipeline result in the same HTTP request** (e.g., Stripe expects a specific response body)
|
|
199
|
+
- The pipeline is **fast and linear** (filter -> transform -> action) with no human-gated nodes (approval, merge)
|
|
200
|
+
|
|
201
|
+
### When to use None mode + onResult
|
|
202
|
+
|
|
203
|
+
- The caller is a **form, UI, or frontend app**
|
|
204
|
+
- You want **instant feedback** ("Sent!") without waiting for the pipeline
|
|
205
|
+
- The pipeline has **approval nodes, merge nodes, or delays**
|
|
206
|
+
- You want **real-time progress** via `onStep` callbacks
|
|
207
|
+
|
|
154
208
|
## Configuration
|
|
155
209
|
|
|
156
210
|
| Option | Type | Default | Description |
|
|
@@ -169,7 +223,9 @@ const { eventId } = await send(
|
|
|
169
223
|
| `headers` | `Record<string, string>` | — | Per-request headers |
|
|
170
224
|
| `contentType` | `string` | `application/json` | Override content type |
|
|
171
225
|
| `rawBody` | `string \| Buffer` | — | Send raw body instead of JSON |
|
|
172
|
-
| `waitForResult` | `boolean` | `false` | Wait for pipeline result via SSE stream |
|
|
226
|
+
| `waitForResult` | `boolean` | `false` | Wait for pipeline result via SSE stream (blocking) |
|
|
227
|
+
| `onResult` | `(result) => void` | — | Non-blocking pipeline result callback via SSE |
|
|
228
|
+
| `onStep` | `(step) => void` | — | Real-time pipeline step callback (with `onResult` or `waitForResult`) |
|
|
173
229
|
|
|
174
230
|
## Error Handling
|
|
175
231
|
|
package/dist/index.js
CHANGED
|
@@ -253,7 +253,7 @@ var HostWebhook = class {
|
|
|
253
253
|
}
|
|
254
254
|
const headers = {
|
|
255
255
|
"Content-Type": options?.contentType ?? "application/json",
|
|
256
|
-
"User-Agent": `HostWebhook-SDK/${"1.
|
|
256
|
+
"User-Agent": `HostWebhook-SDK/${"1.3.0"}`,
|
|
257
257
|
"X-HostWebhook-Sent-At": (/* @__PURE__ */ new Date()).toISOString(),
|
|
258
258
|
...tz ? { "X-HostWebhook-Timezone": tz } : {},
|
|
259
259
|
...__privateGet(this, _defaultHeaders),
|
|
@@ -331,6 +331,53 @@ var HostWebhook = class {
|
|
|
331
331
|
async sendBatch(payloads, options) {
|
|
332
332
|
return Promise.all(payloads.map((p) => this.send(p, options)));
|
|
333
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* Send a webhook with file attachments.
|
|
336
|
+
*
|
|
337
|
+
* Files are uploaded directly to storage via presigned URLs (zero memory on API),
|
|
338
|
+
* then file references are injected into the payload before sending.
|
|
339
|
+
*
|
|
340
|
+
* @param payload - The webhook payload
|
|
341
|
+
* @param files - Map of field name → file (Buffer or Blob with metadata)
|
|
342
|
+
* @param options - Optional per-request configuration
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```ts
|
|
346
|
+
* const hw = new HostWebhook({ token: 'your_token' });
|
|
347
|
+
* await hw.sendWithFiles(
|
|
348
|
+
* { orderId: '123', type: 'invoice' },
|
|
349
|
+
* { invoice: { data: pdfBuffer, fileName: 'inv.pdf', mimeType: 'application/pdf' } },
|
|
350
|
+
* );
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
async sendWithFiles(payload, files, options) {
|
|
354
|
+
const enrichedPayload = { ...payload };
|
|
355
|
+
for (const [fieldName, file] of Object.entries(files)) {
|
|
356
|
+
const uploadRes = await fetch(`${__privateGet(this, _baseUrl)}/api/files/upload-url`, {
|
|
357
|
+
method: "POST",
|
|
358
|
+
headers: {
|
|
359
|
+
"Content-Type": "application/json",
|
|
360
|
+
"Authorization": `Bearer ${__privateGet(this, _token)}`
|
|
361
|
+
},
|
|
362
|
+
body: JSON.stringify({ fileName: file.fileName, mimeType: file.mimeType })
|
|
363
|
+
});
|
|
364
|
+
if (!uploadRes.ok) throw new SendError(`Failed to get upload URL for ${fieldName}`, uploadRes.status, await uploadRes.text());
|
|
365
|
+
const { fileId, uploadUrl, key } = await uploadRes.json();
|
|
366
|
+
const uploadBody = file.data instanceof Blob ? file.data : new Blob([new Uint8Array(file.data)], { type: file.mimeType });
|
|
367
|
+
const putRes = await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": file.mimeType }, body: uploadBody });
|
|
368
|
+
if (!putRes.ok) throw new SendError(`Failed to upload ${fieldName} to storage`, putRes.status, await putRes.text());
|
|
369
|
+
const confirmRes = await fetch(`${__privateGet(this, _baseUrl)}/api/files/${fileId}/confirm`, {
|
|
370
|
+
method: "POST",
|
|
371
|
+
headers: { "Authorization": `Bearer ${__privateGet(this, _token)}` }
|
|
372
|
+
});
|
|
373
|
+
if (!confirmRes.ok) throw new SendError(`Failed to confirm upload for ${fieldName}`, confirmRes.status, await confirmRes.text());
|
|
374
|
+
const confirmed = await confirmRes.json();
|
|
375
|
+
enrichedPayload[fieldName] = {
|
|
376
|
+
_file: { id: confirmed.id, key, originalName: confirmed.originalName, mimeType: confirmed.mimeType, size: confirmed.size }
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
return this.send(enrichedPayload, options);
|
|
380
|
+
}
|
|
334
381
|
};
|
|
335
382
|
_token = new WeakMap();
|
|
336
383
|
_baseUrl = new WeakMap();
|
package/dist/index.mjs
CHANGED
|
@@ -220,7 +220,7 @@ var HostWebhook = class {
|
|
|
220
220
|
}
|
|
221
221
|
const headers = {
|
|
222
222
|
"Content-Type": options?.contentType ?? "application/json",
|
|
223
|
-
"User-Agent": `HostWebhook-SDK/${"1.
|
|
223
|
+
"User-Agent": `HostWebhook-SDK/${"1.3.0"}`,
|
|
224
224
|
"X-HostWebhook-Sent-At": (/* @__PURE__ */ new Date()).toISOString(),
|
|
225
225
|
...tz ? { "X-HostWebhook-Timezone": tz } : {},
|
|
226
226
|
...__privateGet(this, _defaultHeaders),
|
|
@@ -298,6 +298,53 @@ var HostWebhook = class {
|
|
|
298
298
|
async sendBatch(payloads, options) {
|
|
299
299
|
return Promise.all(payloads.map((p) => this.send(p, options)));
|
|
300
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Send a webhook with file attachments.
|
|
303
|
+
*
|
|
304
|
+
* Files are uploaded directly to storage via presigned URLs (zero memory on API),
|
|
305
|
+
* then file references are injected into the payload before sending.
|
|
306
|
+
*
|
|
307
|
+
* @param payload - The webhook payload
|
|
308
|
+
* @param files - Map of field name → file (Buffer or Blob with metadata)
|
|
309
|
+
* @param options - Optional per-request configuration
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const hw = new HostWebhook({ token: 'your_token' });
|
|
314
|
+
* await hw.sendWithFiles(
|
|
315
|
+
* { orderId: '123', type: 'invoice' },
|
|
316
|
+
* { invoice: { data: pdfBuffer, fileName: 'inv.pdf', mimeType: 'application/pdf' } },
|
|
317
|
+
* );
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
async sendWithFiles(payload, files, options) {
|
|
321
|
+
const enrichedPayload = { ...payload };
|
|
322
|
+
for (const [fieldName, file] of Object.entries(files)) {
|
|
323
|
+
const uploadRes = await fetch(`${__privateGet(this, _baseUrl)}/api/files/upload-url`, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
"Content-Type": "application/json",
|
|
327
|
+
"Authorization": `Bearer ${__privateGet(this, _token)}`
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify({ fileName: file.fileName, mimeType: file.mimeType })
|
|
330
|
+
});
|
|
331
|
+
if (!uploadRes.ok) throw new SendError(`Failed to get upload URL for ${fieldName}`, uploadRes.status, await uploadRes.text());
|
|
332
|
+
const { fileId, uploadUrl, key } = await uploadRes.json();
|
|
333
|
+
const uploadBody = file.data instanceof Blob ? file.data : new Blob([new Uint8Array(file.data)], { type: file.mimeType });
|
|
334
|
+
const putRes = await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": file.mimeType }, body: uploadBody });
|
|
335
|
+
if (!putRes.ok) throw new SendError(`Failed to upload ${fieldName} to storage`, putRes.status, await putRes.text());
|
|
336
|
+
const confirmRes = await fetch(`${__privateGet(this, _baseUrl)}/api/files/${fileId}/confirm`, {
|
|
337
|
+
method: "POST",
|
|
338
|
+
headers: { "Authorization": `Bearer ${__privateGet(this, _token)}` }
|
|
339
|
+
});
|
|
340
|
+
if (!confirmRes.ok) throw new SendError(`Failed to confirm upload for ${fieldName}`, confirmRes.status, await confirmRes.text());
|
|
341
|
+
const confirmed = await confirmRes.json();
|
|
342
|
+
enrichedPayload[fieldName] = {
|
|
343
|
+
_file: { id: confirmed.id, key, originalName: confirmed.originalName, mimeType: confirmed.mimeType, size: confirmed.size }
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
return this.send(enrichedPayload, options);
|
|
347
|
+
}
|
|
301
348
|
};
|
|
302
349
|
_token = new WeakMap();
|
|
303
350
|
_baseUrl = new WeakMap();
|
package/package.json
CHANGED
package/dist/index.d.mts
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Thrown when signature verification fails.
|
|
3
|
-
*/
|
|
4
|
-
declare class VerificationError extends Error {
|
|
5
|
-
constructor(message: string);
|
|
6
|
-
}
|
|
7
|
-
interface VerifyOptions {
|
|
8
|
-
/** Max allowed age of the signature timestamp in seconds. Default: 300 (5 min). Set 0 to disable. */
|
|
9
|
-
maxAgeSec?: number;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Verify a HostWebhook signature.
|
|
13
|
-
*
|
|
14
|
-
* Matches the format produced by HostWebhook's delivery processor:
|
|
15
|
-
* `X-HostWebhook-Signature: t=<timestamp_ms>,v1=<hmac_hex>`
|
|
16
|
-
*
|
|
17
|
-
* The HMAC is computed as: HMAC-SHA256(secret, `${timestamp}.${rawBody}`)
|
|
18
|
-
*
|
|
19
|
-
* @param payload - The raw request body (string or Buffer)
|
|
20
|
-
* @param headers - The request headers object
|
|
21
|
-
* @param secret - Your signing secret (e.g. `whsec_...`)
|
|
22
|
-
* @param options - Optional configuration
|
|
23
|
-
* @throws {VerificationError} If the signature is missing, malformed, expired, or invalid
|
|
24
|
-
*/
|
|
25
|
-
declare function verify(payload: string | Buffer, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyOptions): void;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Typed representation of HostWebhook delivery headers.
|
|
29
|
-
*/
|
|
30
|
-
interface WebhookHeaders {
|
|
31
|
-
/** Unique event ID (`X-HostWebhook-Event-Id`) */
|
|
32
|
-
eventId: string;
|
|
33
|
-
/** Delivery attempt number (`X-HostWebhook-Attempt`) */
|
|
34
|
-
attempt: number;
|
|
35
|
-
/** Signature timestamp in milliseconds */
|
|
36
|
-
timestamp: number;
|
|
37
|
-
/** Raw HMAC-SHA256 hex signature */
|
|
38
|
-
signature: string;
|
|
39
|
-
/** Chain step number, if this is a chained delivery */
|
|
40
|
-
chainStep?: number;
|
|
41
|
-
/** Original chain payload (base64-decoded JSON) */
|
|
42
|
-
chainOriginal?: unknown;
|
|
43
|
-
/** Previous chain step response (base64-decoded JSON) */
|
|
44
|
-
chainPrevious?: unknown;
|
|
45
|
-
/** Chain response metadata (base64-decoded JSON) */
|
|
46
|
-
chainResponse?: {
|
|
47
|
-
status: number;
|
|
48
|
-
body: unknown;
|
|
49
|
-
[key: string]: unknown;
|
|
50
|
-
};
|
|
51
|
-
/** Whether the chain response was truncated */
|
|
52
|
-
chainResponseTruncated?: boolean;
|
|
53
|
-
/** Original size of the chain response before truncation */
|
|
54
|
-
chainResponseOriginalSize?: number;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Parse all `X-HostWebhook-*` headers into a typed object.
|
|
58
|
-
*
|
|
59
|
-
* @param headers - The raw request headers
|
|
60
|
-
* @returns Parsed webhook headers
|
|
61
|
-
*/
|
|
62
|
-
declare function parseHeaders(headers: Record<string, string | string[] | undefined>): WebhookHeaders;
|
|
63
|
-
|
|
64
|
-
type NextFn = (err?: unknown) => void;
|
|
65
|
-
interface ExpressRequest {
|
|
66
|
-
body: string | Buffer;
|
|
67
|
-
headers: Record<string, string | string[] | undefined>;
|
|
68
|
-
}
|
|
69
|
-
interface ExpressResponse {
|
|
70
|
-
status(code: number): ExpressResponse;
|
|
71
|
-
json(body: unknown): void;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Express middleware that verifies HostWebhook signatures.
|
|
75
|
-
*
|
|
76
|
-
* IMPORTANT: You must use `express.raw({ type: 'application/json' })` before
|
|
77
|
-
* this middleware so that `req.body` is a Buffer (not parsed JSON).
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```ts
|
|
81
|
-
* import express from 'express';
|
|
82
|
-
* import { expressMiddleware } from '@hostwebhook/node';
|
|
83
|
-
*
|
|
84
|
-
* const app = express();
|
|
85
|
-
* app.post('/webhooks',
|
|
86
|
-
* express.raw({ type: 'application/json' }),
|
|
87
|
-
* expressMiddleware(process.env.SIGNING_SECRET!),
|
|
88
|
-
* (req, res) => {
|
|
89
|
-
* const payload = JSON.parse(req.body.toString());
|
|
90
|
-
* res.status(200).json({ received: true });
|
|
91
|
-
* },
|
|
92
|
-
* );
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
declare function expressMiddleware(secret: string, options?: VerifyOptions): (req: ExpressRequest, res: ExpressResponse, next: NextFn) => void;
|
|
96
|
-
/**
|
|
97
|
-
* NestJS guard factory. Returns a class that can be used with @UseGuards().
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```ts
|
|
101
|
-
* import { Controller, Post, UseGuards, Req } from '@nestjs/common';
|
|
102
|
-
* import { createNestGuard } from '@hostwebhook/node';
|
|
103
|
-
*
|
|
104
|
-
* const WebhookGuard = createNestGuard(process.env.SIGNING_SECRET!);
|
|
105
|
-
*
|
|
106
|
-
* @Controller('webhooks')
|
|
107
|
-
* export class WebhooksController {
|
|
108
|
-
* @Post()
|
|
109
|
-
* @UseGuards(WebhookGuard)
|
|
110
|
-
* handle(@Req() req: Request) {
|
|
111
|
-
* return { received: true };
|
|
112
|
-
* }
|
|
113
|
-
* }
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
declare function createNestGuard(secret: string, options?: VerifyOptions): {
|
|
117
|
-
new (): {
|
|
118
|
-
canActivate(context: {
|
|
119
|
-
switchToHttp(): {
|
|
120
|
-
getRequest(): ExpressRequest;
|
|
121
|
-
};
|
|
122
|
-
}): boolean;
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Fastify preHandler hook that verifies HostWebhook signatures.
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```ts
|
|
130
|
-
* import Fastify from 'fastify';
|
|
131
|
-
* import { fastifyHook } from '@hostwebhook/node';
|
|
132
|
-
*
|
|
133
|
-
* const app = Fastify({ bodyLimit: 1_048_576 });
|
|
134
|
-
* app.addContentTypeParser('application/json', { parseAs: 'buffer' }, (req, body, done) => done(null, body));
|
|
135
|
-
*
|
|
136
|
-
* app.post('/webhooks', { preHandler: fastifyHook(process.env.SIGNING_SECRET!) }, (req, reply) => {
|
|
137
|
-
* reply.send({ received: true });
|
|
138
|
-
* });
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
declare function fastifyHook(secret: string, options?: VerifyOptions): (req: ExpressRequest, reply: ExpressResponse, done: NextFn) => void;
|
|
142
|
-
|
|
143
|
-
/** Static secret signature — sends the secret as-is in a header (no HMAC). */
|
|
144
|
-
interface StaticSignature {
|
|
145
|
-
type: 'static';
|
|
146
|
-
/** The secret/token value to send. */
|
|
147
|
-
secret: string;
|
|
148
|
-
/**
|
|
149
|
-
* Header name to send the secret in.
|
|
150
|
-
* Default: `Authorization` with `Bearer <secret>` format.
|
|
151
|
-
* @example 'X-My-Custom-Key'
|
|
152
|
-
*/
|
|
153
|
-
header?: string;
|
|
154
|
-
}
|
|
155
|
-
/** Configuration for the HostWebhook client. */
|
|
156
|
-
interface HostWebhookConfig {
|
|
157
|
-
/** Ingress token from your endpoint settings. */
|
|
158
|
-
token: string;
|
|
159
|
-
/** Base URL of the HostWebhook API. Default: `https://api.hostwebhook.com` */
|
|
160
|
-
baseUrl?: string;
|
|
161
|
-
/**
|
|
162
|
-
* HMAC-SHA256 signing secret. When set, every request is signed with the
|
|
163
|
-
* HostWebhook signature format (`X-HostWebhook-Signature: t=<ts>,v1=<hmac>`).
|
|
164
|
-
* Pair with `incomingSignatureType: 'hostwebhook'` on the endpoint.
|
|
165
|
-
* @deprecated Prefer `signature` for new integrations.
|
|
166
|
-
*/
|
|
167
|
-
signingSecret?: string;
|
|
168
|
-
/**
|
|
169
|
-
* Signature configuration for incoming webhook verification.
|
|
170
|
-
* Cannot be used together with `signingSecret`.
|
|
171
|
-
*
|
|
172
|
-
* @example Static with default header (Authorization: Bearer)
|
|
173
|
-
* ```ts
|
|
174
|
-
* { type: 'static', secret: 'my-secret' }
|
|
175
|
-
* ```
|
|
176
|
-
* @example Static with custom header
|
|
177
|
-
* ```ts
|
|
178
|
-
* { type: 'static', secret: 'my-secret', header: 'X-My-Custom-Key' }
|
|
179
|
-
* ```
|
|
180
|
-
*/
|
|
181
|
-
signature?: StaticSignature;
|
|
182
|
-
/** Custom headers to include in every request. */
|
|
183
|
-
defaultHeaders?: Record<string, string>;
|
|
184
|
-
/** Request timeout in milliseconds. Default: 10000 (10s). */
|
|
185
|
-
timeoutMs?: number;
|
|
186
|
-
}
|
|
187
|
-
/** A single pipeline execution step received via SSE stream. */
|
|
188
|
-
interface PipelineStep {
|
|
189
|
-
eventId?: string;
|
|
190
|
-
nodeType: string;
|
|
191
|
-
nodeId: string;
|
|
192
|
-
nodeName?: string;
|
|
193
|
-
status: 'running' | 'success' | 'error' | 'blocked';
|
|
194
|
-
statusCode?: number;
|
|
195
|
-
durationMs?: number;
|
|
196
|
-
error?: string;
|
|
197
|
-
lastPayload?: Record<string, unknown>;
|
|
198
|
-
}
|
|
199
|
-
/** Options for a single send call. */
|
|
200
|
-
interface SendOptions {
|
|
201
|
-
/** Custom headers for this specific request (merged with defaultHeaders). */
|
|
202
|
-
headers?: Record<string, string>;
|
|
203
|
-
/** Override the Content-Type. Default: `application/json`. */
|
|
204
|
-
contentType?: string;
|
|
205
|
-
/**
|
|
206
|
-
* Send raw string/Buffer body instead of JSON-stringifying a payload object.
|
|
207
|
-
* When set, the `payload` parameter to `send()` is ignored.
|
|
208
|
-
*/
|
|
209
|
-
rawBody?: string | Buffer;
|
|
210
|
-
/**
|
|
211
|
-
* Wait for the full pipeline result via SSE streaming (blocking).
|
|
212
|
-
* The SDK will POST the payload, then open an SSE stream to receive
|
|
213
|
-
* pipeline steps and the final result. Returns when the pipeline completes.
|
|
214
|
-
* Timeout: ~125s (slightly above the server's 120s SSE timeout).
|
|
215
|
-
*/
|
|
216
|
-
waitForResult?: boolean;
|
|
217
|
-
/**
|
|
218
|
-
* Non-blocking pipeline result callback. `send()` returns immediately with
|
|
219
|
-
* the eventId, and the callback fires in the background when the pipeline
|
|
220
|
-
* completes (via SSE stream). Perfect for UIs that shouldn't block.
|
|
221
|
-
*
|
|
222
|
-
* Requires the endpoint to be in `none` response mode (async).
|
|
223
|
-
*
|
|
224
|
-
* @example
|
|
225
|
-
* ```ts
|
|
226
|
-
* const { eventId } = await hw.send(payload, {
|
|
227
|
-
* onResult: (result) => console.log('Pipeline done:', result.syncStatus),
|
|
228
|
-
* });
|
|
229
|
-
* // UI shows "Sent!" immediately here
|
|
230
|
-
* ```
|
|
231
|
-
*/
|
|
232
|
-
onResult?: (result: SendResult) => void;
|
|
233
|
-
/**
|
|
234
|
-
* Called for each pipeline step during SSE streaming.
|
|
235
|
-
* Only fires when `onResult` or `waitForResult` is used.
|
|
236
|
-
*/
|
|
237
|
-
onStep?: (step: PipelineStep) => void;
|
|
238
|
-
}
|
|
239
|
-
/** Result returned after a successful send. */
|
|
240
|
-
interface SendResult {
|
|
241
|
-
/** The event ID assigned by HostWebhook. */
|
|
242
|
-
eventId: string;
|
|
243
|
-
/** Short-lived token for SSE stream auth (returned by ingress, used internally by waitForResult). */
|
|
244
|
-
streamToken?: string;
|
|
245
|
-
/** Sync/stream: pipeline result status (200=delivered, 422=validation failed, 502=delivery failed, 408=timeout) */
|
|
246
|
-
syncStatus?: number;
|
|
247
|
-
/** Sync/stream: delivery status ('delivered') */
|
|
248
|
-
deliveryStatus?: string;
|
|
249
|
-
/** Sync/stream: HTTP status code from the target URL */
|
|
250
|
-
statusCode?: number;
|
|
251
|
-
/** Sync/stream: response body from the target URL (truncated to 4KB) */
|
|
252
|
-
response?: string;
|
|
253
|
-
/** Sync/stream: delivery latency in ms */
|
|
254
|
-
latencyMs?: number;
|
|
255
|
-
/** Sync/stream: error message if pipeline/delivery failed */
|
|
256
|
-
error?: string;
|
|
257
|
-
/** Sync/stream: validation error messages (schema validator) */
|
|
258
|
-
message?: string[];
|
|
259
|
-
/** SSE stream: pipeline execution steps (only when waitForResult is used) */
|
|
260
|
-
steps?: PipelineStep[];
|
|
261
|
-
/** Any additional fields from the sync response */
|
|
262
|
-
[key: string]: unknown;
|
|
263
|
-
}
|
|
264
|
-
/** Thrown when the HostWebhook API returns a non-2xx response. */
|
|
265
|
-
declare class SendError extends Error {
|
|
266
|
-
readonly statusCode: number;
|
|
267
|
-
readonly responseBody: string;
|
|
268
|
-
constructor(message: string, statusCode: number, responseBody: string);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* HostWebhook client for sending webhooks through the platform.
|
|
273
|
-
*
|
|
274
|
-
* @example
|
|
275
|
-
* ```ts
|
|
276
|
-
* const hw = new HostWebhook({ token: 'your_ingress_token' });
|
|
277
|
-
* const { eventId } = await hw.send({ event: 'order.created', orderId: '123' });
|
|
278
|
-
* ```
|
|
279
|
-
*/
|
|
280
|
-
declare class HostWebhook {
|
|
281
|
-
#private;
|
|
282
|
-
constructor(config: HostWebhookConfig);
|
|
283
|
-
/**
|
|
284
|
-
* Send a webhook payload through HostWebhook.
|
|
285
|
-
*
|
|
286
|
-
* The payload is JSON-stringified and POST'd to the ingress endpoint.
|
|
287
|
-
* HostWebhook then handles delivery to the target URL with retries,
|
|
288
|
-
* monitoring, transforms, and signing.
|
|
289
|
-
*
|
|
290
|
-
* @param payload - The webhook payload (will be JSON.stringify'd)
|
|
291
|
-
* @param options - Optional per-request configuration
|
|
292
|
-
* @returns The event ID assigned by HostWebhook
|
|
293
|
-
* @throws {SendError} If the API returns a non-2xx status
|
|
294
|
-
*/
|
|
295
|
-
send(payload: Record<string, unknown>, options?: SendOptions): Promise<SendResult>;
|
|
296
|
-
/**
|
|
297
|
-
* Convenience: send multiple payloads in parallel.
|
|
298
|
-
*
|
|
299
|
-
* @param payloads - Array of payloads to send
|
|
300
|
-
* @param options - Optional per-request configuration (shared for all)
|
|
301
|
-
* @returns Array of results (in same order as payloads)
|
|
302
|
-
*/
|
|
303
|
-
sendBatch(payloads: Record<string, unknown>[], options?: SendOptions): Promise<SendResult[]>;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Standalone send function (no class instantiation needed).
|
|
307
|
-
*
|
|
308
|
-
* @example
|
|
309
|
-
* ```ts
|
|
310
|
-
* import { send } from '@hostwebhook/node';
|
|
311
|
-
* await send({ token: 'your_token' }, { event: 'test' });
|
|
312
|
-
* ```
|
|
313
|
-
*/
|
|
314
|
-
declare function send(config: HostWebhookConfig, payload: Record<string, unknown>, options?: SendOptions): Promise<SendResult>;
|
|
315
|
-
|
|
316
|
-
export { HostWebhook, type HostWebhookConfig, type PipelineStep, SendError, type SendOptions, type SendResult, type StaticSignature, VerificationError, type VerifyOptions, type WebhookHeaders, createNestGuard, expressMiddleware, fastifyHook, parseHeaders, send, verify };
|
package/dist/index.d.ts
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Thrown when signature verification fails.
|
|
3
|
-
*/
|
|
4
|
-
declare class VerificationError extends Error {
|
|
5
|
-
constructor(message: string);
|
|
6
|
-
}
|
|
7
|
-
interface VerifyOptions {
|
|
8
|
-
/** Max allowed age of the signature timestamp in seconds. Default: 300 (5 min). Set 0 to disable. */
|
|
9
|
-
maxAgeSec?: number;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Verify a HostWebhook signature.
|
|
13
|
-
*
|
|
14
|
-
* Matches the format produced by HostWebhook's delivery processor:
|
|
15
|
-
* `X-HostWebhook-Signature: t=<timestamp_ms>,v1=<hmac_hex>`
|
|
16
|
-
*
|
|
17
|
-
* The HMAC is computed as: HMAC-SHA256(secret, `${timestamp}.${rawBody}`)
|
|
18
|
-
*
|
|
19
|
-
* @param payload - The raw request body (string or Buffer)
|
|
20
|
-
* @param headers - The request headers object
|
|
21
|
-
* @param secret - Your signing secret (e.g. `whsec_...`)
|
|
22
|
-
* @param options - Optional configuration
|
|
23
|
-
* @throws {VerificationError} If the signature is missing, malformed, expired, or invalid
|
|
24
|
-
*/
|
|
25
|
-
declare function verify(payload: string | Buffer, headers: Record<string, string | string[] | undefined>, secret: string, options?: VerifyOptions): void;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Typed representation of HostWebhook delivery headers.
|
|
29
|
-
*/
|
|
30
|
-
interface WebhookHeaders {
|
|
31
|
-
/** Unique event ID (`X-HostWebhook-Event-Id`) */
|
|
32
|
-
eventId: string;
|
|
33
|
-
/** Delivery attempt number (`X-HostWebhook-Attempt`) */
|
|
34
|
-
attempt: number;
|
|
35
|
-
/** Signature timestamp in milliseconds */
|
|
36
|
-
timestamp: number;
|
|
37
|
-
/** Raw HMAC-SHA256 hex signature */
|
|
38
|
-
signature: string;
|
|
39
|
-
/** Chain step number, if this is a chained delivery */
|
|
40
|
-
chainStep?: number;
|
|
41
|
-
/** Original chain payload (base64-decoded JSON) */
|
|
42
|
-
chainOriginal?: unknown;
|
|
43
|
-
/** Previous chain step response (base64-decoded JSON) */
|
|
44
|
-
chainPrevious?: unknown;
|
|
45
|
-
/** Chain response metadata (base64-decoded JSON) */
|
|
46
|
-
chainResponse?: {
|
|
47
|
-
status: number;
|
|
48
|
-
body: unknown;
|
|
49
|
-
[key: string]: unknown;
|
|
50
|
-
};
|
|
51
|
-
/** Whether the chain response was truncated */
|
|
52
|
-
chainResponseTruncated?: boolean;
|
|
53
|
-
/** Original size of the chain response before truncation */
|
|
54
|
-
chainResponseOriginalSize?: number;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Parse all `X-HostWebhook-*` headers into a typed object.
|
|
58
|
-
*
|
|
59
|
-
* @param headers - The raw request headers
|
|
60
|
-
* @returns Parsed webhook headers
|
|
61
|
-
*/
|
|
62
|
-
declare function parseHeaders(headers: Record<string, string | string[] | undefined>): WebhookHeaders;
|
|
63
|
-
|
|
64
|
-
type NextFn = (err?: unknown) => void;
|
|
65
|
-
interface ExpressRequest {
|
|
66
|
-
body: string | Buffer;
|
|
67
|
-
headers: Record<string, string | string[] | undefined>;
|
|
68
|
-
}
|
|
69
|
-
interface ExpressResponse {
|
|
70
|
-
status(code: number): ExpressResponse;
|
|
71
|
-
json(body: unknown): void;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Express middleware that verifies HostWebhook signatures.
|
|
75
|
-
*
|
|
76
|
-
* IMPORTANT: You must use `express.raw({ type: 'application/json' })` before
|
|
77
|
-
* this middleware so that `req.body` is a Buffer (not parsed JSON).
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```ts
|
|
81
|
-
* import express from 'express';
|
|
82
|
-
* import { expressMiddleware } from '@hostwebhook/node';
|
|
83
|
-
*
|
|
84
|
-
* const app = express();
|
|
85
|
-
* app.post('/webhooks',
|
|
86
|
-
* express.raw({ type: 'application/json' }),
|
|
87
|
-
* expressMiddleware(process.env.SIGNING_SECRET!),
|
|
88
|
-
* (req, res) => {
|
|
89
|
-
* const payload = JSON.parse(req.body.toString());
|
|
90
|
-
* res.status(200).json({ received: true });
|
|
91
|
-
* },
|
|
92
|
-
* );
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
declare function expressMiddleware(secret: string, options?: VerifyOptions): (req: ExpressRequest, res: ExpressResponse, next: NextFn) => void;
|
|
96
|
-
/**
|
|
97
|
-
* NestJS guard factory. Returns a class that can be used with @UseGuards().
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```ts
|
|
101
|
-
* import { Controller, Post, UseGuards, Req } from '@nestjs/common';
|
|
102
|
-
* import { createNestGuard } from '@hostwebhook/node';
|
|
103
|
-
*
|
|
104
|
-
* const WebhookGuard = createNestGuard(process.env.SIGNING_SECRET!);
|
|
105
|
-
*
|
|
106
|
-
* @Controller('webhooks')
|
|
107
|
-
* export class WebhooksController {
|
|
108
|
-
* @Post()
|
|
109
|
-
* @UseGuards(WebhookGuard)
|
|
110
|
-
* handle(@Req() req: Request) {
|
|
111
|
-
* return { received: true };
|
|
112
|
-
* }
|
|
113
|
-
* }
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
declare function createNestGuard(secret: string, options?: VerifyOptions): {
|
|
117
|
-
new (): {
|
|
118
|
-
canActivate(context: {
|
|
119
|
-
switchToHttp(): {
|
|
120
|
-
getRequest(): ExpressRequest;
|
|
121
|
-
};
|
|
122
|
-
}): boolean;
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Fastify preHandler hook that verifies HostWebhook signatures.
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```ts
|
|
130
|
-
* import Fastify from 'fastify';
|
|
131
|
-
* import { fastifyHook } from '@hostwebhook/node';
|
|
132
|
-
*
|
|
133
|
-
* const app = Fastify({ bodyLimit: 1_048_576 });
|
|
134
|
-
* app.addContentTypeParser('application/json', { parseAs: 'buffer' }, (req, body, done) => done(null, body));
|
|
135
|
-
*
|
|
136
|
-
* app.post('/webhooks', { preHandler: fastifyHook(process.env.SIGNING_SECRET!) }, (req, reply) => {
|
|
137
|
-
* reply.send({ received: true });
|
|
138
|
-
* });
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
declare function fastifyHook(secret: string, options?: VerifyOptions): (req: ExpressRequest, reply: ExpressResponse, done: NextFn) => void;
|
|
142
|
-
|
|
143
|
-
/** Static secret signature — sends the secret as-is in a header (no HMAC). */
|
|
144
|
-
interface StaticSignature {
|
|
145
|
-
type: 'static';
|
|
146
|
-
/** The secret/token value to send. */
|
|
147
|
-
secret: string;
|
|
148
|
-
/**
|
|
149
|
-
* Header name to send the secret in.
|
|
150
|
-
* Default: `Authorization` with `Bearer <secret>` format.
|
|
151
|
-
* @example 'X-My-Custom-Key'
|
|
152
|
-
*/
|
|
153
|
-
header?: string;
|
|
154
|
-
}
|
|
155
|
-
/** Configuration for the HostWebhook client. */
|
|
156
|
-
interface HostWebhookConfig {
|
|
157
|
-
/** Ingress token from your endpoint settings. */
|
|
158
|
-
token: string;
|
|
159
|
-
/** Base URL of the HostWebhook API. Default: `https://api.hostwebhook.com` */
|
|
160
|
-
baseUrl?: string;
|
|
161
|
-
/**
|
|
162
|
-
* HMAC-SHA256 signing secret. When set, every request is signed with the
|
|
163
|
-
* HostWebhook signature format (`X-HostWebhook-Signature: t=<ts>,v1=<hmac>`).
|
|
164
|
-
* Pair with `incomingSignatureType: 'hostwebhook'` on the endpoint.
|
|
165
|
-
* @deprecated Prefer `signature` for new integrations.
|
|
166
|
-
*/
|
|
167
|
-
signingSecret?: string;
|
|
168
|
-
/**
|
|
169
|
-
* Signature configuration for incoming webhook verification.
|
|
170
|
-
* Cannot be used together with `signingSecret`.
|
|
171
|
-
*
|
|
172
|
-
* @example Static with default header (Authorization: Bearer)
|
|
173
|
-
* ```ts
|
|
174
|
-
* { type: 'static', secret: 'my-secret' }
|
|
175
|
-
* ```
|
|
176
|
-
* @example Static with custom header
|
|
177
|
-
* ```ts
|
|
178
|
-
* { type: 'static', secret: 'my-secret', header: 'X-My-Custom-Key' }
|
|
179
|
-
* ```
|
|
180
|
-
*/
|
|
181
|
-
signature?: StaticSignature;
|
|
182
|
-
/** Custom headers to include in every request. */
|
|
183
|
-
defaultHeaders?: Record<string, string>;
|
|
184
|
-
/** Request timeout in milliseconds. Default: 10000 (10s). */
|
|
185
|
-
timeoutMs?: number;
|
|
186
|
-
}
|
|
187
|
-
/** A single pipeline execution step received via SSE stream. */
|
|
188
|
-
interface PipelineStep {
|
|
189
|
-
eventId?: string;
|
|
190
|
-
nodeType: string;
|
|
191
|
-
nodeId: string;
|
|
192
|
-
nodeName?: string;
|
|
193
|
-
status: 'running' | 'success' | 'error' | 'blocked';
|
|
194
|
-
statusCode?: number;
|
|
195
|
-
durationMs?: number;
|
|
196
|
-
error?: string;
|
|
197
|
-
lastPayload?: Record<string, unknown>;
|
|
198
|
-
}
|
|
199
|
-
/** Options for a single send call. */
|
|
200
|
-
interface SendOptions {
|
|
201
|
-
/** Custom headers for this specific request (merged with defaultHeaders). */
|
|
202
|
-
headers?: Record<string, string>;
|
|
203
|
-
/** Override the Content-Type. Default: `application/json`. */
|
|
204
|
-
contentType?: string;
|
|
205
|
-
/**
|
|
206
|
-
* Send raw string/Buffer body instead of JSON-stringifying a payload object.
|
|
207
|
-
* When set, the `payload` parameter to `send()` is ignored.
|
|
208
|
-
*/
|
|
209
|
-
rawBody?: string | Buffer;
|
|
210
|
-
/**
|
|
211
|
-
* Wait for the full pipeline result via SSE streaming (blocking).
|
|
212
|
-
* The SDK will POST the payload, then open an SSE stream to receive
|
|
213
|
-
* pipeline steps and the final result. Returns when the pipeline completes.
|
|
214
|
-
* Timeout: ~125s (slightly above the server's 120s SSE timeout).
|
|
215
|
-
*/
|
|
216
|
-
waitForResult?: boolean;
|
|
217
|
-
/**
|
|
218
|
-
* Non-blocking pipeline result callback. `send()` returns immediately with
|
|
219
|
-
* the eventId, and the callback fires in the background when the pipeline
|
|
220
|
-
* completes (via SSE stream). Perfect for UIs that shouldn't block.
|
|
221
|
-
*
|
|
222
|
-
* Requires the endpoint to be in `none` response mode (async).
|
|
223
|
-
*
|
|
224
|
-
* @example
|
|
225
|
-
* ```ts
|
|
226
|
-
* const { eventId } = await hw.send(payload, {
|
|
227
|
-
* onResult: (result) => console.log('Pipeline done:', result.syncStatus),
|
|
228
|
-
* });
|
|
229
|
-
* // UI shows "Sent!" immediately here
|
|
230
|
-
* ```
|
|
231
|
-
*/
|
|
232
|
-
onResult?: (result: SendResult) => void;
|
|
233
|
-
/**
|
|
234
|
-
* Called for each pipeline step during SSE streaming.
|
|
235
|
-
* Only fires when `onResult` or `waitForResult` is used.
|
|
236
|
-
*/
|
|
237
|
-
onStep?: (step: PipelineStep) => void;
|
|
238
|
-
}
|
|
239
|
-
/** Result returned after a successful send. */
|
|
240
|
-
interface SendResult {
|
|
241
|
-
/** The event ID assigned by HostWebhook. */
|
|
242
|
-
eventId: string;
|
|
243
|
-
/** Short-lived token for SSE stream auth (returned by ingress, used internally by waitForResult). */
|
|
244
|
-
streamToken?: string;
|
|
245
|
-
/** Sync/stream: pipeline result status (200=delivered, 422=validation failed, 502=delivery failed, 408=timeout) */
|
|
246
|
-
syncStatus?: number;
|
|
247
|
-
/** Sync/stream: delivery status ('delivered') */
|
|
248
|
-
deliveryStatus?: string;
|
|
249
|
-
/** Sync/stream: HTTP status code from the target URL */
|
|
250
|
-
statusCode?: number;
|
|
251
|
-
/** Sync/stream: response body from the target URL (truncated to 4KB) */
|
|
252
|
-
response?: string;
|
|
253
|
-
/** Sync/stream: delivery latency in ms */
|
|
254
|
-
latencyMs?: number;
|
|
255
|
-
/** Sync/stream: error message if pipeline/delivery failed */
|
|
256
|
-
error?: string;
|
|
257
|
-
/** Sync/stream: validation error messages (schema validator) */
|
|
258
|
-
message?: string[];
|
|
259
|
-
/** SSE stream: pipeline execution steps (only when waitForResult is used) */
|
|
260
|
-
steps?: PipelineStep[];
|
|
261
|
-
/** Any additional fields from the sync response */
|
|
262
|
-
[key: string]: unknown;
|
|
263
|
-
}
|
|
264
|
-
/** Thrown when the HostWebhook API returns a non-2xx response. */
|
|
265
|
-
declare class SendError extends Error {
|
|
266
|
-
readonly statusCode: number;
|
|
267
|
-
readonly responseBody: string;
|
|
268
|
-
constructor(message: string, statusCode: number, responseBody: string);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* HostWebhook client for sending webhooks through the platform.
|
|
273
|
-
*
|
|
274
|
-
* @example
|
|
275
|
-
* ```ts
|
|
276
|
-
* const hw = new HostWebhook({ token: 'your_ingress_token' });
|
|
277
|
-
* const { eventId } = await hw.send({ event: 'order.created', orderId: '123' });
|
|
278
|
-
* ```
|
|
279
|
-
*/
|
|
280
|
-
declare class HostWebhook {
|
|
281
|
-
#private;
|
|
282
|
-
constructor(config: HostWebhookConfig);
|
|
283
|
-
/**
|
|
284
|
-
* Send a webhook payload through HostWebhook.
|
|
285
|
-
*
|
|
286
|
-
* The payload is JSON-stringified and POST'd to the ingress endpoint.
|
|
287
|
-
* HostWebhook then handles delivery to the target URL with retries,
|
|
288
|
-
* monitoring, transforms, and signing.
|
|
289
|
-
*
|
|
290
|
-
* @param payload - The webhook payload (will be JSON.stringify'd)
|
|
291
|
-
* @param options - Optional per-request configuration
|
|
292
|
-
* @returns The event ID assigned by HostWebhook
|
|
293
|
-
* @throws {SendError} If the API returns a non-2xx status
|
|
294
|
-
*/
|
|
295
|
-
send(payload: Record<string, unknown>, options?: SendOptions): Promise<SendResult>;
|
|
296
|
-
/**
|
|
297
|
-
* Convenience: send multiple payloads in parallel.
|
|
298
|
-
*
|
|
299
|
-
* @param payloads - Array of payloads to send
|
|
300
|
-
* @param options - Optional per-request configuration (shared for all)
|
|
301
|
-
* @returns Array of results (in same order as payloads)
|
|
302
|
-
*/
|
|
303
|
-
sendBatch(payloads: Record<string, unknown>[], options?: SendOptions): Promise<SendResult[]>;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Standalone send function (no class instantiation needed).
|
|
307
|
-
*
|
|
308
|
-
* @example
|
|
309
|
-
* ```ts
|
|
310
|
-
* import { send } from '@hostwebhook/node';
|
|
311
|
-
* await send({ token: 'your_token' }, { event: 'test' });
|
|
312
|
-
* ```
|
|
313
|
-
*/
|
|
314
|
-
declare function send(config: HostWebhookConfig, payload: Record<string, unknown>, options?: SendOptions): Promise<SendResult>;
|
|
315
|
-
|
|
316
|
-
export { HostWebhook, type HostWebhookConfig, type PipelineStep, SendError, type SendOptions, type SendResult, type StaticSignature, VerificationError, type VerifyOptions, type WebhookHeaders, createNestGuard, expressMiddleware, fastifyHook, parseHeaders, send, verify };
|