UNPKG

@trycourier/courier-js

Version:

A browser-safe API wrapper

164 lines (163 loc) 6.2 kB
import { CourierClientOptions } from '../client/courier-client'; import { ServerMessage } from '../types/socket/protocol/messages'; import { Logger } from '../utils/logger'; /** * Abstract base class for Courier WebSocket implementations. * * The base class handles the connection and close events, as well as retry logic. * Application-specific logic should be implemented in the concrete classes. */ export declare abstract class CourierSocket { /** * The jitter factor for the backoff intervals. * * Backoff with jitter is calculated as a random value in the range: * [BACKOFF_INTERVAL - BACKOFF_JITTER_FACTOR * BACKOFF_INTERVAL, * BACKOFF_INTERVAL + BACKOFF_JITTER_FACTOR * BACKOFF_INTERVAL). */ private static readonly BACKOFF_JITTER_FACTOR; /** * The maximum number of retry attempts. */ private static readonly MAX_RETRY_ATTEMPTS; /** * Backoff intervals in milliseconds. * * Each represents an offset from the previous interval, rather than a * absolute offset from the initial request time. */ private static readonly BACKOFF_INTERVALS_IN_MILLIS; /** * The key of the retry after time in the WebSocket close event reason. * * The Courier WebSocket server may send the close event reason in the following format: * * ```json * { * "Retry-After": "10" // The retry after time in seconds * } * ``` * * @see https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/reason */ private static readonly RETRY_AFTER_KEY; /** The WebSocket instance, which may be null if the connection is not established. */ private webSocket; /** The number of connection retry attempts so far, reset after a successful connection. */ private retryAttempt; /** The timeout ID for the current connectionretry attempt, reset when we attempt to connect. */ private retryTimeoutId; /** * Flag indicating the application initiated a {@link CourierSocket#close} call. * * An application-initiated close may look like an abnormal closure (code 1006) * if it occurs before the connection is established. We differentiate to * prevent retrying the connection when the socket is closed intentionally. */ private closeRequested; private readonly url; private readonly options; constructor(options: CourierClientOptions); /** * Connects to the Courier WebSocket server. * * If the connection is already established, this is a no-op. * * @returns A promise that resolves when the connection is established or rejects if the connection could not be established. */ connect(): Promise<void>; /** * Closes the WebSocket connection. * * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close} for more details. * * @param code The WebSocket close code. Defaults to {@link CLOSE_CODE_NORMAL_CLOSURE}. * @param reason The WebSocket close reason. */ close(code?: number, reason?: string): void; /** * Sends a message to the Courier WebSocket server. * * @param message The message to send. The message will be serialized to a JSON string. */ send(message: Record<string, any>): void; protected get userId(): string; /** The sub-tenant ID, if specified by the user. */ protected get subTenantId(): string | undefined; protected get logger(): Logger | undefined; /** * Called when the WebSocket connection is established with the Courier WebSocket server. * * @param event The WebSocket open event. */ abstract onOpen(event: Event): Promise<void>; /** * Called when a message is received from the Courier WebSocket server. * * @param data The message received. */ abstract onMessageReceived(data: ServerMessage): Promise<void>; /** * Called when the WebSocket connection is closed. * * @param event The WebSocket close event. */ abstract onClose(event: CloseEvent): Promise<void>; /** * Called when an error occurs on the WebSocket connection. * * @param event The WebSocket error event. */ abstract onError(event: Event): Promise<void>; /** * Whether the WebSocket connection is currently being established. */ get isConnecting(): boolean; /** * Whether the WebSocket connection is currently open. */ get isOpen(): boolean; /** * Constructs the WebSocket URL for the Courier WebSocket server using context * from the {@link CourierClientOptions} passed to the constructor. * * @returns The WebSocket URL */ private getWebSocketUrl; /** * Parses the Retry-After time from the WebSocket close event reason, * and returns a new {@link CourierCloseEvent} with the retry after time in seconds * if present. * * The Courier WebSocket server may send the close event reason in the following format: * * ```json * { * "Retry-After": "10" // The retry after time in seconds * } * ``` * * @see https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/reason * * @param closeEvent The WebSocket close event. * @returns The WebSocket close event with the retry after time in seconds. */ private static parseCloseEvent; /** * Calculates the retry backoff time in milliseconds based on the current retry attempt. */ private getBackoffTimeInMillis; /** * Retries the connection to the Courier WebSocket server after * either {@param suggestedBackoffTimeInMillis} or a random backoff time * calculated using {@link getBackoffTimeInMillis}. * * @param suggestedBackoffTimeInMillis The suggested backoff time in milliseconds. * @returns A promise that resolves when the connection is established or rejects if the connection could not be established. */ protected retryConnection(suggestedBackoffTimeInMillis?: number): Promise<void>; /** * Clears the retry timeout if it exists. */ private clearRetryTimeout; }