import { SegmentStorage } from "./segment-storage/index.js"; /** Represents the types of streams available, either primary (main) or secondary. */ export type StreamType = "main" | "secondary"; /** Represents a range of bytes, used for specifying a segment of data to download. */ export type ByteRange = { /** The starting byte index of the range. */ readonly start: number; /** The ending byte index of the range. */ readonly end: number; }; /** Describes a media segment with its unique identifiers, location, and timing information. */ export type Segment = { /** A runtime identifier for the segment that includes URL and byte range from its manifest. */ readonly runtimeId: string; /** A unique identifier for the segment in its stream, used for P2P communications: sequence number for HLS or playtime for MPEG-DASH. */ readonly externalId: number; /** The URL from which the segment can be downloaded. */ readonly url: string; /** An optional property specifying the range of bytes that represent the segment. */ readonly byteRange?: ByteRange; /** The start time of the segment in seconds, relative to the beginning of the stream. */ readonly startTime: number; /** The end time of the segment in seconds, relative to the beginning of the stream. */ readonly endTime: number; }; /** * Raw stream properties extracted from the manifest's variant or rendition * metadata. They define the stream's identity: streams with equal normalized * properties are treated as the same stream by all peers. */ export type StreamProperties = { bitrate?: number | null; codecs?: string | null; width?: number | null; height?: number | null; language?: string | null; channels?: string | number | null; name?: string | null; frameRate?: number | string | null; videoRange?: string | null; }; /** Represents a media stream with various defining characteristics. */ export type Stream = { /** Runtime identifier of the stream from an engine. May differ from peer to peer. */ readonly runtimeId: string; /** Stream type. */ readonly type: StreamType; /** Raw stream properties from the manifest, provided by the player integration. */ readonly properties: Readonly; /** * The swarm ID the stream was registered with: the configured `swarmId` * or, if not set, the manifest response URL. Resolved once at registration. */ readonly swarmId: string; /** * Stream identity hash derived from the normalized stream properties. * The same for all peers regardless of the player in use. */ readonly identityHash: string; /** * The pre-hash string that defines which P2P swarm the stream belongs to. * By default `${peerProtocolVersion}-${swarmId}-${type}-${identityHash}`; * a custom `streamSwarmIdBuilder` may override it. Computed once at registration. */ readonly streamSwarmId: string; /** * The infohash announced to trackers for the stream's swarm: * a 20-character ASCII string derived from the stream swarm ID. * Computed once at registration. */ readonly infoHash: string; }; /** * The stream data a player integration passes to `Core.addStreamIfNoneExists`. * The identity fields (`swarmId`, `identityHash`, `streamSwarmId`, `infoHash`) * are computed by the Core at registration. */ export type StreamRegistration = Omit< TStream, "swarmId" | "identityHash" | "streamSwarmId" | "infoHash" >; /** Represents a defined Core configuration with specific settings for the main and secondary streams. */ export type DefinedCoreConfig = CommonCoreConfig & { /** Configuration for the main stream. */ mainStream: StreamConfig; /** Configuration for the secondary stream. */ secondaryStream: StreamConfig; }; /** Represents a set of properties that can be dynamically modified at runtime. */ export type DynamicStreamProperties = | "highDemandTimeWindow" | "httpDownloadInitialTimeoutMs" | "httpDownloadTimeWindow" | "p2pDownloadTimeWindow" | "simultaneousHttpDownloads" | "simultaneousP2PDownloads" | "webRtcMaxMessageSize" | "p2pNotReceivingBytesTimeoutMs" | "p2pInactiveLoaderDestroyTimeoutMs" | "httpNotReceivingBytesTimeoutMs" | "httpErrorRetries" | "p2pErrorRetries" | "validateP2PSegment" | "validateHTTPSegment" | "httpRequestSetup" | "isP2PDisabled" | "isP2PUploadDisabled" | "p2pMaxPeers" | "p2pChurnMaxPeersMultiplier" | "p2pChurnCleanupIntervalMs" | "p2pChurnGracePeriodMs" | "webRtcOffersCount" | "webRtcOfferTimeoutMs" | "webRtcIceGatheringTimeoutMs" | "webRtcConnectionTimeoutMs" | "rtcConfig"; /** * Represents a dynamically modifiable configuration, allowing updates to selected CoreConfig properties at runtime. * * Note that `swarmId` and `streamSwarmIdBuilder` cannot be changed at runtime: * stream identity is derived from them once, when a stream is registered. * * @example * ```typescript * const dynamicConfig: DynamicCoreConfig = { * core: { * cachedSegmentsCount: 200, * }, * mainStream: { * highDemandTimeWindow: 20, * p2pDownloadTimeWindow: 6000, * }, * secondaryStream: { * highDemandTimeWindow: 10, * p2pDownloadTimeWindow: 3000, * } * }; * ``` */ export type DynamicCoreConfig = Partial< Pick > & Partial & { /** Optional dynamic configuration for the main stream. */ mainStream?: DynamicStreamConfig; /** Optional dynamic configuration for the secondary stream. */ secondaryStream?: DynamicStreamConfig; }; /** Represents a partial configuration for a stream with dynamic properties. */ export type DynamicStreamConfig = Partial< Pick >; /** Represents the configuration for the Core functionality that is common to all streams. */ export type CommonCoreConfig = { /** * Defines the memory storage limit for media segments (in MiB). * * @default * ```typescript * segmentMemoryStorageLimit: undefined * ``` * * - When `undefined`, the default limit is determined based on the device type and browser: * - Desktop: 4096 MiB * - Android: 2048 MiB * - iOS: 1024 MiB * - Android WebView: 1024 MiB * - iOS WebView: 1024 MiB * */ segmentMemoryStorageLimit: number | undefined; /** * An optional custom storage factory for the segment storage. * * @default * ```typescript * customSegmentStorageFactory: undefined * ``` */ customSegmentStorageFactory?: (isLive: boolean) => SegmentStorage; /** * The prefix to use for the WebTorrent client version during tracker communications. * * @default * ```typescript * trackerClientVersionPrefix: `-PM${formattedPackageVersion}-` * ``` */ trackerClientVersionPrefix: string; }; /** * Represents a set of configuration parameters that can be used to override or extend the * default configuration settings for a specific stream (main or secondary). * * @example Configuration for basic video stream * * ```typescript * const config: CoreConfig = { * highDemandTimeWindow: 15, * httpDownloadTimeWindow: 3000, * p2pDownloadTimeWindow: 6000, * swarmId: "custom swarm ID for video stream", * } * ``` * * @example Configuration for advanced video stream * * ```typescript * const config: CoreConfig = { * // Configuration for both streams * highDemandTimeWindow: 20, * httpDownloadTimeWindow: 3000, * p2pDownloadTimeWindow: 6000, * mainStream: { * // Optional configuration for the main stream * swarmId: "custom swarm ID for video stream", * }, * secondaryStream: { * // Optional configuration for the secondary stream * swarmId: "custom swarm ID for audio stream", * }, * } * ``` */ export type CoreConfig = Partial & Partial & { /** Optional configuration for the main stream. */ mainStream?: Partial; /** Optional configuration for the secondary stream. */ secondaryStream?: Partial; }; /** Configuration options for the Core functionality, including network and processing parameters. */ export type StreamConfig = { /** * Controls whether peer-to-peer uploading is disabled for the stream. * If `true`, the stream will only download segments and will not upload to other peers. * * @default * ```typescript * isP2PUploadDisabled: false * ``` */ isP2PUploadDisabled: boolean; /** * Controls whether all peer-to-peer functionality is disabled for the stream. * * @default * ```typescript * isP2PDisabled: false * ``` */ isP2PDisabled: boolean; /** * Defines the duration of the time window (in seconds) during which segments are preemptively loaded to ensure smooth playback. * This window prioritizes the fetching of media segments that will be played imminently. * * @default * ```typescript * highDemandTimeWindow: 15 * ``` */ highDemandTimeWindow: number; /** * Defines the time window (in seconds) for HTTP segment downloads. This property specifies the duration * over which media segments are preemptively fetched using HTTP requests. * * To achieve a higher P2P ratio, it is recommended to set `httpDownloadTimeWindow` lower than `p2pDownloadTimeWindow`. * * NOTE: This setting only takes effect if there is at least one peer connection, and the connected peer * does not have the requested segments available to share via P2P. * * @default * ```typescript * httpDownloadTimeWindow: 3000 * ``` */ httpDownloadTimeWindow: number; /** * The delay (in milliseconds) before falling back to HTTP for the very first segments. * This allows the tracker time to discover peers when playback first begins. * A higher value provides a better opportunity to download initial segments via P2P, thereby improving the overall P2P ratio. * However, setting this value too high can increase playback startup time or stall playback if peers are not immediately available. * If set to `0`, the HTTP fallback will occur immediately. * * @default * ```typescript * httpDownloadInitialTimeoutMs: 0 * ``` */ httpDownloadInitialTimeoutMs: number; /** * Defines the time window (in seconds) dedicated to preemptively fetching media segments via Peer-to-Peer (P2P) downloads. * This duration determines how much content is downloaded in advance via P2P connections to ensure smooth playback and reduce reliance on HTTP downloads. * * To achieve a higher P2P ratio, it is recommended to set this time window higher than `httpDownloadTimeWindow` to maximize P2P usage. * * @default * ```typescript * p2pDownloadTimeWindow: 6000 * ``` */ p2pDownloadTimeWindow: number; /** * The maximum number of simultaneous HTTP downloads allowed. * * @default * ```typescript * simultaneousHttpDownloads: 2 * ``` */ simultaneousHttpDownloads: number; /** * The maximum number of simultaneous P2P downloads allowed. * * @default * ```typescript * simultaneousP2PDownloads: 3 * ``` */ simultaneousP2PDownloads: number; /** * The maximum message size for WebRTC communications, in bytes. * * @default * ```typescript * webRtcMaxMessageSize: 64 * 1024 - 1 * ``` */ webRtcMaxMessageSize: number; /** * The timeout duration (in milliseconds) for not receiving bytes from a P2P connection. * * @default * ```typescript * p2pNotReceivingBytesTimeoutMs: 2000 * ``` */ p2pNotReceivingBytesTimeoutMs: number; /** * The timeout duration (in milliseconds) before destroying the P2P loader if it remains inactive. * * @default * ```typescript * p2pInactiveLoaderDestroyTimeoutMs: 30 * 1000 * ``` */ p2pInactiveLoaderDestroyTimeoutMs: number; /** * The timeout duration (in milliseconds) for not receiving bytes from an HTTP download. * * @default * ```typescript * httpNotReceivingBytesTimeoutMs: 3000 * ``` */ httpNotReceivingBytesTimeoutMs: number; /** * The number of retries allowed following an HTTP error. * * @default * ```typescript * httpErrorRetries: 3 * ``` */ httpErrorRetries: number; /** * The number of retries allowed following a P2P error. * * @default * ```typescript * p2pErrorRetries: 3 * ``` */ p2pErrorRetries: number; /** * A list of URLs to the WebTorrent trackers used for announcing and discovering peers (i.e., WebRTC signaling). * * WARNING: In the Safari browser, only the first tracker will be utilized. Safari has known issues with multiple trackers, * which can lead to problems sending SDP messages during WebRTC signaling. * * @default * The default trackers used are: * ```typescript * [ * "wss://tracker.novage.com.ua", * "wss://tracker.webtorrent.dev", * "wss://tracker.openwebtorrent.com", * ] * ``` */ announceTrackers: string[]; /** * The configuration for the RTC layer, utilized during WebRTC communication. * This configuration specifies the STUN/TURN servers used by WebRTC to establish connections through NATs and firewalls. * * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration * * @default * ```json * { * "rtcConfig": { * "iceServers": [ * { "urls": "stun:stun.l.google.com:19302" }, * { "urls": "stun:global.stun.twilio.com:3478" } * ] * } * } * ``` */ rtcConfig: RTCConfiguration; /** * An optional unique identifier for the swarm, used to isolate peer pools by media stream. * If left undefined, the manifest URL will be used as the swarm ID. * * This property cannot be changed at runtime: stream identity is derived * from it once, when a stream is registered. * * @default * ```typescript * swarmId: undefined * ``` */ swarmId?: string; /** * An optional function that builds a custom stream swarm ID. * The stream swarm ID is hashed into the infohash announced to trackers * (`infoHash = computeInfoHash(streamSwarmId)`), so it fully defines which * swarm the stream's peers join. * * Use it to make infohashes predictable on a server: build the ID from * values the server knows (e.g. swarm ID, stream type, resolution), then * compute the same infohash server-side with `computeInfoHash` from * `p2p-media-loader-core/server` — for example, to allowlist the hashes * on a private tracker. * * The function must be deterministic and identical across all peers of the * swarm, and every distinct stream must map to a distinct ID: peers whose * streams resolve to the same infohash exchange segments with each other, and * registering two different streams with the same ID fails the registration * (reported via the `onStreamRegistrationError` event). Include enough * properties to guarantee uniqueness — resolution alone collides on ladders * with several bitrates at the same resolution. If in doubt, incorporate the * `identityHash` from the context (reproduce it server-side with * `computeStreamIdentityHash`). * * Called once per stream at registration. This property cannot be changed * at runtime. * * @param context - The stream identity data the ID may be built from, * including the ready-made `defaultStreamSwarmId`. * @returns The stream swarm ID, or `undefined` to use the default * derivation (`` `${peerProtocolVersion}-${swarmId}-${streamType}-${identityHash}` ``, * provided as `context.defaultStreamSwarmId`). * * @default * ```typescript * streamSwarmIdBuilder: undefined * ``` * * @example * ```typescript * // Include bitrate: resolution alone collides on multi-bitrate ladders. * streamSwarmIdBuilder: ({ swarmId, streamType, properties }) => * `my-app-${swarmId}-${streamType}-${properties.height ?? 0}-${properties.bitrate ?? 0}`, * ``` */ streamSwarmIdBuilder?: ( context: StreamSwarmIdBuilderContext, ) => string | undefined; /** * An optional function to validate a P2P segment before fully integrating it into the playback buffer. * @param url The URL of the segment to validate. * @param byteRange The optional byte range of the segment. * @param data The downloaded segment data. * @returns A promise that resolves to a boolean indicating whether the segment is valid. * * @default * ```typescript * validateP2PSegment: undefined * ``` */ validateP2PSegment?: ( url: string, byteRange: ByteRange | undefined, data: ArrayBuffer, ) => Promise; /** * An optional function to validate an HTTP segment before fully integrating it into the playback buffer. * @param url The URL of the segment to validate. * @param byteRange The optional byte range of the segment. * @param data The downloaded segment data. * @returns A promise that resolves to a boolean indicating whether the segment is valid. * * @default * ```typescript * validateHTTPSegment: undefined * ``` */ validateHTTPSegment?: ( url: string, byteRange: ByteRange | undefined, data: ArrayBuffer, ) => Promise; /** * An optional function to customize the setup of HTTP requests for segment downloads. * @param segmentUrl The URL of the segment. * @param segmentByteRange The range of bytes requested for the segment. * @param requestAbortSignal An abort signal to cancel the request if needed (will be `undefined` if `AbortController` is not supported by the browser). * @param requestByteRange An additional byte range for partial requests, if required. * @returns A promise that resolves to the configured request, or `undefined` if no customization is necessary. * * @default * ```typescript * httpRequestSetup: undefined * ``` */ httpRequestSetup?: ( segmentUrl: string, segmentByteRange: ByteRange | undefined, requestAbortSignal: AbortSignal | undefined, requestByteRange: { start: number; end?: number } | undefined, ) => Promise; /** * The maximum number of active peer-to-peer connections for the stream. * If this limit is reached, the client will stop accepting new incoming offers * and cease requesting new peers from the tracker until the connection count drops. * * @default * ```typescript * p2pMaxPeers: 50 * ``` */ p2pMaxPeers: number; /** * The multiplier applied to `p2pMaxPeers` to determine the hard limit for accepting incoming connections. * To keep the P2P swarm healthy and well-mixed, incoming connection offers are accepted up to this hard limit, * and a background cleanup process will periodically prune the worst-performing peers if the total count exceeds `p2pMaxPeers`. * * @default * ```typescript * p2pChurnMaxPeersMultiplier: 1.5 * ``` */ p2pChurnMaxPeersMultiplier: number; /** * The interval (in milliseconds) at which the background churning process evaluates and prunes the worst-performing * peers if the total connection count exceeds `p2pMaxPeers`. * * @default * ```typescript * p2pChurnCleanupIntervalMs: 30000 * ``` */ p2pChurnCleanupIntervalMs: number; /** * The duration (in milliseconds) of the grace period granted to new peers. * During this time, newly connected peers are protected from being dropped by the churning logic, * allowing them time to establish connections and prove their bandwidth. * * @default * ```typescript * p2pChurnGracePeriodMs: 15000 * ``` */ p2pChurnGracePeriodMs: number; /** * The number of WebRTC offers to generate and send to the tracker per announce request. * This controls how aggressively the client attempts to discover new peers. * * @default * ```typescript * webRtcOffersCount: 5 * ``` */ webRtcOffersCount: number; /** * The duration (in milliseconds) to keep a pending WebRTC offer alive while waiting for an answer from a remote peer. * * @default * ```typescript * webRtcOfferTimeoutMs: 50000 * ``` */ webRtcOfferTimeoutMs: number; /** * The maximum duration (in milliseconds) to wait for ICE candidates to gather before sending an offer. * * @default * ```typescript * webRtcIceGatheringTimeoutMs: 5000 * ``` */ webRtcIceGatheringTimeoutMs: number; /** * The maximum duration (in milliseconds) to wait for the actual RTCDataChannel to open after signaling has completed. * * @default * ```typescript * webRtcConnectionTimeoutMs: 15000 * ``` */ webRtcConnectionTimeoutMs: number; }; /** The stream identity data passed to a custom `streamSwarmIdBuilder`. */ export type StreamSwarmIdBuilderContext = { /** The swarm ID of the stream: the configured `swarmId` or the manifest response URL. */ swarmId: string; /** Runtime identifier of the stream from the engine. May differ from peer to peer — avoid using it in the ID. */ runtimeId: string; /** Stream type. */ streamType: StreamType; /** Raw stream properties from the manifest. */ properties: Readonly; /** Stream identity hash derived from the normalized stream properties. The same for all peers. */ identityHash: string; /** * The stream swarm ID the default derivation would produce: * `${peerProtocolVersion}-${swarmId}-${streamType}-${identityHash}`. * Useful as a base for custom IDs, e.g. `` `${tenant}-${defaultStreamSwarmId}` ``. */ defaultStreamSwarmId: string; /** Version of the peer swarm protocol used in the default stream swarm ID derivation. */ peerProtocolVersion: string; }; /** * Specifies the source of a download within a media streaming context. * * "http" - Indicates that the segment was downloaded using the HTTP protocol. * * "p2p"- Indicates that the segment was downloaded through a peer-to-peer network. */ export type DownloadSource = "http" | "p2p"; /** Fields common to all segment event payloads. */ export type SegmentEventDetails = { /** The segment that the event is about. */ segment: Segment; /** The source of the download. */ downloadSource: DownloadSource; /** The peer ID, if the segment is downloaded from a peer. */ peerId: string | undefined; /** The info hash of the swarm that the segment belongs to. */ infoHash: string; /** The type of stream that the segment is associated with. */ streamType: StreamType; }; /** Represents details about a segment event. */ export type SegmentStartDetails = SegmentEventDetails; /** Represents details about a segment error event. */ export type SegmentErrorDetails = SegmentEventDetails & { /** The error that occurred during the segment download. */ error: RequestError; }; /** Represents details about a segment abort event. */ export type SegmentAbortDetails = Omit< SegmentEventDetails, "downloadSource" > & { /** The source of the download, if it was determined before the abort. */ downloadSource: DownloadSource | undefined; }; /** Represents the details about a loaded segment. */ export type SegmentLoadDetails = SegmentEventDetails & { /** The length of the segment in bytes. */ bytesLength: number; }; /** Represents the details of a peer in a peer-to-peer network. */ export type PeerDetails = { /** The unique identifier for a peer in the network. */ peerId: string; /** The info hash of the swarm that the peer is part of. */ infoHash: string; /** The type of stream that the peer is connected to. */ streamType: StreamType; /** The tracker URL that the peer was discovered from. */ trackerUrl: string; }; /** Represents the types of errors that can occur during a peer connection. */ export type PeerErrorType = | "transport-error" | "protocol-violation" | "bytes-length-mismatch" | "validation-failed" | "timeout" | "connection-lost"; /** * Base class for all errors and warnings emitted by the library, carrying a * machine-readable `type` discriminator. Use `instanceof TypedError` to catch * any library error regardless of its specific class. */ export abstract class TypedError extends Error { readonly cause?: unknown; constructor( readonly type: T, message?: string, cause?: unknown, ) { super(message); // Explicit assignment for ES6 compatibility (ErrorOptions with cause is ES2022) this.cause = cause; } } /** Represents an error that occurred during a peer connection. */ export class PeerError extends TypedError { readonly name = "PeerError"; } /** Represents the details of a peer error event. */ export type PeerErrorDetails = PeerDetails & { /** The error that occurred during the peer-to-peer connection. */ error: PeerError; }; /** Represents the types of warnings that can occur during a peer connection. */ export type PeerWarningType = "timeout-strike"; /** Represents a warning that occurred during a peer connection. */ export class PeerWarning extends TypedError { readonly name = "PeerWarning"; } /** Represents the details of a peer warning event. */ export type PeerWarningDetails = PeerDetails & { /** The warning that occurred during the peer-to-peer connection. */ warning: PeerWarning; }; /** Fields common to all tracker event payloads. */ export type TrackerEventDetails = { /** The tracker URL. */ trackerUrl: string; /** The info hash of the swarm that the tracker is for. */ infoHash: string; /** The type of stream that the tracker is for. */ streamType: StreamType; }; /** Represents the details of a tracker error event. */ export type TrackerErrorDetails = TrackerEventDetails & { /** The error that occurred during the tracker request. */ error: TrackerError; }; /** Represents the details of a tracker warning event. */ export type TrackerWarningDetails = TrackerEventDetails & { /** The warning that occurred during the tracker request. */ warning: TrackerWarning; }; /** Represents the types of errors that can occur during the tracker request process. */ export type TrackerErrorType = "announce-failed" | "parse-error" | "tracker-response" | "signaling-failed"; /** Represents an error that occurred during a tracker request. */ export class TrackerError extends TypedError { readonly name = "TrackerError"; } /** Represents the types of warnings that can occur during the tracker request process. */ export type TrackerWarningType = "tracker-response" | "offer-failed"; /** Represents a warning that occurred during a tracker request. */ export class TrackerWarning extends TypedError { readonly name = "TrackerWarning"; } /** Represents the types of errors that can occur during the peer connection process. */ export type PeerConnectErrorType = "connection-failed"; /** Represents an error that occurred while establishing a peer connection. */ export class PeerConnectError extends TypedError { readonly name = "PeerConnectError"; } /** Represents the details of a peer connection error event. */ export type PeerConnectErrorDetails = PeerDetails & { /** The error that occurred during the peer-to-peer connection. */ error: PeerConnectError; }; /** Represents the details of a stream registration failure. */ export type StreamRegistrationErrorDetails = { /** Runtime identifier of the stream that failed to register. */ runtimeId: string; /** Stream type. */ streamType: StreamType; /** Raw stream properties the integration passed for the stream. */ properties: Readonly; /** The error that caused the registration to fail. */ error: Error; }; /** Represents the details about a registered stream. */ export type StreamAddedDetails = { /** * The registered stream with its computed identity. * * A snapshot taken at registration, detached from the core's internal * stream state. The identity fields never change after registration, so * the snapshot stays accurate for the stream's lifetime. */ stream: TStream; }; /** * The CoreEventMap defines a comprehensive suite of event handlers crucial for monitoring and controlling the lifecycle * of segment downloading and uploading processes. */ export type CoreEventMap = { /** * Invoked when a stream is registered in the Core, once per stream. * The stream carries its computed identity, including the infohash * announced to trackers for its swarm. * * The event map is not generic, so the stream is typed as the base * `Stream`. Consumers of a `Core` receive their extended stream * at runtime and may narrow via `StreamAddedDetails`. * * @param params - Contains the registered stream. */ onStreamAdded: (params: StreamAddedDetails) => void; /** * Invoked when a stream fails to register in the Core: the swarm ID is * unresolvable, or a custom `streamSwarmIdBuilder` returned an invalid or * colliding stream swarm ID. The stream stays unknown to the core — its * segments load through the player's default path without P2P; other * streams are unaffected. * * Subscribe to surface `streamSwarmIdBuilder` misconfigurations: without a * listener the failure is only visible in debug logs. * * @param params - Contains the failed registration and the error. */ onStreamRegistrationError: (params: StreamRegistrationErrorDetails) => void; /** * Invoked when a segment is fully downloaded and available for use. * * @param params - Contains information about the loaded segment. */ onSegmentLoaded: (params: SegmentLoadDetails) => void; /** * Triggered when an error occurs during the download of a segment. * * @param params - Contains information about the errored segment. */ onSegmentError: (params: SegmentErrorDetails) => void; /** * Called if the download of a segment is aborted before completion. * * @param params - Contains information about the aborted segment. */ onSegmentAbort: (params: SegmentAbortDetails) => void; /** * Fired at the beginning of a segment download process. * * @param params - Provides details about the segment being downloaded. */ onSegmentStart: (params: SegmentStartDetails) => void; /** * Occurs when a new peer-to-peer connection is established. * * @param params - Contains details about the peer that the event is about. */ onPeerConnect: (params: PeerDetails) => void; /** * Triggered when an error occurs while establishing a peer-to-peer connection. * * @param params - Contains details about the connection error and the peer. */ onPeerConnectError: (params: PeerConnectErrorDetails) => void; /** * Triggered when an existing peer-to-peer connection is closed. * * @param params - Contains details about the peer that the event is about. */ onPeerClose: (params: PeerDetails) => void; /** * Triggered when an error occurs during a peer-to-peer connection. * * @param params - Contains details about the error and the peer that the event is about. */ onPeerError: (params: PeerErrorDetails) => void; /** * Called when a warning occurs during a peer-to-peer connection. * * @param params - Contains information about the peer warning. */ onPeerWarning: (params: PeerWarningDetails) => void; // Positional parameters instead of an object to avoid allocation on every // chunk — this is a high-frequency event and allocations increase GC pressure. /** * Invoked after a chunk of data from a segment has been successfully downloaded. * * @param bytesLength - The size of the downloaded chunk in bytes. * @param downloadSource - The source of the download. * @param peerId - The peer ID of the peer that the event is about, if applicable. * @param streamType - The type of stream that the chunk belongs to. * @param infoHash - The info hash of the swarm that the chunk belongs to. */ onChunkDownloaded: ( bytesLength: number, downloadSource: DownloadSource, peerId: string | undefined, streamType: StreamType, infoHash: string, ) => void; // Positional parameters instead of an object to avoid allocation on every // chunk — this is a high-frequency event and allocations increase GC pressure. /** * Called when a chunk of data has been successfully uploaded to a peer. * * @param bytesLength - The length of the segment in bytes. * @param peerId - The peer ID, if the segment was downloaded from a peer * @param streamType - The type of stream that the chunk belongs to. * @param infoHash - The info hash of the swarm that the chunk belongs to. */ onChunkUploaded: ( bytesLength: number, peerId: string, streamType: StreamType, infoHash: string, ) => void; /** * Called when an error occurs during the tracker request process. * * @param params - Contains information about the tracker error. */ onTrackerError: (params: TrackerErrorDetails) => void; /** * Called when a warning occurs during the tracker request process. * * @param params - Contains information about the tracker warning. */ onTrackerWarning: (params: TrackerWarningDetails) => void; }; /** Defines the types of errors that can occur during a request abortion process. */ export type RequestAbortErrorType = "abort" | "bytes-receiving-timeout"; /** Defines the types of errors specific to HTTP requests. */ export type HttpRequestErrorType = | "http-error" | "http-bytes-mismatch" | "http-unexpected-status-code" | "http-segment-validation-failed"; /** Defines the types of errors specific to peer-to-peer requests. */ export type PeerRequestErrorType = "peer-segment-absent" | "peer-closed" | "p2p-segment-validation-failed"; /** Enumerates all possible request error types, including HTTP and peer-related errors. */ export type RequestErrorType = RequestAbortErrorType | PeerRequestErrorType | HttpRequestErrorType; /** * Represents an error that can occur during the request process, with a timestamp for when the error occurred. * @template T - The specific type of request error. */ export class RequestError< T extends RequestErrorType = RequestErrorType, > extends TypedError { readonly name = "RequestError"; /** Error timestamp. */ readonly timestamp: number; /** * Constructs a new RequestError. * @param type - The specific error type. * @param message - Optional message describing the error. * @param cause - Optional underlying cause of the error. */ constructor(type: T, message?: string, cause?: unknown) { super(type, message, cause); this.timestamp = performance.now(); } } /** Represents the response from a segment request, including the data and measured bandwidth. */ export type SegmentResponse = { /** * Segment data as an ArrayBuffer. * * May reference the same buffer the core keeps in segment storage for P2P * upload. Treat it as read-only and never transfer it to a worker — copy it * first (e.g. `data.slice(0)`), otherwise peers receive corrupted segments. */ data: ArrayBuffer; /** Measured bandwidth for the segment download, in bytes per second. */ bandwidth: number; }; /** Custom error class for errors that occur during core network requests. */ export class CoreRequestError extends TypedError<"failed" | "aborted"> { readonly name = "CoreRequestError"; } /** Callbacks for handling the success or failure of an engine operation. */ export type EngineCallbacks = { /** * Called when the operation is successful. * @param response - The response from the successful operation. */ onSuccess: (response: SegmentResponse) => void; /** * Called when the operation encounters an error. * @param reason - The error encountered during the operation. */ onError: (reason: CoreRequestError) => void; };