@amigo-ai/platform-sdk 0.2.1 → 0.4.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 +70 -6
- package/dist/core/errors.js +2 -3
- package/dist/core/errors.js.map +1 -1
- package/dist/core/webhooks.js +127 -13
- package/dist/core/webhooks.js.map +1 -1
- package/dist/index.cjs +123 -18
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +123 -18
- package/dist/index.mjs.map +2 -2
- package/dist/types/core/errors.d.ts.map +1 -1
- package/dist/types/core/webhooks.d.ts +19 -1
- package/dist/types/core/webhooks.d.ts.map +1 -1
- package/dist/types/generated/api.d.ts +12694 -11729
- package/dist/types/generated/api.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/resources/actions.d.ts +83 -83
- package/dist/types/resources/actions.d.ts.map +1 -1
- package/dist/types/resources/agents.d.ts +30 -30
- package/dist/types/resources/agents.d.ts.map +1 -1
- package/dist/types/resources/analytics.d.ts +12 -12
- package/dist/types/resources/analytics.d.ts.map +1 -1
- package/dist/types/resources/api-keys.d.ts +15 -15
- package/dist/types/resources/api-keys.d.ts.map +1 -1
- package/dist/types/resources/audit.d.ts +11 -11
- package/dist/types/resources/audit.d.ts.map +1 -1
- package/dist/types/resources/billing.d.ts +9 -9
- package/dist/types/resources/billing.d.ts.map +1 -1
- package/dist/types/resources/calls.d.ts +31 -45
- package/dist/types/resources/calls.d.ts.map +1 -1
- package/dist/types/resources/compliance.d.ts +17 -17
- package/dist/types/resources/context-graphs.d.ts +35 -35
- package/dist/types/resources/context-graphs.d.ts.map +1 -1
- package/dist/types/resources/data-sources.d.ts +47 -47
- package/dist/types/resources/data-sources.d.ts.map +1 -1
- package/dist/types/resources/functions.d.ts +12 -12
- package/dist/types/resources/functions.d.ts.map +1 -1
- package/dist/types/resources/integrations.d.ts +43 -43
- package/dist/types/resources/integrations.d.ts.map +1 -1
- package/dist/types/resources/memory.d.ts +10 -10
- package/dist/types/resources/memory.d.ts.map +1 -1
- package/dist/types/resources/operators.d.ts +53 -53
- package/dist/types/resources/operators.d.ts.map +1 -1
- package/dist/types/resources/personas.d.ts +23 -23
- package/dist/types/resources/personas.d.ts.map +1 -1
- package/dist/types/resources/phone-numbers.d.ts +38 -38
- package/dist/types/resources/phone-numbers.d.ts.map +1 -1
- package/dist/types/resources/recordings.d.ts +10 -10
- package/dist/types/resources/review-queue.d.ts +71 -71
- package/dist/types/resources/review-queue.d.ts.map +1 -1
- package/dist/types/resources/safety.d.ts +23 -23
- package/dist/types/resources/safety.d.ts.map +1 -1
- package/dist/types/resources/services.d.ts +50 -50
- package/dist/types/resources/services.d.ts.map +1 -1
- package/dist/types/resources/settings.d.ts +24 -24
- package/dist/types/resources/settings.d.ts.map +1 -1
- package/dist/types/resources/simulations.d.ts +12 -12
- package/dist/types/resources/simulations.d.ts.map +1 -1
- package/dist/types/resources/skills.d.ts +83 -83
- package/dist/types/resources/skills.d.ts.map +1 -1
- package/dist/types/resources/triggers.d.ts +55 -55
- package/dist/types/resources/triggers.d.ts.map +1 -1
- package/dist/types/resources/webhook-destinations.d.ts +35 -35
- package/dist/types/resources/webhook-destinations.d.ts.map +1 -1
- package/dist/types/resources/workspaces.d.ts +26 -26
- package/dist/types/resources/workspaces.d.ts.map +1 -1
- package/dist/types/resources/world.d.ts +41 -41
- package/dist/types/resources/world.d.ts.map +1 -1
- package/package.json +36 -14
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @amigo-ai/platform-sdk
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@amigo-ai/platform-sdk)
|
|
4
|
+
[](https://github.com/amigo-ai/amigo-platform-typescript-sdk/actions/workflows/test.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
3
7
|
Official TypeScript SDK for the [Amigo Platform API](https://api.platform.amigo.ai/v1/docs).
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
@@ -59,6 +63,24 @@ const client = new AmigoClient({
|
|
|
59
63
|
|
|
60
64
|
GET requests are retried on 408, 429, 500, 502, 503, 504. POST requests are only retried on 429 with a `Retry-After` header. Backoff uses full jitter.
|
|
61
65
|
|
|
66
|
+
## Generated Types
|
|
67
|
+
|
|
68
|
+
The SDK ships with generated OpenAPI types and re-exports them for direct use:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import type { components, operations, paths } from '@amigo-ai/platform-sdk'
|
|
72
|
+
|
|
73
|
+
type Agent = components['schemas']['AgentResponse']
|
|
74
|
+
type ListAgentsQuery =
|
|
75
|
+
operations['list_agents_v1__workspace_id__agents_get']['parameters']['query']
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Public builds are generated from the committed [`openapi.json`](./openapi.json) snapshot in this repo so type output stays deterministic across machines and CI runs. When you need to refresh that snapshot, run:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm run openapi:sync
|
|
82
|
+
```
|
|
83
|
+
|
|
62
84
|
## Resources
|
|
63
85
|
|
|
64
86
|
### Agents
|
|
@@ -93,13 +115,15 @@ const latest = await client.agents.getVersion(agent.id, 'latest')
|
|
|
93
115
|
const { items: agents } = await client.agents.list({ search: 'intake' })
|
|
94
116
|
```
|
|
95
117
|
|
|
96
|
-
###
|
|
118
|
+
### Actions
|
|
119
|
+
|
|
120
|
+
Actions are reusable agent capabilities (formerly "skills").
|
|
97
121
|
|
|
98
122
|
```typescript
|
|
99
|
-
const
|
|
123
|
+
const action = await client.actions.create({
|
|
100
124
|
slug: 'schedule-appointment',
|
|
101
125
|
name: 'Schedule Appointment',
|
|
102
|
-
description: 'Books appointments in the
|
|
126
|
+
description: 'Books appointments in the scheduling system',
|
|
103
127
|
input_schema: {
|
|
104
128
|
type: 'object',
|
|
105
129
|
properties: {
|
|
@@ -112,10 +136,10 @@ const skill = await client.skills.create({
|
|
|
112
136
|
})
|
|
113
137
|
|
|
114
138
|
// Test with a sample input
|
|
115
|
-
const result = await client.
|
|
116
|
-
input: { patient_id: '
|
|
139
|
+
const result = await client.actions.test(action.id, {
|
|
140
|
+
input: { patient_id: 'ID-001', appointment_type: 'follow-up' },
|
|
117
141
|
})
|
|
118
|
-
console.log(result.
|
|
142
|
+
console.log(result.result, result.duration_ms)
|
|
119
143
|
```
|
|
120
144
|
|
|
121
145
|
### Services
|
|
@@ -361,6 +385,44 @@ const dest = await client.webhookDestinations.create({
|
|
|
361
385
|
const deliveries = await client.webhookDestinations.listDeliveries(dest.id)
|
|
362
386
|
```
|
|
363
387
|
|
|
388
|
+
## Webhook Verification
|
|
389
|
+
|
|
390
|
+
Use the raw request body when verifying webhook deliveries. Timestamped signatures are replay-protected by default.
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
import {
|
|
394
|
+
parseWebhookEvent,
|
|
395
|
+
WebhookVerificationError,
|
|
396
|
+
} from '@amigo-ai/platform-sdk'
|
|
397
|
+
|
|
398
|
+
const body = await request.text()
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
const event = await parseWebhookEvent({
|
|
402
|
+
payload: body,
|
|
403
|
+
signature: request.headers.get('x-amigo-signature') ?? '',
|
|
404
|
+
timestamp: request.headers.get('x-amigo-timestamp') ?? undefined,
|
|
405
|
+
secret: process.env.AMIGO_WEBHOOK_SECRET!,
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
console.log(event.type, event.data)
|
|
409
|
+
} catch (error) {
|
|
410
|
+
if (error instanceof WebhookVerificationError) {
|
|
411
|
+
console.error('Rejected webhook:', error.message)
|
|
412
|
+
} else {
|
|
413
|
+
throw error
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
If your delivery channel only provides a legacy HMAC without a timestamp, the original helper signature still works:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
import { parseWebhookEvent } from '@amigo-ai/platform-sdk'
|
|
422
|
+
|
|
423
|
+
const event = await parseWebhookEvent(rawBody, signature, secret)
|
|
424
|
+
```
|
|
425
|
+
|
|
364
426
|
## BFF Proxy (Next.js)
|
|
365
427
|
|
|
366
428
|
For frontend apps that use a Backend-for-Frontend proxy:
|
|
@@ -416,6 +478,8 @@ try {
|
|
|
416
478
|
}
|
|
417
479
|
```
|
|
418
480
|
|
|
481
|
+
Webhook verification errors are separate from API transport errors and throw `WebhookVerificationError`.
|
|
482
|
+
|
|
419
483
|
### Error classes
|
|
420
484
|
|
|
421
485
|
| Class | HTTP Status | Description |
|
package/dist/core/errors.js
CHANGED
|
@@ -140,9 +140,8 @@ export class ConfigurationError extends AmigoError {
|
|
|
140
140
|
}
|
|
141
141
|
export async function createApiError(response) {
|
|
142
142
|
let body = {};
|
|
143
|
-
let rawBody;
|
|
144
143
|
try {
|
|
145
|
-
rawBody = await response.text();
|
|
144
|
+
const rawBody = await response.text();
|
|
146
145
|
body = JSON.parse(rawBody);
|
|
147
146
|
}
|
|
148
147
|
catch {
|
|
@@ -151,7 +150,7 @@ export async function createApiError(response) {
|
|
|
151
150
|
const ctx = {
|
|
152
151
|
statusCode: response.status,
|
|
153
152
|
errorCode: body.error_code,
|
|
154
|
-
requestId: body.request_id,
|
|
153
|
+
requestId: body.request_id ?? response.headers.get('x-request-id') ?? undefined,
|
|
155
154
|
detail: body.detail,
|
|
156
155
|
context: { url: response.url, response: body },
|
|
157
156
|
};
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/core/webhooks.js
CHANGED
|
@@ -1,17 +1,131 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.
|
|
7
|
-
.
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
export async function
|
|
11
|
-
const
|
|
1
|
+
const textEncoder = new TextEncoder();
|
|
2
|
+
const MAX_TIMESTAMP_SKEW_MS = 5 * 60 * 1000;
|
|
3
|
+
export class WebhookVerificationError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'WebhookVerificationError';
|
|
7
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export async function verifyWebhookSignature(payloadOrOptions, signature, secret) {
|
|
11
|
+
const options = normalizeVerificationOptions(payloadOrOptions, signature, secret);
|
|
12
|
+
const payloadBytes = toUint8Array(options.payload);
|
|
13
|
+
const expectedSignature = await signWebhookPayload(payloadBytes, options.secret, options.timestamp);
|
|
14
|
+
const actualSignature = normalizeSignature(options.signature);
|
|
15
|
+
if (!actualSignature || !constantTimeEqual(expectedSignature, actualSignature)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (options.timestamp) {
|
|
19
|
+
const timestampMs = parseTimestamp(options.timestamp);
|
|
20
|
+
if (timestampMs === undefined)
|
|
21
|
+
return false;
|
|
22
|
+
const maxAgeMs = options.maxAgeMs ?? MAX_TIMESTAMP_SKEW_MS;
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
if (timestampMs > now + maxAgeMs || now - timestampMs > maxAgeMs) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
export async function parseWebhookEvent(payloadOrOptions, signature, secret) {
|
|
31
|
+
const options = normalizeParseOptions(payloadOrOptions, signature, secret);
|
|
32
|
+
const valid = await verifyWebhookSignature(options);
|
|
12
33
|
if (!valid) {
|
|
13
|
-
throw new
|
|
34
|
+
throw new WebhookVerificationError('Invalid or expired webhook signature');
|
|
35
|
+
}
|
|
36
|
+
const payloadText = decodePayload(options.payload);
|
|
37
|
+
let event;
|
|
38
|
+
try {
|
|
39
|
+
event = JSON.parse(payloadText, options.reviver);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new WebhookVerificationError('Invalid JSON webhook payload');
|
|
43
|
+
}
|
|
44
|
+
if (options.expectedType && event.type !== options.expectedType) {
|
|
45
|
+
throw new WebhookVerificationError(`Unexpected webhook event type: expected ${options.expectedType}, received ${event.type}`);
|
|
46
|
+
}
|
|
47
|
+
options.validate?.(event);
|
|
48
|
+
return event;
|
|
49
|
+
}
|
|
50
|
+
function normalizeVerificationOptions(payloadOrOptions, signature, secret) {
|
|
51
|
+
if (typeof payloadOrOptions === 'object' &&
|
|
52
|
+
payloadOrOptions !== null &&
|
|
53
|
+
'payload' in payloadOrOptions) {
|
|
54
|
+
return payloadOrOptions;
|
|
55
|
+
}
|
|
56
|
+
if (!signature || !secret) {
|
|
57
|
+
throw new TypeError('signature and secret are required');
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
payload: payloadOrOptions,
|
|
61
|
+
signature,
|
|
62
|
+
secret,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function normalizeParseOptions(payloadOrOptions, signature, secret) {
|
|
66
|
+
if (typeof payloadOrOptions === 'object' && payloadOrOptions !== null && 'payload' in payloadOrOptions) {
|
|
67
|
+
return payloadOrOptions;
|
|
14
68
|
}
|
|
15
|
-
|
|
69
|
+
if (!signature || !secret) {
|
|
70
|
+
throw new TypeError('signature and secret are required');
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
payload: payloadOrOptions,
|
|
74
|
+
signature,
|
|
75
|
+
secret,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function decodePayload(payload) {
|
|
79
|
+
if (typeof payload === 'string')
|
|
80
|
+
return payload;
|
|
81
|
+
return new TextDecoder().decode(toUint8Array(payload));
|
|
82
|
+
}
|
|
83
|
+
function toUint8Array(payload) {
|
|
84
|
+
if (typeof payload === 'string')
|
|
85
|
+
return textEncoder.encode(payload);
|
|
86
|
+
if (payload instanceof Uint8Array)
|
|
87
|
+
return payload;
|
|
88
|
+
return new Uint8Array(payload);
|
|
89
|
+
}
|
|
90
|
+
async function signWebhookPayload(payload, secret, timestamp) {
|
|
91
|
+
const key = await crypto.subtle.importKey('raw', textEncoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
92
|
+
const message = timestamp
|
|
93
|
+
? concatUint8Arrays(textEncoder.encode(`v1:${timestamp}:`), payload)
|
|
94
|
+
: payload;
|
|
95
|
+
const mac = await crypto.subtle.sign('HMAC', key, message);
|
|
96
|
+
return new Uint8Array(mac);
|
|
97
|
+
}
|
|
98
|
+
function normalizeSignature(signature) {
|
|
99
|
+
const normalized = signature.startsWith('sha256=') ? signature.slice(7) : signature;
|
|
100
|
+
if (!/^[a-fA-F0-9]+$/.test(normalized) || normalized.length % 2 !== 0) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
104
|
+
for (let index = 0; index < normalized.length; index += 2) {
|
|
105
|
+
bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);
|
|
106
|
+
}
|
|
107
|
+
return bytes;
|
|
108
|
+
}
|
|
109
|
+
function constantTimeEqual(expected, actual) {
|
|
110
|
+
const maxLength = Math.max(expected.length, actual.length);
|
|
111
|
+
let diff = expected.length ^ actual.length;
|
|
112
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
113
|
+
diff |= (expected[index] ?? 0) ^ (actual[index] ?? 0);
|
|
114
|
+
}
|
|
115
|
+
return diff === 0;
|
|
116
|
+
}
|
|
117
|
+
function parseTimestamp(timestamp) {
|
|
118
|
+
const numeric = Number(timestamp);
|
|
119
|
+
if (Number.isFinite(numeric)) {
|
|
120
|
+
return numeric < 1_000_000_000_000 ? numeric * 1000 : numeric;
|
|
121
|
+
}
|
|
122
|
+
const parsed = Date.parse(timestamp);
|
|
123
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
124
|
+
}
|
|
125
|
+
function concatUint8Arrays(left, right) {
|
|
126
|
+
const combined = new Uint8Array(left.length + right.length);
|
|
127
|
+
combined.set(left, 0);
|
|
128
|
+
combined.set(right, left.length);
|
|
129
|
+
return combined;
|
|
16
130
|
}
|
|
17
131
|
//# sourceMappingURL=webhooks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/core/webhooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/core/webhooks.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
ServerError: () => ServerError,
|
|
46
46
|
ServiceUnavailableError: () => ServiceUnavailableError,
|
|
47
47
|
ValidationError: () => ValidationError,
|
|
48
|
+
WebhookVerificationError: () => WebhookVerificationError,
|
|
48
49
|
actionId: () => actionId,
|
|
49
50
|
agentId: () => agentId,
|
|
50
51
|
apiKeyId: () => apiKeyId,
|
|
@@ -204,16 +205,15 @@ var ConfigurationError = class extends AmigoError {
|
|
|
204
205
|
};
|
|
205
206
|
async function createApiError(response) {
|
|
206
207
|
let body = {};
|
|
207
|
-
let rawBody;
|
|
208
208
|
try {
|
|
209
|
-
rawBody = await response.text();
|
|
209
|
+
const rawBody = await response.text();
|
|
210
210
|
body = JSON.parse(rawBody);
|
|
211
211
|
} catch {
|
|
212
212
|
}
|
|
213
213
|
const ctx = {
|
|
214
214
|
statusCode: response.status,
|
|
215
215
|
errorCode: body.error_code,
|
|
216
|
-
requestId: body.request_id,
|
|
216
|
+
requestId: body.request_id ?? response.headers.get("x-request-id") ?? void 0,
|
|
217
217
|
detail: body.detail,
|
|
218
218
|
context: { url: response.url, response: body }
|
|
219
219
|
};
|
|
@@ -2199,29 +2199,134 @@ function parseRateLimitHeaders(headers) {
|
|
|
2199
2199
|
}
|
|
2200
2200
|
|
|
2201
2201
|
// src/core/webhooks.ts
|
|
2202
|
-
|
|
2203
|
-
|
|
2202
|
+
var textEncoder = new TextEncoder();
|
|
2203
|
+
var MAX_TIMESTAMP_SKEW_MS = 5 * 60 * 1e3;
|
|
2204
|
+
var WebhookVerificationError = class extends Error {
|
|
2205
|
+
constructor(message) {
|
|
2206
|
+
super(message);
|
|
2207
|
+
this.name = "WebhookVerificationError";
|
|
2208
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
2209
|
+
}
|
|
2210
|
+
};
|
|
2211
|
+
async function verifyWebhookSignature(payloadOrOptions, signature, secret) {
|
|
2212
|
+
const options = normalizeVerificationOptions(payloadOrOptions, signature, secret);
|
|
2213
|
+
const payloadBytes = toUint8Array(options.payload);
|
|
2214
|
+
const expectedSignature = await signWebhookPayload(payloadBytes, options.secret, options.timestamp);
|
|
2215
|
+
const actualSignature = normalizeSignature(options.signature);
|
|
2216
|
+
if (!actualSignature || !constantTimeEqual(expectedSignature, actualSignature)) {
|
|
2217
|
+
return false;
|
|
2218
|
+
}
|
|
2219
|
+
if (options.timestamp) {
|
|
2220
|
+
const timestampMs = parseTimestamp(options.timestamp);
|
|
2221
|
+
if (timestampMs === void 0) return false;
|
|
2222
|
+
const maxAgeMs = options.maxAgeMs ?? MAX_TIMESTAMP_SKEW_MS;
|
|
2223
|
+
const now = Date.now();
|
|
2224
|
+
if (timestampMs > now + maxAgeMs || now - timestampMs > maxAgeMs) {
|
|
2225
|
+
return false;
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
async function parseWebhookEvent(payloadOrOptions, signature, secret) {
|
|
2231
|
+
const options = normalizeParseOptions(payloadOrOptions, signature, secret);
|
|
2232
|
+
const valid = await verifyWebhookSignature(options);
|
|
2233
|
+
if (!valid) {
|
|
2234
|
+
throw new WebhookVerificationError("Invalid or expired webhook signature");
|
|
2235
|
+
}
|
|
2236
|
+
const payloadText = decodePayload(options.payload);
|
|
2237
|
+
let event;
|
|
2238
|
+
try {
|
|
2239
|
+
event = JSON.parse(payloadText, options.reviver);
|
|
2240
|
+
} catch {
|
|
2241
|
+
throw new WebhookVerificationError("Invalid JSON webhook payload");
|
|
2242
|
+
}
|
|
2243
|
+
if (options.expectedType && event.type !== options.expectedType) {
|
|
2244
|
+
throw new WebhookVerificationError(
|
|
2245
|
+
`Unexpected webhook event type: expected ${options.expectedType}, received ${event.type}`
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
options.validate?.(event);
|
|
2249
|
+
return event;
|
|
2250
|
+
}
|
|
2251
|
+
function normalizeVerificationOptions(payloadOrOptions, signature, secret) {
|
|
2252
|
+
if (typeof payloadOrOptions === "object" && payloadOrOptions !== null && "payload" in payloadOrOptions) {
|
|
2253
|
+
return payloadOrOptions;
|
|
2254
|
+
}
|
|
2255
|
+
if (!signature || !secret) {
|
|
2256
|
+
throw new TypeError("signature and secret are required");
|
|
2257
|
+
}
|
|
2258
|
+
return {
|
|
2259
|
+
payload: payloadOrOptions,
|
|
2260
|
+
signature,
|
|
2261
|
+
secret
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
function normalizeParseOptions(payloadOrOptions, signature, secret) {
|
|
2265
|
+
if (typeof payloadOrOptions === "object" && payloadOrOptions !== null && "payload" in payloadOrOptions) {
|
|
2266
|
+
return payloadOrOptions;
|
|
2267
|
+
}
|
|
2268
|
+
if (!signature || !secret) {
|
|
2269
|
+
throw new TypeError("signature and secret are required");
|
|
2270
|
+
}
|
|
2271
|
+
return {
|
|
2272
|
+
payload: payloadOrOptions,
|
|
2273
|
+
signature,
|
|
2274
|
+
secret
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2277
|
+
function decodePayload(payload) {
|
|
2278
|
+
if (typeof payload === "string") return payload;
|
|
2279
|
+
return new TextDecoder().decode(toUint8Array(payload));
|
|
2280
|
+
}
|
|
2281
|
+
function toUint8Array(payload) {
|
|
2282
|
+
if (typeof payload === "string") return textEncoder.encode(payload);
|
|
2283
|
+
if (payload instanceof Uint8Array) return payload;
|
|
2284
|
+
return new Uint8Array(payload);
|
|
2285
|
+
}
|
|
2286
|
+
async function signWebhookPayload(payload, secret, timestamp) {
|
|
2204
2287
|
const key = await crypto.subtle.importKey(
|
|
2205
2288
|
"raw",
|
|
2206
|
-
|
|
2289
|
+
textEncoder.encode(secret),
|
|
2207
2290
|
{ name: "HMAC", hash: "SHA-256" },
|
|
2208
2291
|
false,
|
|
2209
2292
|
["sign"]
|
|
2210
2293
|
);
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
typeof payload === "string" ? encoder.encode(payload) : payload
|
|
2215
|
-
);
|
|
2216
|
-
const expected = Array.from(new Uint8Array(mac)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2217
|
-
return signature === `sha256=${expected}`;
|
|
2294
|
+
const message = timestamp ? concatUint8Arrays(textEncoder.encode(`v1:${timestamp}:`), payload) : payload;
|
|
2295
|
+
const mac = await crypto.subtle.sign("HMAC", key, message);
|
|
2296
|
+
return new Uint8Array(mac);
|
|
2218
2297
|
}
|
|
2219
|
-
|
|
2220
|
-
const
|
|
2221
|
-
if (
|
|
2222
|
-
|
|
2298
|
+
function normalizeSignature(signature) {
|
|
2299
|
+
const normalized = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
2300
|
+
if (!/^[a-fA-F0-9]+$/.test(normalized) || normalized.length % 2 !== 0) {
|
|
2301
|
+
return void 0;
|
|
2223
2302
|
}
|
|
2224
|
-
|
|
2303
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
2304
|
+
for (let index = 0; index < normalized.length; index += 2) {
|
|
2305
|
+
bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);
|
|
2306
|
+
}
|
|
2307
|
+
return bytes;
|
|
2308
|
+
}
|
|
2309
|
+
function constantTimeEqual(expected, actual) {
|
|
2310
|
+
const maxLength = Math.max(expected.length, actual.length);
|
|
2311
|
+
let diff = expected.length ^ actual.length;
|
|
2312
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
2313
|
+
diff |= (expected[index] ?? 0) ^ (actual[index] ?? 0);
|
|
2314
|
+
}
|
|
2315
|
+
return diff === 0;
|
|
2316
|
+
}
|
|
2317
|
+
function parseTimestamp(timestamp) {
|
|
2318
|
+
const numeric = Number(timestamp);
|
|
2319
|
+
if (Number.isFinite(numeric)) {
|
|
2320
|
+
return numeric < 1e12 ? numeric * 1e3 : numeric;
|
|
2321
|
+
}
|
|
2322
|
+
const parsed = Date.parse(timestamp);
|
|
2323
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
2324
|
+
}
|
|
2325
|
+
function concatUint8Arrays(left, right) {
|
|
2326
|
+
const combined = new Uint8Array(left.length + right.length);
|
|
2327
|
+
combined.set(left, 0);
|
|
2328
|
+
combined.set(right, left.length);
|
|
2329
|
+
return combined;
|
|
2225
2330
|
}
|
|
2226
2331
|
|
|
2227
2332
|
// src/index.ts
|