@amigo-ai/platform-sdk 0.24.0 → 0.26.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/api.md +6 -3
- package/dist/core/errors.js +155 -9
- package/dist/core/errors.js.map +1 -1
- package/dist/core/reconnecting-websocket.js +371 -0
- package/dist/core/reconnecting-websocket.js.map +1 -0
- package/dist/index.cjs +711 -13
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +711 -13
- package/dist/index.mjs.map +4 -4
- package/dist/resources/events.js +139 -3
- package/dist/resources/events.js.map +1 -1
- package/dist/resources/integrations.js +25 -0
- package/dist/resources/integrations.js.map +1 -1
- package/dist/resources/observers.js +238 -0
- package/dist/resources/observers.js.map +1 -0
- package/dist/types/core/errors.d.ts +93 -1
- package/dist/types/core/errors.d.ts.map +1 -1
- package/dist/types/core/reconnecting-websocket.d.ts +156 -0
- package/dist/types/core/reconnecting-websocket.d.ts.map +1 -0
- package/dist/types/generated/api.d.ts +686 -113
- package/dist/types/generated/api.d.ts.map +1 -1
- package/dist/types/index.d.cts +42 -2
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +42 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/resources/events.d.ts +33 -0
- package/dist/types/resources/events.d.ts.map +1 -1
- package/dist/types/resources/functions.d.ts.map +1 -1
- package/dist/types/resources/integrations.d.ts +33 -0
- package/dist/types/resources/integrations.d.ts.map +1 -1
- package/dist/types/resources/metrics.d.ts.map +1 -1
- package/dist/types/resources/observers.d.ts +148 -0
- package/dist/types/resources/observers.d.ts.map +1 -0
- package/dist/types/resources/operators.d.ts.map +1 -1
- package/dist/types/resources/settings.d.ts.map +1 -1
- package/package.json +1 -1
package/api.md
CHANGED
|
@@ -47,7 +47,7 @@ Notes:
|
|
|
47
47
|
## Core exports
|
|
48
48
|
|
|
49
49
|
- Errors: `AmigoError`, `BadRequestError`, `AuthenticationError`, `PermissionError`, `NotFoundError`, `ConflictError`, `ValidationError`, `RateLimitError`, `ServerError`, `ServiceUnavailableError`, `NetworkError`, `RequestTimeoutError`, `ParseError`, `ConfigurationError`
|
|
50
|
-
- Error guards: `isAmigoError`, `isNotFoundError`, `isRateLimitError`, `isAuthenticationError`, `isRequestTimeoutError`
|
|
50
|
+
- Error guards: `isAmigoError`, `isNotFoundError`, `isRateLimitError`, `isAuthenticationError`, `isRequestTimeoutError`, `isPermissionError`, `isConflictError`, `isValidationError`, `isServerError`, `isNetworkError`, `isHttpException`, `isHttpValidationError`, `isUnparseableErrorBody`
|
|
51
51
|
- Request option types: `AmigoRequestOptions`, `ScopedRequestOptions`
|
|
52
52
|
- Webhooks: `verifyWebhookSignature`, `parseWebhookEvent`, `WebhookVerificationError`
|
|
53
53
|
- Pagination and response helpers: `paginate`, `buildLastResponse`, `extractRequestId`
|
|
@@ -263,6 +263,7 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
263
263
|
- `update`
|
|
264
264
|
- `delete`
|
|
265
265
|
- `testEndpoint`
|
|
266
|
+
- `testConnection`
|
|
266
267
|
- `getHealthCheck`
|
|
267
268
|
|
|
268
269
|
### `analytics`
|
|
@@ -419,8 +420,6 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
419
420
|
|
|
420
421
|
### `events`
|
|
421
422
|
|
|
422
|
-
- `subscribeToWorkspace`
|
|
423
|
-
|
|
424
423
|
### `functions`
|
|
425
424
|
|
|
426
425
|
- `list`
|
|
@@ -431,4 +430,8 @@ All workspace-scoped resources also expose `withOptions(options)`.
|
|
|
431
430
|
- `query`
|
|
432
431
|
- `sync`
|
|
433
432
|
|
|
433
|
+
### `observers`
|
|
434
|
+
|
|
435
|
+
- `subscribe`
|
|
436
|
+
|
|
434
437
|
### `api`
|
package/dist/core/errors.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Error hierarchy for the Amigo Platform SDK.
|
|
3
3
|
* All errors extend AmigoError which can be caught with a single catch.
|
|
4
4
|
*/
|
|
5
|
+
const RAW_BODY_LIMIT = 8 * 1024; // 8 KB
|
|
5
6
|
const SENSITIVE_FIELDS = new Set([
|
|
6
7
|
'id_token',
|
|
7
8
|
'access_token',
|
|
@@ -42,6 +43,20 @@ export class AmigoError extends Error {
|
|
|
42
43
|
requestId;
|
|
43
44
|
detail;
|
|
44
45
|
context;
|
|
46
|
+
/**
|
|
47
|
+
* Typed body of the error response, when one was returned and successfully
|
|
48
|
+
* parsed. Use the `isHttpException` / `isHttpValidationError` /
|
|
49
|
+
* `isUnparseableErrorBody` type guards to narrow the discriminated union.
|
|
50
|
+
*
|
|
51
|
+
* Named `errorBody` (not `body`) to avoid colliding with the legacy
|
|
52
|
+
* `ParseError.body: string` field.
|
|
53
|
+
*/
|
|
54
|
+
errorBody;
|
|
55
|
+
/**
|
|
56
|
+
* Raw response body (truncated to 8 KB). Populated even when parsing fails,
|
|
57
|
+
* so callers always have something to log when debugging server errors.
|
|
58
|
+
*/
|
|
59
|
+
rawBody;
|
|
45
60
|
constructor(message, ctx = {}) {
|
|
46
61
|
super(message);
|
|
47
62
|
this.name = this.constructor.name;
|
|
@@ -52,6 +67,8 @@ export class AmigoError extends Error {
|
|
|
52
67
|
this.context = ctx.context
|
|
53
68
|
? sanitizeErrorContext(ctx.context)
|
|
54
69
|
: undefined;
|
|
70
|
+
this.errorBody = ctx.errorBody;
|
|
71
|
+
this.rawBody = ctx.rawBody;
|
|
55
72
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
56
73
|
if (typeof Error.captureStackTrace === 'function') {
|
|
57
74
|
Error.captureStackTrace(this, this.constructor);
|
|
@@ -157,23 +174,90 @@ export class ConfigurationError extends AmigoError {
|
|
|
157
174
|
super(message);
|
|
158
175
|
}
|
|
159
176
|
}
|
|
160
|
-
|
|
161
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Best-effort body reader. Always returns *something* — never throws.
|
|
179
|
+
*
|
|
180
|
+
* - On successful JSON parse: returns the typed body (HttpException or
|
|
181
|
+
* HTTPValidationError shape) plus the raw text for logging.
|
|
182
|
+
* - On parse failure or empty body: returns an UnparseableErrorBody with
|
|
183
|
+
* `detail` set to `response.statusText` and the raw text preserved.
|
|
184
|
+
* - On network read failure (connection drop mid-read): returns an
|
|
185
|
+
* UnparseableErrorBody with empty `raw_body`.
|
|
186
|
+
*/
|
|
187
|
+
async function readErrorBody(response) {
|
|
188
|
+
let rawBody = '';
|
|
189
|
+
try {
|
|
190
|
+
rawBody = await response.text();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Connection dropped mid-read or body already consumed — fall through.
|
|
194
|
+
return {
|
|
195
|
+
body: { detail: response.statusText || `HTTP ${response.status}`, raw_body: '' },
|
|
196
|
+
rawBody: '',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const truncatedRaw = rawBody.length > RAW_BODY_LIMIT ? rawBody.slice(0, RAW_BODY_LIMIT) : rawBody;
|
|
200
|
+
if (rawBody.length === 0) {
|
|
201
|
+
return {
|
|
202
|
+
body: { detail: response.statusText || `HTTP ${response.status}`, raw_body: '' },
|
|
203
|
+
rawBody: '',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
const parsed = JSON.parse(rawBody);
|
|
208
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
209
|
+
// Recognized shapes: HTTPValidationError (detail is array) or HttpException.
|
|
210
|
+
return { body: parsed, rawBody: truncatedRaw };
|
|
211
|
+
}
|
|
212
|
+
// JSON parsed but isn't an object (e.g. null, string literal) — surface as
|
|
213
|
+
// unparseable so consumers don't have to guard against weird shapes.
|
|
214
|
+
return {
|
|
215
|
+
body: {
|
|
216
|
+
detail: response.statusText || `HTTP ${response.status}`,
|
|
217
|
+
raw_body: truncatedRaw,
|
|
218
|
+
},
|
|
219
|
+
rawBody: truncatedRaw,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return {
|
|
224
|
+
body: {
|
|
225
|
+
detail: response.statusText || `HTTP ${response.status}`,
|
|
226
|
+
raw_body: truncatedRaw,
|
|
227
|
+
},
|
|
228
|
+
rawBody: truncatedRaw,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function safeStringify(value) {
|
|
162
233
|
try {
|
|
163
|
-
|
|
164
|
-
body = JSON.parse(rawBody);
|
|
234
|
+
return JSON.stringify(value);
|
|
165
235
|
}
|
|
166
236
|
catch {
|
|
167
|
-
|
|
237
|
+
return String(value);
|
|
168
238
|
}
|
|
239
|
+
}
|
|
240
|
+
export async function createApiError(response) {
|
|
241
|
+
const { body, rawBody } = await readErrorBody(response);
|
|
242
|
+
const flat = body;
|
|
243
|
+
const detailString = typeof flat.detail === 'string'
|
|
244
|
+
? flat.detail
|
|
245
|
+
: flat.detail !== undefined
|
|
246
|
+
? safeStringify(flat.detail)
|
|
247
|
+
: undefined;
|
|
248
|
+
const errorCode = typeof flat.error_code === 'string' ? flat.error_code : undefined;
|
|
249
|
+
const requestIdFromBody = typeof flat.request_id === 'string' ? flat.request_id : undefined;
|
|
250
|
+
const messageFromBody = typeof flat.message === 'string' ? flat.message : undefined;
|
|
169
251
|
const ctx = {
|
|
170
252
|
statusCode: response.status,
|
|
171
|
-
errorCode
|
|
172
|
-
requestId:
|
|
173
|
-
detail:
|
|
253
|
+
errorCode,
|
|
254
|
+
requestId: requestIdFromBody ?? response.headers.get('x-request-id') ?? undefined,
|
|
255
|
+
detail: detailString,
|
|
174
256
|
context: { url: response.url, response: body },
|
|
257
|
+
errorBody: body,
|
|
258
|
+
rawBody,
|
|
175
259
|
};
|
|
176
|
-
const message =
|
|
260
|
+
const message = messageFromBody ?? detailString ?? response.statusText ?? `HTTP ${response.status}`;
|
|
177
261
|
switch (response.status) {
|
|
178
262
|
case 400:
|
|
179
263
|
return new BadRequestError(message, ctx);
|
|
@@ -226,4 +310,66 @@ export function isAuthenticationError(err) {
|
|
|
226
310
|
export function isRequestTimeoutError(err) {
|
|
227
311
|
return err instanceof RequestTimeoutError;
|
|
228
312
|
}
|
|
313
|
+
export function isPermissionError(err) {
|
|
314
|
+
return err instanceof PermissionError;
|
|
315
|
+
}
|
|
316
|
+
export function isConflictError(err) {
|
|
317
|
+
return err instanceof ConflictError;
|
|
318
|
+
}
|
|
319
|
+
export function isValidationError(err) {
|
|
320
|
+
return err instanceof ValidationError;
|
|
321
|
+
}
|
|
322
|
+
export function isServerError(err) {
|
|
323
|
+
return err instanceof ServerError;
|
|
324
|
+
}
|
|
325
|
+
export function isNetworkError(err) {
|
|
326
|
+
return err instanceof NetworkError;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* True when `err.errorBody` is the FastAPI 422 validation-error shape (an
|
|
330
|
+
* object with `detail: ValidationError[]`). Lets consumers iterate
|
|
331
|
+
* field-level errors without `as any`:
|
|
332
|
+
*
|
|
333
|
+
* ```ts
|
|
334
|
+
* if (isHttpValidationError(err)) {
|
|
335
|
+
* for (const issue of err.errorBody.detail ?? []) {
|
|
336
|
+
* console.log(issue.loc, issue.msg)
|
|
337
|
+
* }
|
|
338
|
+
* }
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
export function isHttpValidationError(err) {
|
|
342
|
+
if (!(err instanceof AmigoError))
|
|
343
|
+
return false;
|
|
344
|
+
const body = err.errorBody;
|
|
345
|
+
return Array.isArray(body?.detail);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* True when `err.errorBody` is the default FastAPI HTTPException shape
|
|
349
|
+
* (`{ detail: string | object | array }`, possibly with `error_code` /
|
|
350
|
+
* `request_id`). This is the most common error body across platform-api.
|
|
351
|
+
*/
|
|
352
|
+
export function isHttpException(err) {
|
|
353
|
+
if (!(err instanceof AmigoError))
|
|
354
|
+
return false;
|
|
355
|
+
const body = err.errorBody;
|
|
356
|
+
if (!body)
|
|
357
|
+
return false;
|
|
358
|
+
if (Array.isArray(body.detail)) {
|
|
359
|
+
// HTTPValidationError, not a plain HTTPException
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
// Has detail (string/object) and no `raw_body` discriminator from the unparseable fallback
|
|
363
|
+
return 'detail' in body && !('raw_body' in body);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* True when the response body could not be parsed as JSON (or was empty).
|
|
367
|
+
* `err.errorBody.raw_body` is the verbatim text (truncated to 8 KB).
|
|
368
|
+
*/
|
|
369
|
+
export function isUnparseableErrorBody(err) {
|
|
370
|
+
if (!(err instanceof AmigoError))
|
|
371
|
+
return false;
|
|
372
|
+
const body = err.errorBody;
|
|
373
|
+
return typeof body?.raw_body === 'string';
|
|
374
|
+
}
|
|
229
375
|
//# sourceMappingURL=errors.js.map
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnecting WebSocket primitive shared by the SDK's WS-based realtime
|
|
3
|
+
* helpers (text-stream, session-connect, observer).
|
|
4
|
+
*
|
|
5
|
+
* The platform exposes three workspace-scoped WebSocket surfaces with similar
|
|
6
|
+
* lifecycle requirements:
|
|
7
|
+
*
|
|
8
|
+
* * Resume on transient drops with exponential backoff + full jitter
|
|
9
|
+
* * Treat 4001 (client error) and 4403 (auth) close codes as terminal
|
|
10
|
+
* * Treat 4029 (rate limit / cap) as terminal-but-retryable on a slow timer
|
|
11
|
+
* * Watchdog the connection: if no message arrives within an idle window,
|
|
12
|
+
* the upstream is dead even if the TCP socket has not closed; force a
|
|
13
|
+
* reconnect
|
|
14
|
+
* * Surface every typed message through ``onMessage`` and every state
|
|
15
|
+
* transition through ``onStateChange``
|
|
16
|
+
*
|
|
17
|
+
* Before this primitive existed, every consumer (developer-console
|
|
18
|
+
* useStreamSession, useCallObserver, agent-engineering scripts) re-implemented
|
|
19
|
+
* the loop with subtle bugs (different idle thresholds, missing retry budget,
|
|
20
|
+
* no terminal-code handling). This module is the single canonical
|
|
21
|
+
* implementation; resource helpers compose it with their own message parsers
|
|
22
|
+
* and protocol details.
|
|
23
|
+
*
|
|
24
|
+
* @see ReconnectingWebSocket
|
|
25
|
+
* @see EventsResource for the analogous SSE-based helper
|
|
26
|
+
*/
|
|
27
|
+
/** Structured terminal error surfaced to consumers. */
|
|
28
|
+
export class ReconnectingWebSocketError extends Error {
|
|
29
|
+
reason;
|
|
30
|
+
closeCode;
|
|
31
|
+
closeReason;
|
|
32
|
+
attempts;
|
|
33
|
+
constructor(message, reason, closeCode, closeReason, attempts) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = 'ReconnectingWebSocketError';
|
|
36
|
+
this.reason = reason;
|
|
37
|
+
this.closeCode = closeCode;
|
|
38
|
+
this.closeReason = closeReason;
|
|
39
|
+
this.attempts = attempts;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Close codes that should NEVER be retried. The server is telling us the
|
|
44
|
+
* connection cannot succeed regardless of how many times we try.
|
|
45
|
+
*
|
|
46
|
+
* 1008 (policy violation), 4001 (client error / bad params), 4003
|
|
47
|
+
* (forbidden), 4100 (auth / not authenticated, used by some platform
|
|
48
|
+
* endpoints), 4403 (forbidden — used by platform-api session-connect for
|
|
49
|
+
* auth and origin rejection).
|
|
50
|
+
*/
|
|
51
|
+
const TERMINAL_CLOSE_CODES = new Set([1008, 4001, 4003, 4100, 4403]);
|
|
52
|
+
/**
|
|
53
|
+
* Close codes that are terminal-but-rate-limited. The reconnect loop honors
|
|
54
|
+
* a longer floor (``RATE_LIMITED_FLOOR_MS``) before retrying so the client
|
|
55
|
+
* does not amplify the problem it just hit.
|
|
56
|
+
*
|
|
57
|
+
* 4029 (custom platform code for "too many connections / burst exceeded").
|
|
58
|
+
* 1013 (try again later, RFC 6455 standard hint).
|
|
59
|
+
*/
|
|
60
|
+
const RATE_LIMITED_CLOSE_CODES = new Set([1013, 4029]);
|
|
61
|
+
const RATE_LIMITED_FLOOR_MS = 5_000;
|
|
62
|
+
const DEFAULT_INITIAL_DELAY_MS = 1_000;
|
|
63
|
+
const DEFAULT_MAX_DELAY_MS = 30_000;
|
|
64
|
+
const DEFAULT_MAX_RECONNECTS = 10;
|
|
65
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 45_000;
|
|
66
|
+
/**
|
|
67
|
+
* Build a managed reconnecting WebSocket.
|
|
68
|
+
*
|
|
69
|
+
* The returned handle is the only public surface; the underlying
|
|
70
|
+
* ``WebSocket`` is held privately so consumers cannot bypass the lifecycle
|
|
71
|
+
* machinery (which would defeat the watchdog and reconnect loop).
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const handle = createReconnectingWebSocket({
|
|
76
|
+
* url: client.conversations.sessionConnectUrl({ serviceId, entityId }),
|
|
77
|
+
* protocols: sessionConnectAuthProtocols(apiKey),
|
|
78
|
+
* onMessage: (e) => console.log('frame', e.data),
|
|
79
|
+
* onStateChange: (s) => console.log('state', s),
|
|
80
|
+
* onError: (err) => console.error('terminal:', err.reason, err.closeCode),
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* handle.send(JSON.stringify({ type: 'user_text', text: 'hi' }));
|
|
84
|
+
* await handle.done; // resolves after handle.close() or terminal error
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function createReconnectingWebSocket(options) {
|
|
88
|
+
const factory = resolveWebSocketFactory(options.webSocketFactory);
|
|
89
|
+
const initialDelayMs = options.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
|
|
90
|
+
const maxDelayMs = options.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
91
|
+
const maxReconnects = options.maxReconnects ?? DEFAULT_MAX_RECONNECTS;
|
|
92
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
93
|
+
const localController = new AbortController();
|
|
94
|
+
if (options.signal) {
|
|
95
|
+
if (options.signal.aborted) {
|
|
96
|
+
localController.abort(options.signal.reason);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const onAbort = () => localController.abort(options.signal?.reason);
|
|
100
|
+
options.signal.addEventListener('abort', onAbort, { once: true });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
let currentSocket = null;
|
|
104
|
+
let state = 'connecting';
|
|
105
|
+
let errorReported = false;
|
|
106
|
+
function setState(next) {
|
|
107
|
+
if (state === next)
|
|
108
|
+
return;
|
|
109
|
+
state = next;
|
|
110
|
+
try {
|
|
111
|
+
options.onStateChange?.(next);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Consumer-thrown error in onStateChange must not kill the loop.
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function reportError(err) {
|
|
118
|
+
if (errorReported)
|
|
119
|
+
return;
|
|
120
|
+
errorReported = true;
|
|
121
|
+
setState('terminal');
|
|
122
|
+
try {
|
|
123
|
+
options.onError?.(err);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Consumer-thrown error must not leak.
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const handle = {
|
|
130
|
+
get state() {
|
|
131
|
+
return state;
|
|
132
|
+
},
|
|
133
|
+
get done() {
|
|
134
|
+
return done;
|
|
135
|
+
},
|
|
136
|
+
send(data) {
|
|
137
|
+
if (!currentSocket || currentSocket.readyState !== 1 /* OPEN */) {
|
|
138
|
+
throw new Error(`Cannot send on socket in state ${state}`);
|
|
139
|
+
}
|
|
140
|
+
currentSocket.send(data);
|
|
141
|
+
},
|
|
142
|
+
close(code, reason) {
|
|
143
|
+
localController.abort(new Error(reason ?? 'closed'));
|
|
144
|
+
try {
|
|
145
|
+
currentSocket?.close(code, reason);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Already closed; ignore.
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
const done = runLoop({
|
|
153
|
+
factory,
|
|
154
|
+
options,
|
|
155
|
+
initialDelayMs,
|
|
156
|
+
maxDelayMs,
|
|
157
|
+
maxReconnects,
|
|
158
|
+
idleTimeoutMs,
|
|
159
|
+
signal: localController.signal,
|
|
160
|
+
setState,
|
|
161
|
+
reportError,
|
|
162
|
+
setSocket: (s) => {
|
|
163
|
+
currentSocket = s;
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
return handle;
|
|
167
|
+
}
|
|
168
|
+
async function runLoop(args) {
|
|
169
|
+
const { options, signal, setState, reportError, setSocket } = args;
|
|
170
|
+
let attempt = 0;
|
|
171
|
+
let delayMs = args.initialDelayMs;
|
|
172
|
+
while (!signal.aborted) {
|
|
173
|
+
if (attempt > 0) {
|
|
174
|
+
setState('reconnecting');
|
|
175
|
+
const sleepMs = jitter(delayMs);
|
|
176
|
+
try {
|
|
177
|
+
options.onReconnect?.({ attempt, delayMs: sleepMs, closeCode: undefined });
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// ignore
|
|
181
|
+
}
|
|
182
|
+
const slept = await abortableSleep(sleepMs, signal);
|
|
183
|
+
if (!slept)
|
|
184
|
+
break;
|
|
185
|
+
delayMs = Math.min(delayMs * 2, args.maxDelayMs);
|
|
186
|
+
}
|
|
187
|
+
setState(attempt === 0 ? 'connecting' : 'connecting');
|
|
188
|
+
let outcome;
|
|
189
|
+
try {
|
|
190
|
+
outcome = await runOneConnection(args);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
// Synchronous open failure (e.g., factory threw, invalid URL).
|
|
194
|
+
reportError(new ReconnectingWebSocketError(err instanceof Error ? err.message : 'Failed to open WebSocket', 'open_failed', undefined, undefined, attempt));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
setSocket(null);
|
|
199
|
+
}
|
|
200
|
+
// Terminal close codes are reported BEFORE the abort check because the
|
|
201
|
+
// close arrived from the wire — the consumer's subsequent ``close()``
|
|
202
|
+
// call (which flips signal.aborted true) must not suppress the diagnostic.
|
|
203
|
+
if (outcome.closeCode !== undefined && TERMINAL_CLOSE_CODES.has(outcome.closeCode)) {
|
|
204
|
+
reportError(new ReconnectingWebSocketError(`Server closed with terminal code ${outcome.closeCode}: ${outcome.closeReason ?? ''}`, outcome.closeCode === 4403 ? 'auth' : 'client_error', outcome.closeCode, outcome.closeReason, attempt));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (outcome.aborted || signal.aborted) {
|
|
208
|
+
setState('closed');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (attempt >= args.maxReconnects) {
|
|
212
|
+
reportError(new ReconnectingWebSocketError(`Reconnect budget exhausted (${args.maxReconnects} attempts)`, 'reconnect_budget_exhausted', outcome.closeCode, outcome.closeReason, attempt));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (outcome.closeCode !== undefined && RATE_LIMITED_CLOSE_CODES.has(outcome.closeCode)) {
|
|
216
|
+
// Pin the floor up so we do not hammer the server we just got
|
|
217
|
+
// throttled by. Honor whichever is larger between the current
|
|
218
|
+
// exponential delay and the rate-limited floor.
|
|
219
|
+
delayMs = Math.max(delayMs, RATE_LIMITED_FLOOR_MS);
|
|
220
|
+
}
|
|
221
|
+
attempt += 1;
|
|
222
|
+
}
|
|
223
|
+
setState('closed');
|
|
224
|
+
}
|
|
225
|
+
async function runOneConnection(args) {
|
|
226
|
+
const { options, factory, signal, setState, setSocket, idleTimeoutMs } = args;
|
|
227
|
+
let socket;
|
|
228
|
+
try {
|
|
229
|
+
socket = factory(options.url, options.protocols);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
233
|
+
}
|
|
234
|
+
setSocket(socket);
|
|
235
|
+
return new Promise((resolve) => {
|
|
236
|
+
let watchdogTimer = null;
|
|
237
|
+
let resolved = false;
|
|
238
|
+
function clearWatchdog() {
|
|
239
|
+
if (watchdogTimer !== null) {
|
|
240
|
+
clearTimeout(watchdogTimer);
|
|
241
|
+
watchdogTimer = null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function armWatchdog() {
|
|
245
|
+
if (idleTimeoutMs <= 0)
|
|
246
|
+
return;
|
|
247
|
+
clearWatchdog();
|
|
248
|
+
watchdogTimer = setTimeout(() => {
|
|
249
|
+
if (resolved)
|
|
250
|
+
return;
|
|
251
|
+
try {
|
|
252
|
+
socket.close(4001, 'idle timeout');
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// already closed
|
|
256
|
+
}
|
|
257
|
+
finalize({
|
|
258
|
+
closeCode: 4001,
|
|
259
|
+
closeReason: 'idle timeout',
|
|
260
|
+
watchdogTriggered: true,
|
|
261
|
+
aborted: false,
|
|
262
|
+
});
|
|
263
|
+
}, idleTimeoutMs);
|
|
264
|
+
}
|
|
265
|
+
function finalize(outcome) {
|
|
266
|
+
if (resolved)
|
|
267
|
+
return;
|
|
268
|
+
resolved = true;
|
|
269
|
+
clearWatchdog();
|
|
270
|
+
signal.removeEventListener('abort', onAbort);
|
|
271
|
+
try {
|
|
272
|
+
socket.removeEventListener('open', onOpen);
|
|
273
|
+
socket.removeEventListener('message', onMessage);
|
|
274
|
+
socket.removeEventListener('close', onClose);
|
|
275
|
+
socket.removeEventListener('error', onSocketError);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// best effort
|
|
279
|
+
}
|
|
280
|
+
resolve(outcome);
|
|
281
|
+
}
|
|
282
|
+
function onOpen() {
|
|
283
|
+
setState('open');
|
|
284
|
+
armWatchdog();
|
|
285
|
+
}
|
|
286
|
+
function onMessage(ev) {
|
|
287
|
+
armWatchdog();
|
|
288
|
+
try {
|
|
289
|
+
options.onMessage(ev);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Consumer-thrown error in onMessage must not kill the loop;
|
|
293
|
+
// the connection is still healthy.
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// CloseEvent is not in lib: ESNext + @types/node — accept a structural
|
|
297
|
+
// shape with just the fields we read so this works in browser, Bun,
|
|
298
|
+
// Deno, Node ws library, and the WHATWG ws polyfill alike.
|
|
299
|
+
function onClose(ev) {
|
|
300
|
+
setState('closed');
|
|
301
|
+
finalize({
|
|
302
|
+
closeCode: ev.code,
|
|
303
|
+
closeReason: ev.reason,
|
|
304
|
+
watchdogTriggered: false,
|
|
305
|
+
aborted: false,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
function onSocketError() {
|
|
309
|
+
// The browser/Node WebSocket fires 'error' before 'close' on transport
|
|
310
|
+
// failures. We don't terminate here — the close handler will run with
|
|
311
|
+
// a meaningful close code and we want one resolution path.
|
|
312
|
+
}
|
|
313
|
+
function onAbort() {
|
|
314
|
+
try {
|
|
315
|
+
socket.close(1000, 'client aborted');
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
// already closed
|
|
319
|
+
}
|
|
320
|
+
finalize({
|
|
321
|
+
closeCode: undefined,
|
|
322
|
+
closeReason: undefined,
|
|
323
|
+
watchdogTriggered: false,
|
|
324
|
+
aborted: true,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
if (signal.aborted) {
|
|
328
|
+
onAbort();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
socket.addEventListener('open', onOpen);
|
|
332
|
+
socket.addEventListener('message', onMessage);
|
|
333
|
+
// ``addEventListener`` accepts a ``CloseEvent``-shaped handler; we cast
|
|
334
|
+
// through ``unknown`` because lib: ESNext + @types/node doesn't expose
|
|
335
|
+
// a global ``CloseEvent`` / ``EventListener`` in every supported runtime.
|
|
336
|
+
socket.addEventListener('close', onClose);
|
|
337
|
+
socket.addEventListener('error', onSocketError);
|
|
338
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function resolveWebSocketFactory(factory) {
|
|
342
|
+
if (factory)
|
|
343
|
+
return factory;
|
|
344
|
+
const globalWs = globalThis.WebSocket;
|
|
345
|
+
if (!globalWs) {
|
|
346
|
+
return () => {
|
|
347
|
+
throw new Error('No global WebSocket available; pass webSocketFactory to createReconnectingWebSocket');
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
return (url, protocols) => new globalWs(url, protocols);
|
|
351
|
+
}
|
|
352
|
+
function jitter(ms) {
|
|
353
|
+
return Math.floor(Math.random() * Math.max(1, ms));
|
|
354
|
+
}
|
|
355
|
+
async function abortableSleep(ms, signal) {
|
|
356
|
+
if (signal.aborted)
|
|
357
|
+
return false;
|
|
358
|
+
return new Promise((resolve) => {
|
|
359
|
+
const timer = setTimeout(() => {
|
|
360
|
+
signal.removeEventListener('abort', onAbort);
|
|
361
|
+
resolve(true);
|
|
362
|
+
}, ms);
|
|
363
|
+
const onAbort = () => {
|
|
364
|
+
clearTimeout(timer);
|
|
365
|
+
signal.removeEventListener('abort', onAbort);
|
|
366
|
+
resolve(false);
|
|
367
|
+
};
|
|
368
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=reconnecting-websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnecting-websocket.js","sourceRoot":"","sources":["../../src/core/reconnecting-websocket.ts"],"names":[],"mappings":"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"}
|