API: Type Definitions
Relevant source files
The following files were used as context for generating this wiki page:
The webext-bridge library is built with TypeScript and leverages a comprehensive set of type definitions to ensure type-safe, predictable, and robust communication between different parts of a web extension. These types form the core contract for all interactions within the library, from identifying communication endpoints to structuring messages and defining custom data protocols.
Understanding these types is essential for effectively using the library, especially for features like creating custom, type-safe message protocols. The primary definitions are located in src/types.ts, but they are used and referenced throughout the entire codebase to create a cohesive system.
Endpoints and Runtime Contexts
At the heart of the bridge is the concept of an Endpoint, which represents a specific location within the web extension that can send or receive messages. Each endpoint is defined by its context, and for context-sensitive parts like content scripts, its tab and frame ID.
Sources: src/types.ts:3-14, src/internal/endpoint.ts
RuntimeContext
The RuntimeContext is a string literal type that enumerates all possible execution contexts where the bridge can operate.
| Context | Description |
|---|---|
background | The extension's background script or service worker. |
content-script | A script injected into a web page. |
popup | The script running in the browser action popup. |
options | The script running in the extension's options page. |
devtools | A script running in the developer tools panel. |
window | A script running in a regular, non-extension page. |
Sources: src/types.ts:3-9
Endpoint Interface
The Endpoint interface provides a structured representation of a message's origin or destination.
// src/types.ts:11-15
export interface Endpoint {
context: RuntimeContext
tabId: number
frameId?: number
}
This structure is serialized into and parsed from a string format for routing, particularly in the background script. The functions parseEndpoint and formatEndpoint handle this conversion.
The following diagram illustrates how an Endpoint object is converted to a string representation.
This diagram shows the bidirectional conversion between the Endpoint object and its string format.
Sources: src/internal/endpoint.ts:3-19
Message Structures
The library defines several message interfaces for different stages of communication. The primary ones are BridgeMessage, which is exposed to the user, and InternalMessage, which is used for routing and internal state management.
BridgeMessage<T>
This is the public-facing message structure that developers interact with when using onMessage. It contains the essential information about a received message.
| Property | Type | Description |
|---|---|---|
sender | Endpoint | The endpoint that sent the message. |
id | string | The message ID (e.g., 'get-user-data'). |
data | T | The payload of the message. |
timestamp | number | The creation timestamp of the message. |
Sources: src/types.ts:17-22
InternalMessage
This interface extends the basic message with properties required for internal routing, transaction management, and error handling. It is the structure passed between different parts of the bridge.
| Property | Type | Description |
|---|---|---|
origin | Endpoint | The original sender of the message. |
destination | Endpoint | The target recipient of the message. |
transactionId | string | A unique ID to track a request-response cycle. |
hops | string[] | An array of contexts the message has passed through, used for debugging. |
messageID | string | The user-defined message identifier. |
messageType | 'message' | 'reply' | Indicates if it's an initial message or a reply. |
err | JsonValue | A serialized error object if the handler threw an exception. |
data | JsonValue | void | The payload or the return value of a handler. |
timestamp | number | The creation timestamp. |
Sources: src/types.ts:27-38
The following diagram shows the relationship between these message types and other related types used in port communication.
This diagram illustrates how InternalMessage is a more detailed version of BridgeMessage and how PortMessage is a utility class for transporting these and other message types.
Sources: src/types.ts:11-38, src/internal/port-message.ts:6-43
User-Defined Protocols (ProtocolMap)
A key feature of webext-bridge is the ability to define a typed contract for messages. This is achieved through the ProtocolMap interface, which is designed to be extended by the user via TypeScript's module augmentation.
Sources: src/types.ts:54-91
Defining Protocols
The user can define a map of message IDs to their data and return types.
- Simple Protocol: For fire-and-forget messages, the value is the data type.
- Request/Response Protocol: For messages that expect a reply, the
ProtocolWithReturn<Data, Return>type is used.
Here is an example of how a user would extend the ProtocolMap:
// src/bridge.d.ts
import type { ProtocolWithReturn } from 'webext-bridge'
declare module 'webext-bridge' {
export interface ProtocolMap {
// Simple message, no return value
'user-signed-in': { name: string; email: string }
// Message with a return value
'get-user-settings': ProtocolWithReturn<void, { theme: 'dark' | 'light' }>
}
}
Sources: src/types.ts:57-60
Type Inference
The library provides two helper types, GetDataType<K> and GetReturnType<K>, which automatically infer the correct data and return types from the user's ProtocolMap. This enables type-safe calls to sendMessage and onMessage.
The inference logic is as follows:
This flowchart shows how webext-bridge infers data and return types based on the user-defined ProtocolMap.
Sources: src/types.ts:65-91
Stream Types
For continuous, stateful communication, the library provides Streams. The types associated with streams define their identity and lifecycle.
Sources: src/internal/stream.ts
StreamInfo
This interface holds the metadata for a single stream instance, uniquely identifying it across the extension.
// src/types.ts:40-44
export interface StreamInfo {
streamId: string
channel: string
endpoint: Endpoint
}
streamId: A unique ID for the stream instance, generated withtiny-uid.channel: A user-defined string that acts as a namespaced scope for the stream.endpoint: TheEndpointof the other party in the stream communication.
Sources: src/types.ts:40-44, src/internal/stream.ts:133-134
HybridUnsubscriber
When listening to stream events like onMessage or onClose, the returned function allows for unsubscribing. The HybridUnsubscriber type provides a consistent API for this, with dispose and close methods aliasing the function itself for convenience.
// src/types.ts:46-50
export interface HybridUnsubscriber {
(): void
dispose: () => void
close: () => void
}
Sources: src/types.ts:46-50, src/internal/stream.ts:114-119
Summary
The type definitions in webext-bridge are fundamental to its design, providing a robust and developer-friendly API. By defining clear structures for endpoints, messages, and user protocols, the library ensures that communication across different parts of a web extension is not only simple but also type-safe and less prone to runtime errors. Extending the ProtocolMap is a powerful feature that allows developers to create custom, self-documenting communication contracts tailored to their specific application needs.