@webhook-platform/node 1.0.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 +252 -0
- package/dist/__tests__/client.test.d.ts +1 -0
- package/dist/__tests__/client.test.js +79 -0
- package/dist/__tests__/webhooks.test.d.ts +1 -0
- package/dist/__tests__/webhooks.test.js +162 -0
- package/dist/client.d.ts +48 -0
- package/dist/client.js +229 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +46 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +29 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.js +3 -0
- package/dist/webhooks.d.ts +38 -0
- package/dist/webhooks.js +138 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# @webhook-platform/node
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for [Webhook Platform](https://github.com/vadymkykalo/webhook-platform).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @webhook-platform/node
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { WebhookPlatform } from '@webhook-platform/node';
|
|
15
|
+
|
|
16
|
+
const client = new WebhookPlatform({
|
|
17
|
+
apiKey: 'wh_live_your_api_key',
|
|
18
|
+
baseUrl: 'http://localhost:8080', // optional, defaults to localhost
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Send an event
|
|
22
|
+
const event = await client.events.send({
|
|
23
|
+
type: 'order.completed',
|
|
24
|
+
data: {
|
|
25
|
+
orderId: 'ord_12345',
|
|
26
|
+
amount: 99.99,
|
|
27
|
+
currency: 'USD',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
console.log(`Event created: ${event.eventId}`);
|
|
32
|
+
console.log(`Deliveries created: ${event.deliveriesCreated}`);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API Reference
|
|
36
|
+
|
|
37
|
+
### Events
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Send event with idempotency key
|
|
41
|
+
const event = await client.events.send(
|
|
42
|
+
{ type: 'order.completed', data: { orderId: '123' } },
|
|
43
|
+
'unique-idempotency-key'
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Endpoints
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Create endpoint
|
|
51
|
+
const endpoint = await client.endpoints.create(projectId, {
|
|
52
|
+
url: 'https://api.example.com/webhooks',
|
|
53
|
+
description: 'Production webhooks',
|
|
54
|
+
enabled: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// List endpoints
|
|
58
|
+
const endpoints = await client.endpoints.list(projectId);
|
|
59
|
+
|
|
60
|
+
// Update endpoint
|
|
61
|
+
await client.endpoints.update(projectId, endpointId, {
|
|
62
|
+
enabled: false,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Delete endpoint
|
|
66
|
+
await client.endpoints.delete(projectId, endpointId);
|
|
67
|
+
|
|
68
|
+
// Rotate secret
|
|
69
|
+
const updated = await client.endpoints.rotateSecret(projectId, endpointId);
|
|
70
|
+
console.log(`New secret: ${updated.secret}`);
|
|
71
|
+
|
|
72
|
+
// Test endpoint connectivity
|
|
73
|
+
const result = await client.endpoints.test(projectId, endpointId);
|
|
74
|
+
console.log(`Test ${result.success ? 'passed' : 'failed'}: ${result.latencyMs}ms`);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Subscriptions
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Subscribe endpoint to event types
|
|
81
|
+
const subscription = await client.subscriptions.create(projectId, {
|
|
82
|
+
endpointId: endpoint.id,
|
|
83
|
+
eventTypes: ['order.completed', 'order.cancelled'],
|
|
84
|
+
enabled: true,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// List subscriptions
|
|
88
|
+
const subscriptions = await client.subscriptions.list(projectId);
|
|
89
|
+
|
|
90
|
+
// Update subscription
|
|
91
|
+
await client.subscriptions.update(projectId, subscriptionId, {
|
|
92
|
+
eventTypes: ['order.*'],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Delete subscription
|
|
96
|
+
await client.subscriptions.delete(projectId, subscriptionId);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Deliveries
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// List deliveries with filters
|
|
103
|
+
const deliveries = await client.deliveries.list(projectId, {
|
|
104
|
+
status: 'FAILED',
|
|
105
|
+
page: 0,
|
|
106
|
+
size: 20,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
console.log(`Total failed: ${deliveries.totalElements}`);
|
|
110
|
+
|
|
111
|
+
// Get delivery attempts
|
|
112
|
+
const attempts = await client.deliveries.getAttempts(deliveryId);
|
|
113
|
+
for (const attempt of attempts) {
|
|
114
|
+
console.log(`Attempt ${attempt.attemptNumber}: ${attempt.httpStatus} (${attempt.latencyMs}ms)`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Replay failed delivery
|
|
118
|
+
await client.deliveries.replay(deliveryId);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Webhook Signature Verification
|
|
122
|
+
|
|
123
|
+
Verify incoming webhooks in your endpoint:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { verifySignature, constructEvent } from '@webhook-platform/node';
|
|
127
|
+
|
|
128
|
+
app.post('/webhooks', (req, res) => {
|
|
129
|
+
const payload = req.body; // raw body string
|
|
130
|
+
const signature = req.headers['x-signature'];
|
|
131
|
+
const secret = process.env.WEBHOOK_SECRET;
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
// Option 1: Just verify
|
|
135
|
+
verifySignature(payload, signature, secret);
|
|
136
|
+
|
|
137
|
+
// Option 2: Verify and parse
|
|
138
|
+
const event = constructEvent(payload, req.headers, secret);
|
|
139
|
+
|
|
140
|
+
console.log(`Received ${event.type}:`, event.data);
|
|
141
|
+
|
|
142
|
+
// Handle the event
|
|
143
|
+
switch (event.type) {
|
|
144
|
+
case 'order.completed':
|
|
145
|
+
handleOrderCompleted(event.data);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
res.status(200).send('OK');
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error('Webhook verification failed:', err.message);
|
|
152
|
+
res.status(400).send('Invalid signature');
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Express.js Example
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import express from 'express';
|
|
161
|
+
import { constructEvent } from '@webhook-platform/node';
|
|
162
|
+
|
|
163
|
+
const app = express();
|
|
164
|
+
|
|
165
|
+
// Important: Use raw body for signature verification
|
|
166
|
+
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
167
|
+
const event = constructEvent(
|
|
168
|
+
req.body.toString(),
|
|
169
|
+
req.headers,
|
|
170
|
+
process.env.WEBHOOK_SECRET
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Process event...
|
|
174
|
+
res.sendStatus(200);
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Error Handling
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import {
|
|
182
|
+
WebhookPlatformError,
|
|
183
|
+
RateLimitError,
|
|
184
|
+
AuthenticationError,
|
|
185
|
+
ValidationError
|
|
186
|
+
} from '@webhook-platform/node';
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
await client.events.send({ type: 'test', data: {} });
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (err instanceof RateLimitError) {
|
|
192
|
+
// Wait and retry
|
|
193
|
+
console.log(`Rate limited. Retry after ${err.retryAfter}ms`);
|
|
194
|
+
await sleep(err.retryAfter);
|
|
195
|
+
} else if (err instanceof AuthenticationError) {
|
|
196
|
+
console.error('Invalid API key');
|
|
197
|
+
} else if (err instanceof ValidationError) {
|
|
198
|
+
console.error('Validation failed:', err.fieldErrors);
|
|
199
|
+
} else if (err instanceof WebhookPlatformError) {
|
|
200
|
+
console.error(`Error ${err.status}: ${err.message}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Configuration
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const client = new WebhookPlatform({
|
|
209
|
+
apiKey: 'wh_live_xxx', // Required: Your API key
|
|
210
|
+
baseUrl: 'https://api.example.com', // Optional: API base URL
|
|
211
|
+
timeout: 30000, // Optional: Request timeout in ms (default: 30000)
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## TypeScript Support
|
|
216
|
+
|
|
217
|
+
This SDK is written in TypeScript and includes full type definitions:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import type {
|
|
221
|
+
Event,
|
|
222
|
+
EventResponse,
|
|
223
|
+
Endpoint,
|
|
224
|
+
Delivery,
|
|
225
|
+
DeliveryStatus
|
|
226
|
+
} from '@webhook-platform/node';
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Development
|
|
230
|
+
|
|
231
|
+
### Running Tests
|
|
232
|
+
|
|
233
|
+
**Local (requires Node.js 16+):**
|
|
234
|
+
```bash
|
|
235
|
+
npm install
|
|
236
|
+
npm test
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Docker:**
|
|
240
|
+
```bash
|
|
241
|
+
docker run --rm -v $(pwd):/app -w /app node:20-alpine sh -c "npm install && npm test"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Building
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
npm run build
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const client_1 = require("../client");
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
describe('WebhookPlatform Client', () => {
|
|
6
|
+
describe('constructor', () => {
|
|
7
|
+
it('should create client with API key', () => {
|
|
8
|
+
const client = new client_1.WebhookPlatform({ apiKey: 'test_api_key' });
|
|
9
|
+
expect(client).toBeInstanceOf(client_1.WebhookPlatform);
|
|
10
|
+
});
|
|
11
|
+
it('should throw error without API key', () => {
|
|
12
|
+
expect(() => new client_1.WebhookPlatform({ apiKey: '' })).toThrow('API key is required');
|
|
13
|
+
});
|
|
14
|
+
it('should use default base URL', () => {
|
|
15
|
+
const client = new client_1.WebhookPlatform({ apiKey: 'test_api_key' });
|
|
16
|
+
expect(client).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
it('should accept custom base URL', () => {
|
|
19
|
+
const client = new client_1.WebhookPlatform({
|
|
20
|
+
apiKey: 'test_api_key',
|
|
21
|
+
baseUrl: 'https://api.example.com',
|
|
22
|
+
});
|
|
23
|
+
expect(client).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
it('should accept custom timeout', () => {
|
|
26
|
+
const client = new client_1.WebhookPlatform({
|
|
27
|
+
apiKey: 'test_api_key',
|
|
28
|
+
timeout: 60000,
|
|
29
|
+
});
|
|
30
|
+
expect(client).toBeDefined();
|
|
31
|
+
});
|
|
32
|
+
it('should initialize all API modules', () => {
|
|
33
|
+
const client = new client_1.WebhookPlatform({ apiKey: 'test_api_key' });
|
|
34
|
+
expect(client.events).toBeDefined();
|
|
35
|
+
expect(client.endpoints).toBeDefined();
|
|
36
|
+
expect(client.subscriptions).toBeDefined();
|
|
37
|
+
expect(client.deliveries).toBeDefined();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('Error Classes', () => {
|
|
42
|
+
describe('WebhookPlatformError', () => {
|
|
43
|
+
it('should have correct properties', () => {
|
|
44
|
+
const error = new errors_1.WebhookPlatformError('Test error', 500, 'test_code');
|
|
45
|
+
expect(error.message).toBe('Test error');
|
|
46
|
+
expect(error.status).toBe(500);
|
|
47
|
+
expect(error.code).toBe('test_code');
|
|
48
|
+
expect(error.name).toBe('WebhookPlatformError');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('AuthenticationError', () => {
|
|
52
|
+
it('should have correct defaults', () => {
|
|
53
|
+
const error = new errors_1.AuthenticationError();
|
|
54
|
+
expect(error.message).toBe('Invalid API key');
|
|
55
|
+
expect(error.status).toBe(401);
|
|
56
|
+
expect(error.code).toBe('authentication_error');
|
|
57
|
+
expect(error.name).toBe('AuthenticationError');
|
|
58
|
+
});
|
|
59
|
+
it('should accept custom message', () => {
|
|
60
|
+
const error = new errors_1.AuthenticationError('Custom auth error');
|
|
61
|
+
expect(error.message).toBe('Custom auth error');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('ValidationError', () => {
|
|
65
|
+
it('should have field errors', () => {
|
|
66
|
+
const fieldErrors = { email: 'Invalid email', url: 'Invalid URL' };
|
|
67
|
+
const error = new errors_1.ValidationError('Validation failed', fieldErrors);
|
|
68
|
+
expect(error.message).toBe('Validation failed');
|
|
69
|
+
expect(error.status).toBe(400);
|
|
70
|
+
expect(error.code).toBe('validation_error');
|
|
71
|
+
expect(error.fieldErrors).toEqual(fieldErrors);
|
|
72
|
+
});
|
|
73
|
+
it('should default to empty field errors', () => {
|
|
74
|
+
const error = new errors_1.ValidationError('Validation failed');
|
|
75
|
+
expect(error.fieldErrors).toEqual({});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX190ZXN0c19fL2NsaWVudC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsc0NBQTRDO0FBQzVDLHNDQUF1RjtBQUV2RixRQUFRLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxFQUFFO0lBQ3RDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsR0FBRyxFQUFFO1FBQzNCLEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7WUFDM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSx3QkFBZSxDQUFDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFDL0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGNBQWMsQ0FBQyx3QkFBZSxDQUFDLENBQUM7UUFDakQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0NBQW9DLEVBQUUsR0FBRyxFQUFFO1lBQzVDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLHdCQUFlLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ25GLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtZQUNyQyxNQUFNLE1BQU0sR0FBRyxJQUFJLHdCQUFlLENBQUMsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsR0FBRyxFQUFFO1lBQ3ZDLE1BQU0sTUFBTSxHQUFHLElBQUksd0JBQWUsQ0FBQztnQkFDakMsTUFBTSxFQUFFLGNBQWM7Z0JBQ3RCLE9BQU8sRUFBRSx5QkFBeUI7YUFDbkMsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtZQUN0QyxNQUFNLE1BQU0sR0FBRyxJQUFJLHdCQUFlLENBQUM7Z0JBQ2pDLE1BQU0sRUFBRSxjQUFjO2dCQUN0QixPQUFPLEVBQUUsS0FBSzthQUNmLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLEVBQUU7WUFDM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSx3QkFBZSxDQUFDLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFDL0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNwQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDM0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRTtJQUM3QixRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO1FBQ3BDLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxHQUFHLEVBQUU7WUFDeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSw2QkFBb0IsQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7UUFDbkMsRUFBRSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtZQUN0QyxNQUFNLEtBQUssR0FBRyxJQUFJLDRCQUFtQixFQUFFLENBQUM7WUFDeEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQ2hELE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDakQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUUsR0FBRyxFQUFFO1lBQ3RDLE1BQU0sS0FBSyxHQUFHLElBQUksNEJBQW1CLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2xELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO1FBQy9CLEVBQUUsQ0FBQywwQkFBMEIsRUFBRSxHQUFHLEVBQUU7WUFDbEMsTUFBTSxXQUFXLEdBQUcsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsQ0FBQztZQUNuRSxNQUFNLEtBQUssR0FBRyxJQUFJLHdCQUFlLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDcEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNoRCxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtZQUM5QyxNQUFNLEtBQUssR0FBRyxJQUFJLHdCQUFlLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUN2RCxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXZWJob29rUGxhdGZvcm0gfSBmcm9tICcuLi9jbGllbnQnO1xuaW1wb3J0IHsgV2ViaG9va1BsYXRmb3JtRXJyb3IsIEF1dGhlbnRpY2F0aW9uRXJyb3IsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmRlc2NyaWJlKCdXZWJob29rUGxhdGZvcm0gQ2xpZW50JywgKCkgPT4ge1xuICBkZXNjcmliZSgnY29uc3RydWN0b3InLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgY2xpZW50IHdpdGggQVBJIGtleScsICgpID0+IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBXZWJob29rUGxhdGZvcm0oeyBhcGlLZXk6ICd0ZXN0X2FwaV9rZXknIH0pO1xuICAgICAgZXhwZWN0KGNsaWVudCkudG9CZUluc3RhbmNlT2YoV2ViaG9va1BsYXRmb3JtKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2l0aG91dCBBUEkga2V5JywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IG5ldyBXZWJob29rUGxhdGZvcm0oeyBhcGlLZXk6ICcnIH0pKS50b1Rocm93KCdBUEkga2V5IGlzIHJlcXVpcmVkJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHVzZSBkZWZhdWx0IGJhc2UgVVJMJywgKCkgPT4ge1xuICAgICAgY29uc3QgY2xpZW50ID0gbmV3IFdlYmhvb2tQbGF0Zm9ybSh7IGFwaUtleTogJ3Rlc3RfYXBpX2tleScgfSk7XG4gICAgICBleHBlY3QoY2xpZW50KS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhY2NlcHQgY3VzdG9tIGJhc2UgVVJMJywgKCkgPT4ge1xuICAgICAgY29uc3QgY2xpZW50ID0gbmV3IFdlYmhvb2tQbGF0Zm9ybSh7XG4gICAgICAgIGFwaUtleTogJ3Rlc3RfYXBpX2tleScsXG4gICAgICAgIGJhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gICAgICB9KTtcbiAgICAgIGV4cGVjdChjbGllbnQpLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFjY2VwdCBjdXN0b20gdGltZW91dCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBXZWJob29rUGxhdGZvcm0oe1xuICAgICAgICBhcGlLZXk6ICd0ZXN0X2FwaV9rZXknLFxuICAgICAgICB0aW1lb3V0OiA2MDAwMCxcbiAgICAgIH0pO1xuICAgICAgZXhwZWN0KGNsaWVudCkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSBhbGwgQVBJIG1vZHVsZXMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjbGllbnQgPSBuZXcgV2ViaG9va1BsYXRmb3JtKHsgYXBpS2V5OiAndGVzdF9hcGlfa2V5JyB9KTtcbiAgICAgIGV4cGVjdChjbGllbnQuZXZlbnRzKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KGNsaWVudC5lbmRwb2ludHMpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2xpZW50LnN1YnNjcmlwdGlvbnMpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2xpZW50LmRlbGl2ZXJpZXMpLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdFcnJvciBDbGFzc2VzJywgKCkgPT4ge1xuICBkZXNjcmliZSgnV2ViaG9va1BsYXRmb3JtRXJyb3InLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIGNvcnJlY3QgcHJvcGVydGllcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IFdlYmhvb2tQbGF0Zm9ybUVycm9yKCdUZXN0IGVycm9yJywgNTAwLCAndGVzdF9jb2RlJyk7XG4gICAgICBleHBlY3QoZXJyb3IubWVzc2FnZSkudG9CZSgnVGVzdCBlcnJvcicpO1xuICAgICAgZXhwZWN0KGVycm9yLnN0YXR1cykudG9CZSg1MDApO1xuICAgICAgZXhwZWN0KGVycm9yLmNvZGUpLnRvQmUoJ3Rlc3RfY29kZScpO1xuICAgICAgZXhwZWN0KGVycm9yLm5hbWUpLnRvQmUoJ1dlYmhvb2tQbGF0Zm9ybUVycm9yJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdBdXRoZW50aWNhdGlvbkVycm9yJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgaGF2ZSBjb3JyZWN0IGRlZmF1bHRzJywgKCkgPT4ge1xuICAgICAgY29uc3QgZXJyb3IgPSBuZXcgQXV0aGVudGljYXRpb25FcnJvcigpO1xuICAgICAgZXhwZWN0KGVycm9yLm1lc3NhZ2UpLnRvQmUoJ0ludmFsaWQgQVBJIGtleScpO1xuICAgICAgZXhwZWN0KGVycm9yLnN0YXR1cykudG9CZSg0MDEpO1xuICAgICAgZXhwZWN0KGVycm9yLmNvZGUpLnRvQmUoJ2F1dGhlbnRpY2F0aW9uX2Vycm9yJyk7XG4gICAgICBleHBlY3QoZXJyb3IubmFtZSkudG9CZSgnQXV0aGVudGljYXRpb25FcnJvcicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhY2NlcHQgY3VzdG9tIG1lc3NhZ2UnLCAoKSA9PiB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBBdXRoZW50aWNhdGlvbkVycm9yKCdDdXN0b20gYXV0aCBlcnJvcicpO1xuICAgICAgZXhwZWN0KGVycm9yLm1lc3NhZ2UpLnRvQmUoJ0N1c3RvbSBhdXRoIGVycm9yJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWYWxpZGF0aW9uRXJyb3InLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBoYXZlIGZpZWxkIGVycm9ycycsICgpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkRXJyb3JzID0geyBlbWFpbDogJ0ludmFsaWQgZW1haWwnLCB1cmw6ICdJbnZhbGlkIFVSTCcgfTtcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IFZhbGlkYXRpb25FcnJvcignVmFsaWRhdGlvbiBmYWlsZWQnLCBmaWVsZEVycm9ycyk7XG4gICAgICBleHBlY3QoZXJyb3IubWVzc2FnZSkudG9CZSgnVmFsaWRhdGlvbiBmYWlsZWQnKTtcbiAgICAgIGV4cGVjdChlcnJvci5zdGF0dXMpLnRvQmUoNDAwKTtcbiAgICAgIGV4cGVjdChlcnJvci5jb2RlKS50b0JlKCd2YWxpZGF0aW9uX2Vycm9yJyk7XG4gICAgICBleHBlY3QoZXJyb3IuZmllbGRFcnJvcnMpLnRvRXF1YWwoZmllbGRFcnJvcnMpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBkZWZhdWx0IHRvIGVtcHR5IGZpZWxkIGVycm9ycycsICgpID0+IHtcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IFZhbGlkYXRpb25FcnJvcignVmFsaWRhdGlvbiBmYWlsZWQnKTtcbiAgICAgIGV4cGVjdChlcnJvci5maWVsZEVycm9ycykudG9FcXVhbCh7fSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const webhooks_1 = require("../webhooks");
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
describe('Webhook Signature Verification', () => {
|
|
6
|
+
const secret = 'whsec_test_secret_key_123';
|
|
7
|
+
const payload = JSON.stringify({ type: 'order.completed', data: { orderId: '12345' } });
|
|
8
|
+
describe('generateSignature', () => {
|
|
9
|
+
it('should generate valid signature format', () => {
|
|
10
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret);
|
|
11
|
+
expect(signature).toMatch(/^t=\d+,v1=[a-f0-9]{64}$/);
|
|
12
|
+
});
|
|
13
|
+
it('should use provided timestamp', () => {
|
|
14
|
+
const timestamp = 1700000000000;
|
|
15
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
16
|
+
expect(signature).toContain(`t=${timestamp}`);
|
|
17
|
+
});
|
|
18
|
+
it('should generate consistent signatures for same inputs', () => {
|
|
19
|
+
const timestamp = 1700000000000;
|
|
20
|
+
const sig1 = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
21
|
+
const sig2 = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
22
|
+
expect(sig1).toBe(sig2);
|
|
23
|
+
});
|
|
24
|
+
it('should generate different signatures for different payloads', () => {
|
|
25
|
+
const timestamp = 1700000000000;
|
|
26
|
+
const sig1 = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
27
|
+
const sig2 = (0, webhooks_1.generateSignature)('different payload', secret, timestamp);
|
|
28
|
+
expect(sig1).not.toBe(sig2);
|
|
29
|
+
});
|
|
30
|
+
it('should generate different signatures for different secrets', () => {
|
|
31
|
+
const timestamp = 1700000000000;
|
|
32
|
+
const sig1 = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
33
|
+
const sig2 = (0, webhooks_1.generateSignature)(payload, 'different_secret', timestamp);
|
|
34
|
+
expect(sig1).not.toBe(sig2);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('verifySignature', () => {
|
|
38
|
+
it('should verify valid signature', () => {
|
|
39
|
+
const timestamp = Date.now();
|
|
40
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
41
|
+
expect((0, webhooks_1.verifySignature)(payload, signature, secret)).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
it('should throw on missing signature', () => {
|
|
44
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, '', secret)).toThrow(errors_1.WebhookPlatformError);
|
|
45
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, '', secret)).toThrow('Missing signature header');
|
|
46
|
+
});
|
|
47
|
+
it('should throw on invalid signature format', () => {
|
|
48
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, 'invalid', secret)).toThrow('Invalid signature format');
|
|
49
|
+
});
|
|
50
|
+
it('should throw on missing timestamp', () => {
|
|
51
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, 'v1=abc123', secret)).toThrow('Invalid signature format');
|
|
52
|
+
});
|
|
53
|
+
it('should throw on missing v1 signature', () => {
|
|
54
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, 't=1700000000000', secret)).toThrow('Invalid signature format');
|
|
55
|
+
});
|
|
56
|
+
it('should throw on expired timestamp', () => {
|
|
57
|
+
const oldTimestamp = Date.now() - 600000; // 10 minutes ago
|
|
58
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, oldTimestamp);
|
|
59
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, signature, secret)).toThrow('outside tolerance window');
|
|
60
|
+
});
|
|
61
|
+
it('should throw on future timestamp outside tolerance', () => {
|
|
62
|
+
const futureTimestamp = Date.now() + 600000; // 10 minutes in future
|
|
63
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, futureTimestamp);
|
|
64
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, signature, secret)).toThrow('outside tolerance window');
|
|
65
|
+
});
|
|
66
|
+
it('should accept timestamp within tolerance', () => {
|
|
67
|
+
const recentTimestamp = Date.now() - 60000; // 1 minute ago
|
|
68
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, recentTimestamp);
|
|
69
|
+
expect((0, webhooks_1.verifySignature)(payload, signature, secret)).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('should throw on invalid signature value', () => {
|
|
72
|
+
const timestamp = Date.now();
|
|
73
|
+
const signature = `t=${timestamp},v1=invalid_signature_that_will_not_match`;
|
|
74
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, signature, secret)).toThrow('Invalid signature');
|
|
75
|
+
});
|
|
76
|
+
it('should throw on tampered payload', () => {
|
|
77
|
+
const timestamp = Date.now();
|
|
78
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
79
|
+
const tamperedPayload = JSON.stringify({ type: 'order.cancelled', data: {} });
|
|
80
|
+
expect(() => (0, webhooks_1.verifySignature)(tamperedPayload, signature, secret)).toThrow('Invalid signature');
|
|
81
|
+
});
|
|
82
|
+
it('should respect custom tolerance', () => {
|
|
83
|
+
const oldTimestamp = Date.now() - 60000; // 1 minute ago
|
|
84
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, oldTimestamp);
|
|
85
|
+
// Should fail with 30s tolerance
|
|
86
|
+
expect(() => (0, webhooks_1.verifySignature)(payload, signature, secret, { tolerance: 30000 }))
|
|
87
|
+
.toThrow('outside tolerance window');
|
|
88
|
+
// Should pass with 2min tolerance
|
|
89
|
+
expect((0, webhooks_1.verifySignature)(payload, signature, secret, { tolerance: 120000 })).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('constructEvent', () => {
|
|
93
|
+
it('should construct event from valid request', () => {
|
|
94
|
+
const timestamp = Date.now();
|
|
95
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
96
|
+
const headers = {
|
|
97
|
+
'x-signature': signature,
|
|
98
|
+
'x-timestamp': timestamp.toString(),
|
|
99
|
+
'x-event-id': 'evt_123',
|
|
100
|
+
'x-delivery-id': 'dlv_456',
|
|
101
|
+
};
|
|
102
|
+
const event = (0, webhooks_1.constructEvent)(payload, headers, secret);
|
|
103
|
+
expect(event.eventId).toBe('evt_123');
|
|
104
|
+
expect(event.deliveryId).toBe('dlv_456');
|
|
105
|
+
expect(event.timestamp).toBe(timestamp);
|
|
106
|
+
expect(event.type).toBe('order.completed');
|
|
107
|
+
expect(event.data).toEqual({ orderId: '12345' });
|
|
108
|
+
});
|
|
109
|
+
it('should handle uppercase headers', () => {
|
|
110
|
+
const timestamp = Date.now();
|
|
111
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
112
|
+
const headers = {
|
|
113
|
+
'X-Signature': signature,
|
|
114
|
+
'X-Timestamp': timestamp.toString(),
|
|
115
|
+
'X-Event-Id': 'evt_123',
|
|
116
|
+
'X-Delivery-Id': 'dlv_456',
|
|
117
|
+
};
|
|
118
|
+
const event = (0, webhooks_1.constructEvent)(payload, headers, secret);
|
|
119
|
+
expect(event.eventId).toBe('evt_123');
|
|
120
|
+
});
|
|
121
|
+
it('should throw on missing signature header', () => {
|
|
122
|
+
const headers = {
|
|
123
|
+
'x-timestamp': Date.now().toString(),
|
|
124
|
+
};
|
|
125
|
+
expect(() => (0, webhooks_1.constructEvent)(payload, headers, secret))
|
|
126
|
+
.toThrow('Missing X-Signature header');
|
|
127
|
+
});
|
|
128
|
+
it('should throw on invalid JSON payload', () => {
|
|
129
|
+
const timestamp = Date.now();
|
|
130
|
+
const invalidPayload = 'not valid json';
|
|
131
|
+
const signature = (0, webhooks_1.generateSignature)(invalidPayload, secret, timestamp);
|
|
132
|
+
const headers = {
|
|
133
|
+
'x-signature': signature,
|
|
134
|
+
'x-timestamp': timestamp.toString(),
|
|
135
|
+
};
|
|
136
|
+
expect(() => (0, webhooks_1.constructEvent)(invalidPayload, headers, secret))
|
|
137
|
+
.toThrow('Invalid JSON payload');
|
|
138
|
+
});
|
|
139
|
+
it('should handle payload without nested data field', () => {
|
|
140
|
+
const flatPayload = JSON.stringify({ type: 'test.event', value: 123 });
|
|
141
|
+
const timestamp = Date.now();
|
|
142
|
+
const signature = (0, webhooks_1.generateSignature)(flatPayload, secret, timestamp);
|
|
143
|
+
const headers = {
|
|
144
|
+
'x-signature': signature,
|
|
145
|
+
'x-timestamp': timestamp.toString(),
|
|
146
|
+
};
|
|
147
|
+
const event = (0, webhooks_1.constructEvent)(flatPayload, headers, secret);
|
|
148
|
+
expect(event.type).toBe('test.event');
|
|
149
|
+
expect(event.data).toEqual({ type: 'test.event', value: 123 });
|
|
150
|
+
});
|
|
151
|
+
it('should use current timestamp if not provided in headers', () => {
|
|
152
|
+
const timestamp = Date.now();
|
|
153
|
+
const signature = (0, webhooks_1.generateSignature)(payload, secret, timestamp);
|
|
154
|
+
const headers = {
|
|
155
|
+
'x-signature': signature,
|
|
156
|
+
};
|
|
157
|
+
const event = (0, webhooks_1.constructEvent)(payload, headers, secret);
|
|
158
|
+
expect(event.timestamp).toBeGreaterThan(0);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViaG9va3MudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fX3Rlc3RzX18vd2ViaG9va3MudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDBDQUFpRjtBQUNqRixzQ0FBaUQ7QUFFakQsUUFBUSxDQUFDLGdDQUFnQyxFQUFFLEdBQUcsRUFBRTtJQUM5QyxNQUFNLE1BQU0sR0FBRywyQkFBMkIsQ0FBQztJQUMzQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFeEYsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEdBQUcsRUFBRTtRQUNqQyxFQUFFLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFO1lBQ2hELE1BQU0sU0FBUyxHQUFHLElBQUEsNEJBQWlCLEVBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3JELE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUN2RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywrQkFBK0IsRUFBRSxHQUFHLEVBQUU7WUFDdkMsTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sU0FBUyxHQUFHLElBQUEsNEJBQWlCLEVBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNoRSxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx1REFBdUQsRUFBRSxHQUFHLEVBQUU7WUFDL0QsTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxHQUFHLElBQUEsNEJBQWlCLEVBQUMsT0FB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QUFNLENBQUMsQ0FBQztZQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN0QyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDakUsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseURBQXlELEVBQUUsR0FBRyxFQUFFO1lBQ2pFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUM3QixNQUFNLFNBQVMsR0FBRyxJQUFBLDRCQUFpQixFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFFaEUsTUFBTSxPQUFPLEdBQUc7Z0JBQ2QsYUFBYSxFQUFFLFNBQVM7YUFDekIsQ0FBQztZQUVGLE1BQU0sS0FBSyxHQUFHLElBQUEseUJBQWMsRUFBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHZlcmlmeVNpZ25hdHVyZSwgY29uc3RydWN0RXZlbnQsIGdlbmVyYXRlU2lnbmF0dXJlIH0gZnJvbSAnLi4vd2ViaG9va3MnO1xuaW1wb3J0IHsgV2ViaG9va1BsYXRmb3JtRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuXG5kZXNjcmliZSgnV2ViaG9vayBTaWduYXR1cmUgVmVyaWZpY2F0aW9uJywgKCkgPT4ge1xuICBjb25zdCBzZWNyZXQgPSAnd2hzZWNfdGVzdF9zZWNyZXRfa2V5XzEyMyc7XG4gIGNvbnN0IHBheWxvYWQgPSBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdvcmRlci5jb21wbGV0ZWQnLCBkYXRhOiB7IG9yZGVySWQ6ICcxMjM0NScgfSB9KTtcblxuICBkZXNjcmliZSgnZ2VuZXJhdGVTaWduYXR1cmUnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSB2YWxpZCBzaWduYXR1cmUgZm9ybWF0JywgKCkgPT4ge1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVTaWduYXR1cmUocGF5bG9hZCwgc2VjcmV0KTtcbiAgICAgIGV4cGVjdChzaWduYXR1cmUpLnRvTWF0Y2goL150PVxcZCssdjE9W2EtZjAtOV17NjR9JC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB1c2UgcHJvdmlkZWQgdGltZXN0YW1wJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gMTcwMDAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgdGltZXN0YW1wKTtcbiAgICAgIGV4cGVjdChzaWduYXR1cmUpLnRvQ29udGFpbihgdD0ke3RpbWVzdGFtcH1gKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgY29uc2lzdGVudCBzaWduYXR1cmVzIGZvciBzYW1lIGlucHV0cycsICgpID0+IHtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IDE3MDAwMDAwMDAwMDA7XG4gICAgICBjb25zdCBzaWcxID0gZ2VuZXJhdGVTaWduYXR1cmUocGF5bG9hZCwgc2VjcmV0LCB0aW1lc3RhbXApO1xuICAgICAgY29uc3Qgc2lnMiA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgdGltZXN0YW1wKTtcbiAgICAgIGV4cGVjdChzaWcxKS50b0JlKHNpZzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBkaWZmZXJlbnQgc2lnbmF0dXJlcyBmb3IgZGlmZmVyZW50IHBheWxvYWRzJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gMTcwMDAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IHNpZzEgPSBnZW5lcmF0ZVNpZ25hdHVyZShwYXlsb2FkLCBzZWNyZXQsIHRpbWVzdGFtcCk7XG4gICAgICBjb25zdCBzaWcyID0gZ2VuZXJhdGVTaWduYXR1cmUoJ2RpZmZlcmVudCBwYXlsb2FkJywgc2VjcmV0LCB0aW1lc3RhbXApO1xuICAgICAgZXhwZWN0KHNpZzEpLm5vdC50b0JlKHNpZzIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBkaWZmZXJlbnQgc2lnbmF0dXJlcyBmb3IgZGlmZmVyZW50IHNlY3JldHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSAxNzAwMDAwMDAwMDAwO1xuICAgICAgY29uc3Qgc2lnMSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgdGltZXN0YW1wKTtcbiAgICAgIGNvbnN0IHNpZzIgPSBnZW5lcmF0ZVNpZ25hdHVyZShwYXlsb2FkLCAnZGlmZmVyZW50X3NlY3JldCcsIHRpbWVzdGFtcCk7XG4gICAgICBleHBlY3Qoc2lnMSkubm90LnRvQmUoc2lnMik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2ZXJpZnlTaWduYXR1cmUnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgc2lnbmF0dXJlJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgdGltZXN0YW1wKTtcbiAgICAgIGV4cGVjdCh2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgc2lnbmF0dXJlLCBzZWNyZXQpKS50b0JlKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBtaXNzaW5nIHNpZ25hdHVyZScsICgpID0+IHtcbiAgICAgIGV4cGVjdCgoKSA9PiB2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgJycsIHNlY3JldCkpLnRvVGhyb3coV2ViaG9va1BsYXRmb3JtRXJyb3IpO1xuICAgICAgZXhwZWN0KCgpID0+IHZlcmlmeVNpZ25hdHVyZShwYXlsb2FkLCAnJywgc2VjcmV0KSkudG9UaHJvdygnTWlzc2luZyBzaWduYXR1cmUgaGVhZGVyJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG9uIGludmFsaWQgc2lnbmF0dXJlIGZvcm1hdCcsICgpID0+IHtcbiAgICAgIGV4cGVjdCgoKSA9PiB2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgJ2ludmFsaWQnLCBzZWNyZXQpKS50b1Rocm93KCdJbnZhbGlkIHNpZ25hdHVyZSBmb3JtYXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gbWlzc2luZyB0aW1lc3RhbXAnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4gdmVyaWZ5U2lnbmF0dXJlKHBheWxvYWQsICd2MT1hYmMxMjMnLCBzZWNyZXQpKS50b1Rocm93KCdJbnZhbGlkIHNpZ25hdHVyZSBmb3JtYXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gbWlzc2luZyB2MSBzaWduYXR1cmUnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4gdmVyaWZ5U2lnbmF0dXJlKHBheWxvYWQsICd0PTE3MDAwMDAwMDAwMDAnLCBzZWNyZXQpKS50b1Rocm93KCdJbnZhbGlkIHNpZ25hdHVyZSBmb3JtYXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gZXhwaXJlZCB0aW1lc3RhbXAnLCAoKSA9PiB7XG4gICAgICBjb25zdCBvbGRUaW1lc3RhbXAgPSBEYXRlLm5vdygpIC0gNjAwMDAwOyAvLyAxMCBtaW51dGVzIGFnb1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVTaWduYXR1cmUocGF5bG9hZCwgc2VjcmV0LCBvbGRUaW1lc3RhbXApO1xuICAgICAgZXhwZWN0KCgpID0+IHZlcmlmeVNpZ25hdHVyZShwYXlsb2FkLCBzaWduYXR1cmUsIHNlY3JldCkpLnRvVGhyb3coJ291dHNpZGUgdG9sZXJhbmNlIHdpbmRvdycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBmdXR1cmUgdGltZXN0YW1wIG91dHNpZGUgdG9sZXJhbmNlJywgKCkgPT4ge1xuICAgICAgY29uc3QgZnV0dXJlVGltZXN0YW1wID0gRGF0ZS5ub3coKSArIDYwMDAwMDsgLy8gMTAgbWludXRlcyBpbiBmdXR1cmVcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgZnV0dXJlVGltZXN0YW1wKTtcbiAgICAgIGV4cGVjdCgoKSA9PiB2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgc2lnbmF0dXJlLCBzZWNyZXQpKS50b1Rocm93KCdvdXRzaWRlIHRvbGVyYW5jZSB3aW5kb3cnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWNjZXB0IHRpbWVzdGFtcCB3aXRoaW4gdG9sZXJhbmNlJywgKCkgPT4ge1xuICAgICAgY29uc3QgcmVjZW50VGltZXN0YW1wID0gRGF0ZS5ub3coKSAtIDYwMDAwOyAvLyAxIG1pbnV0ZSBhZ29cbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgcmVjZW50VGltZXN0YW1wKTtcbiAgICAgIGV4cGVjdCh2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgc2lnbmF0dXJlLCBzZWNyZXQpKS50b0JlKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBpbnZhbGlkIHNpZ25hdHVyZSB2YWx1ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBgdD0ke3RpbWVzdGFtcH0sdjE9aW52YWxpZF9zaWduYXR1cmVfdGhhdF93aWxsX25vdF9tYXRjaGA7XG4gICAgICBleHBlY3QoKCkgPT4gdmVyaWZ5U2lnbmF0dXJlKHBheWxvYWQsIHNpZ25hdHVyZSwgc2VjcmV0KSkudG9UaHJvdygnSW52YWxpZCBzaWduYXR1cmUnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgb24gdGFtcGVyZWQgcGF5bG9hZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBnZW5lcmF0ZVNpZ25hdHVyZShwYXlsb2FkLCBzZWNyZXQsIHRpbWVzdGFtcCk7XG4gICAgICBjb25zdCB0YW1wZXJlZFBheWxvYWQgPSBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdvcmRlci5jYW5jZWxsZWQnLCBkYXRhOiB7fSB9KTtcbiAgICAgIGV4cGVjdCgoKSA9PiB2ZXJpZnlTaWduYXR1cmUodGFtcGVyZWRQYXlsb2FkLCBzaWduYXR1cmUsIHNlY3JldCkpLnRvVGhyb3coJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgY3VzdG9tIHRvbGVyYW5jZScsICgpID0+IHtcbiAgICAgIGNvbnN0IG9sZFRpbWVzdGFtcCA9IERhdGUubm93KCkgLSA2MDAwMDsgLy8gMSBtaW51dGUgYWdvXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBnZW5lcmF0ZVNpZ25hdHVyZShwYXlsb2FkLCBzZWNyZXQsIG9sZFRpbWVzdGFtcCk7XG4gICAgICBcbiAgICAgIC8vIFNob3VsZCBmYWlsIHdpdGggMzBzIHRvbGVyYW5jZVxuICAgICAgZXhwZWN0KCgpID0+IHZlcmlmeVNpZ25hdHVyZShwYXlsb2FkLCBzaWduYXR1cmUsIHNlY3JldCwgeyB0b2xlcmFuY2U6IDMwMDAwIH0pKVxuICAgICAgICAudG9UaHJvdygnb3V0c2lkZSB0b2xlcmFuY2Ugd2luZG93Jyk7XG4gICAgICBcbiAgICAgIC8vIFNob3VsZCBwYXNzIHdpdGggMm1pbiB0b2xlcmFuY2VcbiAgICAgIGV4cGVjdCh2ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgc2lnbmF0dXJlLCBzZWNyZXQsIHsgdG9sZXJhbmNlOiAxMjAwMDAgfSkpLnRvQmUodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjb25zdHJ1Y3RFdmVudCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGNvbnN0cnVjdCBldmVudCBmcm9tIHZhbGlkIHJlcXVlc3QnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVTaWduYXR1cmUocGF5bG9hZCwgc2VjcmV0LCB0aW1lc3RhbXApO1xuICAgICAgXG4gICAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgICAneC1zaWduYXR1cmUnOiBzaWduYXR1cmUsXG4gICAgICAgICd4LXRpbWVzdGFtcCc6IHRpbWVzdGFtcC50b1N0cmluZygpLFxuICAgICAgICAneC1ldmVudC1pZCc6ICdldnRfMTIzJyxcbiAgICAgICAgJ3gtZGVsaXZlcnktaWQnOiAnZGx2XzQ1NicsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBldmVudCA9IGNvbnN0cnVjdEV2ZW50KHBheWxvYWQsIGhlYWRlcnMsIHNlY3JldCk7XG4gICAgICBcbiAgICAgIGV4cGVjdChldmVudC5ldmVudElkKS50b0JlKCdldnRfMTIzJyk7XG4gICAgICBleHBlY3QoZXZlbnQuZGVsaXZlcnlJZCkudG9CZSgnZGx2XzQ1NicpO1xuICAgICAgZXhwZWN0KGV2ZW50LnRpbWVzdGFtcCkudG9CZSh0aW1lc3RhbXApO1xuICAgICAgZXhwZWN0KGV2ZW50LnR5cGUpLnRvQmUoJ29yZGVyLmNvbXBsZXRlZCcpO1xuICAgICAgZXhwZWN0KGV2ZW50LmRhdGEpLnRvRXF1YWwoeyBvcmRlcklkOiAnMTIzNDUnIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgdXBwZXJjYXNlIGhlYWRlcnMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gZ2VuZXJhdGVTaWduYXR1cmUocGF5bG9hZCwgc2VjcmV0LCB0aW1lc3RhbXApO1xuICAgICAgXG4gICAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgICAnWC1TaWduYXR1cmUnOiBzaWduYXR1cmUsXG4gICAgICAgICdYLVRpbWVzdGFtcCc6IHRpbWVzdGFtcC50b1N0cmluZygpLFxuICAgICAgICAnWC1FdmVudC1JZCc6ICdldnRfMTIzJyxcbiAgICAgICAgJ1gtRGVsaXZlcnktSWQnOiAnZGx2XzQ1NicsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBldmVudCA9IGNvbnN0cnVjdEV2ZW50KHBheWxvYWQsIGhlYWRlcnMsIHNlY3JldCk7XG4gICAgICBleHBlY3QoZXZlbnQuZXZlbnRJZCkudG9CZSgnZXZ0XzEyMycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBtaXNzaW5nIHNpZ25hdHVyZSBoZWFkZXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgICAneC10aW1lc3RhbXAnOiBEYXRlLm5vdygpLnRvU3RyaW5nKCksXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QoKCkgPT4gY29uc3RydWN0RXZlbnQocGF5bG9hZCwgaGVhZGVycywgc2VjcmV0KSlcbiAgICAgICAgLnRvVGhyb3coJ01pc3NpbmcgWC1TaWduYXR1cmUgaGVhZGVyJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG9uIGludmFsaWQgSlNPTiBwYXlsb2FkJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IGludmFsaWRQYXlsb2FkID0gJ25vdCB2YWxpZCBqc29uJztcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKGludmFsaWRQYXlsb2FkLCBzZWNyZXQsIHRpbWVzdGFtcCk7XG4gICAgICBcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7XG4gICAgICAgICd4LXNpZ25hdHVyZSc6IHNpZ25hdHVyZSxcbiAgICAgICAgJ3gtdGltZXN0YW1wJzogdGltZXN0YW1wLnRvU3RyaW5nKCksXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QoKCkgPT4gY29uc3RydWN0RXZlbnQoaW52YWxpZFBheWxvYWQsIGhlYWRlcnMsIHNlY3JldCkpXG4gICAgICAgIC50b1Rocm93KCdJbnZhbGlkIEpTT04gcGF5bG9hZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgcGF5bG9hZCB3aXRob3V0IG5lc3RlZCBkYXRhIGZpZWxkJywgKCkgPT4ge1xuICAgICAgY29uc3QgZmxhdFBheWxvYWQgPSBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICd0ZXN0LmV2ZW50JywgdmFsdWU6IDEyMyB9KTtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBnZW5lcmF0ZVNpZ25hdHVyZShmbGF0UGF5bG9hZCwgc2VjcmV0LCB0aW1lc3RhbXApO1xuICAgICAgXG4gICAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgICAneC1zaWduYXR1cmUnOiBzaWduYXR1cmUsXG4gICAgICAgICd4LXRpbWVzdGFtcCc6IHRpbWVzdGFtcC50b1N0cmluZygpLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZXZlbnQgPSBjb25zdHJ1Y3RFdmVudChmbGF0UGF5bG9hZCwgaGVhZGVycywgc2VjcmV0KTtcbiAgICAgIGV4cGVjdChldmVudC50eXBlKS50b0JlKCd0ZXN0LmV2ZW50Jyk7XG4gICAgICBleHBlY3QoZXZlbnQuZGF0YSkudG9FcXVhbCh7IHR5cGU6ICd0ZXN0LmV2ZW50JywgdmFsdWU6IDEyMyB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdXNlIGN1cnJlbnQgdGltZXN0YW1wIGlmIG5vdCBwcm92aWRlZCBpbiBoZWFkZXJzJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGdlbmVyYXRlU2lnbmF0dXJlKHBheWxvYWQsIHNlY3JldCwgdGltZXN0YW1wKTtcbiAgICAgIFxuICAgICAgY29uc3QgaGVhZGVycyA9IHtcbiAgICAgICAgJ3gtc2lnbmF0dXJlJzogc2lnbmF0dXJlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZXZlbnQgPSBjb25zdHJ1Y3RFdmVudChwYXlsb2FkLCBoZWFkZXJzLCBzZWNyZXQpO1xuICAgICAgZXhwZWN0KGV2ZW50LnRpbWVzdGFtcCkudG9CZUdyZWF0ZXJUaGFuKDApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WebhookPlatformConfig, Event, EventResponse, Endpoint, EndpointCreateParams, EndpointUpdateParams, Subscription, SubscriptionCreateParams, Delivery, DeliveryAttempt, DeliveryListParams, PaginatedResponse, EndpointTestResult } from './types';
|
|
2
|
+
export declare class WebhookPlatform {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly baseUrl;
|
|
5
|
+
private readonly timeout;
|
|
6
|
+
readonly events: Events;
|
|
7
|
+
readonly endpoints: Endpoints;
|
|
8
|
+
readonly subscriptions: Subscriptions;
|
|
9
|
+
readonly deliveries: Deliveries;
|
|
10
|
+
constructor(config: WebhookPlatformConfig);
|
|
11
|
+
request<T>(method: string, path: string, body?: unknown, idempotencyKey?: string): Promise<T>;
|
|
12
|
+
private extractRateLimitInfo;
|
|
13
|
+
private handleError;
|
|
14
|
+
}
|
|
15
|
+
declare class Events {
|
|
16
|
+
private client;
|
|
17
|
+
constructor(client: WebhookPlatform);
|
|
18
|
+
send(event: Event, idempotencyKey?: string): Promise<EventResponse>;
|
|
19
|
+
}
|
|
20
|
+
declare class Endpoints {
|
|
21
|
+
private client;
|
|
22
|
+
constructor(client: WebhookPlatform);
|
|
23
|
+
create(projectId: string, params: EndpointCreateParams): Promise<Endpoint>;
|
|
24
|
+
get(projectId: string, endpointId: string): Promise<Endpoint>;
|
|
25
|
+
list(projectId: string): Promise<Endpoint[]>;
|
|
26
|
+
update(projectId: string, endpointId: string, params: EndpointUpdateParams): Promise<Endpoint>;
|
|
27
|
+
delete(projectId: string, endpointId: string): Promise<void>;
|
|
28
|
+
rotateSecret(projectId: string, endpointId: string): Promise<Endpoint>;
|
|
29
|
+
test(projectId: string, endpointId: string): Promise<EndpointTestResult>;
|
|
30
|
+
}
|
|
31
|
+
declare class Subscriptions {
|
|
32
|
+
private client;
|
|
33
|
+
constructor(client: WebhookPlatform);
|
|
34
|
+
create(projectId: string, params: SubscriptionCreateParams): Promise<Subscription>;
|
|
35
|
+
get(projectId: string, subscriptionId: string): Promise<Subscription>;
|
|
36
|
+
list(projectId: string): Promise<Subscription[]>;
|
|
37
|
+
update(projectId: string, subscriptionId: string, params: Partial<SubscriptionCreateParams>): Promise<Subscription>;
|
|
38
|
+
delete(projectId: string, subscriptionId: string): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
declare class Deliveries {
|
|
41
|
+
private client;
|
|
42
|
+
constructor(client: WebhookPlatform);
|
|
43
|
+
get(deliveryId: string): Promise<Delivery>;
|
|
44
|
+
list(projectId: string, params?: DeliveryListParams): Promise<PaginatedResponse<Delivery>>;
|
|
45
|
+
getAttempts(deliveryId: string): Promise<DeliveryAttempt[]>;
|
|
46
|
+
replay(deliveryId: string): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export {};
|