@amigo-ai/platform-sdk 0.3.0 → 0.4.1
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 +112 -49
- package/dist/core/errors.js +2 -3
- package/dist/core/errors.js.map +1 -1
- package/dist/core/webhooks.js +133 -13
- package/dist/core/webhooks.js.map +1 -1
- package/dist/index.cjs +131 -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 +131 -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
|
@@ -23,29 +23,38 @@ const client = new AmigoClient({
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
// List agents
|
|
26
|
-
const { items: agents } = await client.agents.list()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
const { items: agents } = await client.agents.list({ limit: 10 })
|
|
27
|
+
console.log(agents.map((agent) => agent.name))
|
|
28
|
+
|
|
29
|
+
// Search entities in the world model
|
|
30
|
+
const entityResults = await client.world.listEntities({
|
|
31
|
+
q: 'Jane Doe',
|
|
32
|
+
entity_type: ['patient'],
|
|
33
|
+
limit: 5,
|
|
33
34
|
})
|
|
35
|
+
console.log(entityResults.entities[0]?.display_name)
|
|
34
36
|
|
|
35
37
|
// Get call analytics for the last 30 days
|
|
36
|
-
const stats = await client.analytics.getCalls({
|
|
38
|
+
const stats = await client.analytics.getCalls({ days: 30 })
|
|
37
39
|
console.log(stats.total_calls, stats.avg_duration_seconds)
|
|
38
40
|
```
|
|
39
41
|
|
|
42
|
+
## Examples and Docs
|
|
43
|
+
|
|
44
|
+
- Product docs and API reference: [docs.amigo.ai](https://docs.amigo.ai/)
|
|
45
|
+
- Repo-local SDK examples: [examples/README.md](./examples/README.md)
|
|
46
|
+
|
|
47
|
+
The docs site remains the primary reference. The examples in this repo stay close to the package surface and are typechecked in CI to reduce drift.
|
|
48
|
+
|
|
40
49
|
## Configuration
|
|
41
50
|
|
|
42
|
-
| Option
|
|
43
|
-
|
|
44
|
-
| `apiKey`
|
|
45
|
-
| `workspaceId` | `string`
|
|
46
|
-
| `baseUrl`
|
|
47
|
-
| `retry`
|
|
48
|
-
| `fetch`
|
|
51
|
+
| Option | Type | Required | Description |
|
|
52
|
+
| ------------- | -------------- | -------- | -------------------------------------------------------------------- |
|
|
53
|
+
| `apiKey` | `string` | Yes | Your Platform API key — create one at Workspace Settings > API Keys |
|
|
54
|
+
| `workspaceId` | `string` | Yes | Your workspace ID — all resource operations are scoped to this |
|
|
55
|
+
| `baseUrl` | `string` | No | Override the API base URL (default: `https://api.platform.amigo.ai`) |
|
|
56
|
+
| `retry` | `RetryOptions` | No | Retry configuration for transient failures |
|
|
57
|
+
| `fetch` | `typeof fetch` | No | Custom fetch for BFF proxy, cookie forwarding, or test mocking |
|
|
49
58
|
|
|
50
59
|
### Retry options
|
|
51
60
|
|
|
@@ -54,8 +63,8 @@ const client = new AmigoClient({
|
|
|
54
63
|
apiKey: 'your-key',
|
|
55
64
|
workspaceId: 'your-workspace-id',
|
|
56
65
|
retry: {
|
|
57
|
-
maxAttempts: 3,
|
|
58
|
-
baseDelayMs: 250,
|
|
66
|
+
maxAttempts: 3, // Total attempts including first. Default: 3
|
|
67
|
+
baseDelayMs: 250, // Base delay for exponential backoff. Default: 250
|
|
59
68
|
maxDelayMs: 30000, // Cap on delay. Default: 30_000
|
|
60
69
|
},
|
|
61
70
|
})
|
|
@@ -63,6 +72,23 @@ const client = new AmigoClient({
|
|
|
63
72
|
|
|
64
73
|
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.
|
|
65
74
|
|
|
75
|
+
## Generated Types
|
|
76
|
+
|
|
77
|
+
The SDK ships with generated OpenAPI types and re-exports them for direct use:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import type { components, operations, paths } from '@amigo-ai/platform-sdk'
|
|
81
|
+
|
|
82
|
+
type Agent = components['schemas']['AgentResponse']
|
|
83
|
+
type ListAgentsQuery = operations['list_agents_v1__workspace_id__agents_get']['parameters']['query']
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
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:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run openapi:sync
|
|
90
|
+
```
|
|
91
|
+
|
|
66
92
|
## Resources
|
|
67
93
|
|
|
68
94
|
### Agents
|
|
@@ -139,25 +165,27 @@ console.log(service.agent_name, service.channel_type, service.version_sets)
|
|
|
139
165
|
The world model tracks entities (patients, contacts, appointments) and the events that flow through them.
|
|
140
166
|
|
|
141
167
|
```typescript
|
|
142
|
-
//
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
168
|
+
// Filter entities with simple list queries
|
|
169
|
+
const patients = await client.world.listEntities({
|
|
170
|
+
q: 'Jane Doe',
|
|
171
|
+
entity_type: ['patient'],
|
|
172
|
+
limit: 10,
|
|
147
173
|
})
|
|
174
|
+
console.log(patients.entities.length)
|
|
148
175
|
|
|
149
|
-
//
|
|
150
|
-
await client.world.
|
|
151
|
-
|
|
152
|
-
event_type: 'call_completed',
|
|
153
|
-
data: { duration_seconds: 180, outcome: 'appointment_scheduled' },
|
|
154
|
-
})
|
|
176
|
+
// Get a single entity
|
|
177
|
+
const patient = await client.world.getEntity('entity-id')
|
|
178
|
+
console.log(patient.display_name, patient.entity_type)
|
|
155
179
|
|
|
156
180
|
// Query timeline
|
|
157
|
-
const timeline = await client.world.getTimeline(
|
|
181
|
+
const timeline = await client.world.getTimeline('entity-id', { limit: 20 })
|
|
158
182
|
|
|
159
|
-
//
|
|
160
|
-
const results = await client.world.search(
|
|
183
|
+
// Semantic search over the world model
|
|
184
|
+
const results = await client.world.search({
|
|
185
|
+
q: 'Jane Doe',
|
|
186
|
+
entity_type: 'patient',
|
|
187
|
+
limit: 5,
|
|
188
|
+
})
|
|
161
189
|
|
|
162
190
|
// View sync status from connectors
|
|
163
191
|
const syncStatus = await client.world.getSyncStatusBySink()
|
|
@@ -191,7 +219,7 @@ console.log(dashboard.call_volume.value, dashboard.call_volume.delta_pct)
|
|
|
191
219
|
console.log(dashboard.avg_quality.value)
|
|
192
220
|
|
|
193
221
|
// Call volume time series
|
|
194
|
-
const calls = await client.analytics.getCalls({
|
|
222
|
+
const calls = await client.analytics.getCalls({ days: 30, interval: '1d' })
|
|
195
223
|
console.log(calls.total_calls, calls.calls_by_date)
|
|
196
224
|
|
|
197
225
|
// Per-agent performance
|
|
@@ -229,11 +257,9 @@ console.log(analytics.coverage_rate, analytics.total_facts)
|
|
|
229
257
|
const { items: integrations } = await client.integrations.list({ enabled: true })
|
|
230
258
|
|
|
231
259
|
// Test a specific endpoint
|
|
232
|
-
const result = await client.integrations.testEndpoint(
|
|
233
|
-
'
|
|
234
|
-
|
|
235
|
-
{ textQuery: '123 Main St, Springfield' },
|
|
236
|
-
)
|
|
260
|
+
const result = await client.integrations.testEndpoint('integration-id', 'geocode', {
|
|
261
|
+
textQuery: '123 Main St, Springfield',
|
|
262
|
+
})
|
|
237
263
|
```
|
|
238
264
|
|
|
239
265
|
### Data Sources
|
|
@@ -367,6 +393,41 @@ const dest = await client.webhookDestinations.create({
|
|
|
367
393
|
const deliveries = await client.webhookDestinations.listDeliveries(dest.id)
|
|
368
394
|
```
|
|
369
395
|
|
|
396
|
+
## Webhook Verification
|
|
397
|
+
|
|
398
|
+
Use the raw request body when verifying webhook deliveries. Timestamped signatures are replay-protected by default.
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { parseWebhookEvent, WebhookVerificationError } from '@amigo-ai/platform-sdk'
|
|
402
|
+
|
|
403
|
+
const body = await request.text()
|
|
404
|
+
|
|
405
|
+
try {
|
|
406
|
+
const event = await parseWebhookEvent({
|
|
407
|
+
payload: body,
|
|
408
|
+
signature: request.headers.get('x-amigo-signature') ?? '',
|
|
409
|
+
timestamp: request.headers.get('x-amigo-timestamp') ?? undefined,
|
|
410
|
+
secret: process.env.AMIGO_WEBHOOK_SECRET!,
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
console.log(event.type, event.data)
|
|
414
|
+
} catch (error) {
|
|
415
|
+
if (error instanceof WebhookVerificationError) {
|
|
416
|
+
console.error('Rejected webhook:', error.message)
|
|
417
|
+
} else {
|
|
418
|
+
throw error
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
If your delivery channel only provides a legacy HMAC without a timestamp, the original helper signature still works:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { parseWebhookEvent } from '@amigo-ai/platform-sdk'
|
|
427
|
+
|
|
428
|
+
const event = await parseWebhookEvent(rawBody, signature, secret)
|
|
429
|
+
```
|
|
430
|
+
|
|
370
431
|
## BFF Proxy (Next.js)
|
|
371
432
|
|
|
372
433
|
For frontend apps that use a Backend-for-Frontend proxy:
|
|
@@ -422,20 +483,22 @@ try {
|
|
|
422
483
|
}
|
|
423
484
|
```
|
|
424
485
|
|
|
486
|
+
Webhook verification errors are separate from API transport errors and throw `WebhookVerificationError`.
|
|
487
|
+
|
|
425
488
|
### Error classes
|
|
426
489
|
|
|
427
|
-
| Class
|
|
428
|
-
|
|
429
|
-
| `BadRequestError`
|
|
430
|
-
| `AuthenticationError` | 401
|
|
431
|
-
| `PermissionError`
|
|
432
|
-
| `NotFoundError`
|
|
433
|
-
| `ConflictError`
|
|
434
|
-
| `ValidationError`
|
|
435
|
-
| `RateLimitError`
|
|
436
|
-
| `ServerError`
|
|
437
|
-
| `ConfigurationError`
|
|
438
|
-
| `NetworkError`
|
|
490
|
+
| Class | HTTP Status | Description |
|
|
491
|
+
| --------------------- | ----------- | --------------------------------------- |
|
|
492
|
+
| `BadRequestError` | 400 | Malformed request |
|
|
493
|
+
| `AuthenticationError` | 401 | Invalid or expired API key |
|
|
494
|
+
| `PermissionError` | 403 | Insufficient permissions |
|
|
495
|
+
| `NotFoundError` | 404 | Resource does not exist |
|
|
496
|
+
| `ConflictError` | 409 | Duplicate slug or version conflict |
|
|
497
|
+
| `ValidationError` | 422 | Request body validation failure |
|
|
498
|
+
| `RateLimitError` | 429 | Too many requests — check `.retryAfter` |
|
|
499
|
+
| `ServerError` | 5xx | Server-side error |
|
|
500
|
+
| `ConfigurationError` | — | SDK misconfiguration at init time |
|
|
501
|
+
| `NetworkError` | — | Fetch/network failure |
|
|
439
502
|
|
|
440
503
|
## CommonJS (CJS) usage
|
|
441
504
|
|
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,137 @@
|
|
|
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' &&
|
|
67
|
+
payloadOrOptions !== null &&
|
|
68
|
+
'payload' in payloadOrOptions) {
|
|
69
|
+
return payloadOrOptions;
|
|
14
70
|
}
|
|
15
|
-
|
|
71
|
+
if (!signature || !secret) {
|
|
72
|
+
throw new TypeError('signature and secret are required');
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
payload: payloadOrOptions,
|
|
76
|
+
signature,
|
|
77
|
+
secret,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function decodePayload(payload) {
|
|
81
|
+
if (typeof payload === 'string')
|
|
82
|
+
return payload;
|
|
83
|
+
return new TextDecoder().decode(toUint8Array(payload));
|
|
84
|
+
}
|
|
85
|
+
function toUint8Array(payload) {
|
|
86
|
+
if (typeof payload === 'string')
|
|
87
|
+
return textEncoder.encode(payload);
|
|
88
|
+
if (payload instanceof Uint8Array)
|
|
89
|
+
return payload;
|
|
90
|
+
return new Uint8Array(payload);
|
|
91
|
+
}
|
|
92
|
+
async function signWebhookPayload(payload, secret, timestamp) {
|
|
93
|
+
const key = await crypto.subtle.importKey('raw', textEncoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
94
|
+
const message = timestamp
|
|
95
|
+
? concatUint8Arrays(textEncoder.encode(`v1:${timestamp}:`), payload)
|
|
96
|
+
: payload;
|
|
97
|
+
const mac = await crypto.subtle.sign('HMAC', key, toCryptoBuffer(message));
|
|
98
|
+
return new Uint8Array(mac);
|
|
99
|
+
}
|
|
100
|
+
function normalizeSignature(signature) {
|
|
101
|
+
const normalized = signature.startsWith('sha256=') ? signature.slice(7) : signature;
|
|
102
|
+
if (!/^[a-fA-F0-9]+$/.test(normalized) || normalized.length % 2 !== 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
106
|
+
for (let index = 0; index < normalized.length; index += 2) {
|
|
107
|
+
bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);
|
|
108
|
+
}
|
|
109
|
+
return bytes;
|
|
110
|
+
}
|
|
111
|
+
function constantTimeEqual(expected, actual) {
|
|
112
|
+
const maxLength = Math.max(expected.length, actual.length);
|
|
113
|
+
let diff = expected.length ^ actual.length;
|
|
114
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
115
|
+
diff |= (expected[index] ?? 0) ^ (actual[index] ?? 0);
|
|
116
|
+
}
|
|
117
|
+
return diff === 0;
|
|
118
|
+
}
|
|
119
|
+
function parseTimestamp(timestamp) {
|
|
120
|
+
const numeric = Number(timestamp);
|
|
121
|
+
if (Number.isFinite(numeric)) {
|
|
122
|
+
return numeric < 1_000_000_000_000 ? numeric * 1000 : numeric;
|
|
123
|
+
}
|
|
124
|
+
const parsed = Date.parse(timestamp);
|
|
125
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
126
|
+
}
|
|
127
|
+
function concatUint8Arrays(left, right) {
|
|
128
|
+
const combined = new Uint8Array(left.length + right.length);
|
|
129
|
+
combined.set(left, 0);
|
|
130
|
+
combined.set(right, left.length);
|
|
131
|
+
return combined;
|
|
132
|
+
}
|
|
133
|
+
function toCryptoBuffer(bytes) {
|
|
134
|
+
const copy = Uint8Array.from(bytes);
|
|
135
|
+
return copy.buffer;
|
|
16
136
|
}
|
|
17
137
|
//# 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":"AAAA,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAA;AACrC,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;AAwB3C,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAA;QACtC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACnD,CAAC;CACF;AAQD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,gBAAgF,EAChF,SAAkB,EAClB,MAAe;IAEf,MAAM,OAAO,GAAG,4BAA4B,CAAC,gBAAgB,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;IACjF,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,MAAM,iBAAiB,GAAG,MAAM,kBAAkB,CAChD,YAAY,EACZ,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,SAAS,CAClB,CAAA;IACD,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAE7D,IAAI,CAAC,eAAe,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,eAAe,CAAC,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACrD,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;QAE3C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,qBAAqB,CAAA;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,WAAW,GAAG,GAAG,GAAG,QAAQ,IAAI,GAAG,GAAG,WAAW,GAAG,QAAQ,EAAE,CAAC;YACjE,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,gBAAsD,EACtD,SAAkB,EAClB,MAAe;IAEf,MAAM,OAAO,GAAG,qBAAqB,CAAC,gBAAgB,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;IAC1E,MAAM,KAAK,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAEnD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,wBAAwB,CAAC,sCAAsC,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAElD,IAAI,KAAsB,CAAA;IAC1B,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAoB,CAAA;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,wBAAwB,CAAC,8BAA8B,CAAC,CAAA;IACpE,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;QAChE,MAAM,IAAI,wBAAwB,CAChC,2CAA2C,OAAO,CAAC,YAAY,cAAc,KAAK,CAAC,IAAI,EAAE,CAC1F,CAAA;IACH,CAAC;IAED,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAA;IACzB,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,4BAA4B,CACnC,gBAAgF,EAChF,SAAkB,EAClB,MAAe;IAEf,IACE,OAAO,gBAAgB,KAAK,QAAQ;QACpC,gBAAgB,KAAK,IAAI;QACzB,SAAS,IAAI,gBAAgB,EAC7B,CAAC;QACD,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,SAAS;QACT,MAAM;KACP,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,gBAAsD,EACtD,SAAkB,EAClB,MAAe;IAEf,IACE,OAAO,gBAAgB,KAAK,QAAQ;QACpC,gBAAgB,KAAK,IAAI;QACzB,SAAS,IAAI,gBAAgB,EAC7B,CAAC;QACD,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,SAAS;QACT,MAAM;KACP,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAA0C;IAC/D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAA;IAC/C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,YAAY,CAAC,OAA0C;IAC9D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACnE,IAAI,OAAO,YAAY,UAAU;QAAE,OAAO,OAAO,CAAA;IACjD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,OAAmB,EACnB,MAAc,EACd,SAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAC1B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAA;IAED,MAAM,OAAO,GAAG,SAAS;QACvB,CAAC,CAAC,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAE,OAAO,CAAC;QACpE,CAAC,CAAC,OAAO,CAAA;IAEX,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1E,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;AAC5B,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACtE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACnD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAoB,EAAE,MAAkB;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1D,IAAI,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAE1C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,IAAI,KAAK,CAAC,CAAA;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;IACjC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAA;IAC/D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACpC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAA;AAClD,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAgB,EAAE,KAAiB;IAC5D,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3D,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,KAAiB;IACvC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnC,OAAO,IAAI,CAAC,MAAM,CAAA;AACpB,CAAC"}
|
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,142 @@ 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(
|
|
2215
|
+
payloadBytes,
|
|
2216
|
+
options.secret,
|
|
2217
|
+
options.timestamp
|
|
2218
|
+
);
|
|
2219
|
+
const actualSignature = normalizeSignature(options.signature);
|
|
2220
|
+
if (!actualSignature || !constantTimeEqual(expectedSignature, actualSignature)) {
|
|
2221
|
+
return false;
|
|
2222
|
+
}
|
|
2223
|
+
if (options.timestamp) {
|
|
2224
|
+
const timestampMs = parseTimestamp(options.timestamp);
|
|
2225
|
+
if (timestampMs === void 0) return false;
|
|
2226
|
+
const maxAgeMs = options.maxAgeMs ?? MAX_TIMESTAMP_SKEW_MS;
|
|
2227
|
+
const now = Date.now();
|
|
2228
|
+
if (timestampMs > now + maxAgeMs || now - timestampMs > maxAgeMs) {
|
|
2229
|
+
return false;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
return true;
|
|
2233
|
+
}
|
|
2234
|
+
async function parseWebhookEvent(payloadOrOptions, signature, secret) {
|
|
2235
|
+
const options = normalizeParseOptions(payloadOrOptions, signature, secret);
|
|
2236
|
+
const valid = await verifyWebhookSignature(options);
|
|
2237
|
+
if (!valid) {
|
|
2238
|
+
throw new WebhookVerificationError("Invalid or expired webhook signature");
|
|
2239
|
+
}
|
|
2240
|
+
const payloadText = decodePayload(options.payload);
|
|
2241
|
+
let event;
|
|
2242
|
+
try {
|
|
2243
|
+
event = JSON.parse(payloadText, options.reviver);
|
|
2244
|
+
} catch {
|
|
2245
|
+
throw new WebhookVerificationError("Invalid JSON webhook payload");
|
|
2246
|
+
}
|
|
2247
|
+
if (options.expectedType && event.type !== options.expectedType) {
|
|
2248
|
+
throw new WebhookVerificationError(
|
|
2249
|
+
`Unexpected webhook event type: expected ${options.expectedType}, received ${event.type}`
|
|
2250
|
+
);
|
|
2251
|
+
}
|
|
2252
|
+
options.validate?.(event);
|
|
2253
|
+
return event;
|
|
2254
|
+
}
|
|
2255
|
+
function normalizeVerificationOptions(payloadOrOptions, signature, secret) {
|
|
2256
|
+
if (typeof payloadOrOptions === "object" && payloadOrOptions !== null && "payload" in payloadOrOptions) {
|
|
2257
|
+
return payloadOrOptions;
|
|
2258
|
+
}
|
|
2259
|
+
if (!signature || !secret) {
|
|
2260
|
+
throw new TypeError("signature and secret are required");
|
|
2261
|
+
}
|
|
2262
|
+
return {
|
|
2263
|
+
payload: payloadOrOptions,
|
|
2264
|
+
signature,
|
|
2265
|
+
secret
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
function normalizeParseOptions(payloadOrOptions, signature, secret) {
|
|
2269
|
+
if (typeof payloadOrOptions === "object" && payloadOrOptions !== null && "payload" in payloadOrOptions) {
|
|
2270
|
+
return payloadOrOptions;
|
|
2271
|
+
}
|
|
2272
|
+
if (!signature || !secret) {
|
|
2273
|
+
throw new TypeError("signature and secret are required");
|
|
2274
|
+
}
|
|
2275
|
+
return {
|
|
2276
|
+
payload: payloadOrOptions,
|
|
2277
|
+
signature,
|
|
2278
|
+
secret
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
function decodePayload(payload) {
|
|
2282
|
+
if (typeof payload === "string") return payload;
|
|
2283
|
+
return new TextDecoder().decode(toUint8Array(payload));
|
|
2284
|
+
}
|
|
2285
|
+
function toUint8Array(payload) {
|
|
2286
|
+
if (typeof payload === "string") return textEncoder.encode(payload);
|
|
2287
|
+
if (payload instanceof Uint8Array) return payload;
|
|
2288
|
+
return new Uint8Array(payload);
|
|
2289
|
+
}
|
|
2290
|
+
async function signWebhookPayload(payload, secret, timestamp) {
|
|
2204
2291
|
const key = await crypto.subtle.importKey(
|
|
2205
2292
|
"raw",
|
|
2206
|
-
|
|
2293
|
+
textEncoder.encode(secret),
|
|
2207
2294
|
{ name: "HMAC", hash: "SHA-256" },
|
|
2208
2295
|
false,
|
|
2209
2296
|
["sign"]
|
|
2210
2297
|
);
|
|
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}`;
|
|
2298
|
+
const message = timestamp ? concatUint8Arrays(textEncoder.encode(`v1:${timestamp}:`), payload) : payload;
|
|
2299
|
+
const mac = await crypto.subtle.sign("HMAC", key, toCryptoBuffer(message));
|
|
2300
|
+
return new Uint8Array(mac);
|
|
2218
2301
|
}
|
|
2219
|
-
|
|
2220
|
-
const
|
|
2221
|
-
if (
|
|
2222
|
-
|
|
2302
|
+
function normalizeSignature(signature) {
|
|
2303
|
+
const normalized = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
2304
|
+
if (!/^[a-fA-F0-9]+$/.test(normalized) || normalized.length % 2 !== 0) {
|
|
2305
|
+
return void 0;
|
|
2306
|
+
}
|
|
2307
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
2308
|
+
for (let index = 0; index < normalized.length; index += 2) {
|
|
2309
|
+
bytes[index / 2] = Number.parseInt(normalized.slice(index, index + 2), 16);
|
|
2310
|
+
}
|
|
2311
|
+
return bytes;
|
|
2312
|
+
}
|
|
2313
|
+
function constantTimeEqual(expected, actual) {
|
|
2314
|
+
const maxLength = Math.max(expected.length, actual.length);
|
|
2315
|
+
let diff = expected.length ^ actual.length;
|
|
2316
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
2317
|
+
diff |= (expected[index] ?? 0) ^ (actual[index] ?? 0);
|
|
2223
2318
|
}
|
|
2224
|
-
return
|
|
2319
|
+
return diff === 0;
|
|
2320
|
+
}
|
|
2321
|
+
function parseTimestamp(timestamp) {
|
|
2322
|
+
const numeric = Number(timestamp);
|
|
2323
|
+
if (Number.isFinite(numeric)) {
|
|
2324
|
+
return numeric < 1e12 ? numeric * 1e3 : numeric;
|
|
2325
|
+
}
|
|
2326
|
+
const parsed = Date.parse(timestamp);
|
|
2327
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
2328
|
+
}
|
|
2329
|
+
function concatUint8Arrays(left, right) {
|
|
2330
|
+
const combined = new Uint8Array(left.length + right.length);
|
|
2331
|
+
combined.set(left, 0);
|
|
2332
|
+
combined.set(right, left.length);
|
|
2333
|
+
return combined;
|
|
2334
|
+
}
|
|
2335
|
+
function toCryptoBuffer(bytes) {
|
|
2336
|
+
const copy = Uint8Array.from(bytes);
|
|
2337
|
+
return copy.buffer;
|
|
2225
2338
|
}
|
|
2226
2339
|
|
|
2227
2340
|
// src/index.ts
|