import type { PagePlacementOperation } from '@pdfrx/viewer-core'; import { type CommittedPageOperation, type PageSessionSnapshot } from './protocol.js'; import { type AnnotationPreview, type AnnotationSessionSnapshot, type CommittedAnnotationOperation, type SharedAnnotationChange } from './annotation-protocol.js'; import { type CommittedFormOperation, type FormSessionSnapshot, type SharedFormFieldChange } from './form-protocol.js'; /** Minimal browser WebSocket surface used by {@link PageCollaborationClient}. */ export interface CollaborationWebSocket { /** Native WebSocket ready-state value. */ readonly readyState: number; /** * Sends one serialized relay message. * * @param data - The input data. * */ send(data: string): void; /** Begins a normal socket close. */ close(): void; /** * Registers a browser-compatible socket event listener. * * @param type - The type value ( or or or ). * @param listener - The callback to invoke when the value changes. * */ addEventListener(type: 'open' | 'close' | 'error' | 'message', listener: (event: Event | MessageEvent) => void): void; } /** Factory override used by tests or hosts that provide a WebSocket polyfill. */ export type CollaborationWebSocketFactory = (url: string) => CollaborationWebSocket; /** Fetch-compatible hook used for authenticated source download and upload. */ export type CollaborationFetch = (input: string | URL, init?: RequestInit) => Promise; /** Resolves the immutable source endpoint used by the collaboration session. */ export type RelaySourceUrlResolver = (relayUrl: string, sessionId: string, documentId: string) => string; /** Credentials sent in the encrypted WebSocket join payload. */ export interface CollaborationJoinOptions { /** Device-specific membership token. It is never appended to the relay URL. */ readonly memberToken?: string; /** Participant display name used for approval requests. */ readonly displayName?: string; /** Rejoin automatically after a connection that completed successfully closes. */ readonly reconnect?: boolean; /** Delay before automatic reconnection. Defaults to 1500 milliseconds. */ readonly reconnectDelayMs?: number; } /** * Host-provided transport hooks for authentication and custom relay routing. * * The defaults use the browser's native `WebSocket` and `fetch`, and derive a * root-level HTTP source path from the relay URL. Applications can inject a * credentialed fetch, a ticket-bearing socket factory, or a reverse-proxy * specific source URL without coupling the package to one auth provider. * */ export interface CollaborationTransport { /** Creates the relay socket; useful for short-lived connection tickets or polyfills. */ readonly createWebSocket?: CollaborationWebSocketFactory; /** Performs source GET/PUT requests; add credentials or authorization here. */ readonly fetch?: CollaborationFetch; /** Overrides source HTTP URL construction. */ readonly resolveSourceUrl?: RelaySourceUrlResolver; } /** Receives the current page snapshot and, for incremental updates, its commit. */ export type PageSessionListener = (snapshot: PageSessionSnapshot, committed?: CommittedPageOperation) => void; /** Receives the current annotation snapshot and optional incremental commit. */ export type AnnotationSessionListener = (snapshot: AnnotationSessionSnapshot, committed?: CommittedAnnotationOperation) => void; /** @internal Receives non-persistent annotation geometry while another participant drags. */ export type AnnotationPreviewListener = (preview: AnnotationPreview) => void; /** Receives the current form snapshot and optional incremental commit. */ export type FormSessionListener = (snapshot: FormSessionSnapshot, committed?: CommittedFormOperation) => void; /** Join request shown to already admitted participants. */ export interface CollaborationJoinRequest { readonly requestId: string; readonly actorId: string; readonly displayName: string; } /** Receives a pending participant request that any current member may approve. */ export type CollaborationJoinRequestListener = (request: CollaborationJoinRequest) => void; /** Receives the id of a join request resolved by any current member. */ export type CollaborationJoinResolutionListener = (requestId: string) => void; /** Current relay connection lifecycle state. */ export type CollaborationConnectionState = 'connecting' | 'connected' | 'disconnected'; /** Receives relay connection lifecycle changes. */ export type CollaborationConnectionStateListener = (state: CollaborationConnectionState) => void; /** Receives the number of participants currently connected to the session. */ export type CollaborationPresenceListener = (connectedCount: number) => void; /** * Converts a relay WebSocket endpoint into its session source HTTP endpoint. * * @param relayUrl - The relayUrl value (string). * @param sessionId - The collaboration session identifier. * @param documentId - The stable document identifier. * @returns The resulting string. * */ export declare function relaySourceUrl(relayUrl: string, sessionId: string, documentId: string): string; /** * Fetches one immutable source using optional host transport hooks. * * @param relayUrl - The relayUrl value (string). * @param sessionId - The collaboration session identifier. * @param documentId - The stable document identifier. * @param transport - The HTTP transport implementation to use. * @returns The resulting Promise. * */ export declare function fetchRelaySource(relayUrl: string, sessionId: string, documentId: string, transport?: CollaborationTransport): Promise; /** * Uploads one immutable PDF source to the reference relay's HTTP endpoint. * @throws `Error` when the relay rejects or cannot store the source. * @param relayUrl - The relayUrl value (string). * @param sessionId - The collaboration session identifier. * @param documentId - The stable document identifier. * @param bytes - The binary data to process. * @param transport - The HTTP transport implementation to use. * @returns The resulting Promise. * */ export declare function uploadRelaySource(relayUrl: string, sessionId: string, documentId: string, bytes: ArrayBuffer, transport?: CollaborationTransport): Promise; /** Uploads immutable non-PDF bytes through the relay's out-of-band source store. */ /** * @internal * * @param relayUrl - The relayUrl value (string). * @param sessionId - The collaboration session identifier. * @param assetId - The stable asset identifier. * @param bytes - The binary data to process. * @param transport - The HTTP transport implementation to use. * @returns The resulting Promise. * */ export declare function uploadRelayAsset(relayUrl: string, sessionId: string, assetId: string, bytes: ArrayBuffer, transport?: CollaborationTransport): Promise; /** Operation rejection returned by the relay, optionally with its current revision. */ export declare class RelayOperationError extends Error { readonly code: string; readonly currentRevision?: number | undefined; /** * @param code Machine-readable error category supplied by the relay. * @param message Human-readable relay diagnostic. * @param currentRevision Relay revision included for stale-operation recovery. * */ constructor(code: string, message: string, currentRevision?: number | undefined); } /** * Browser-side client for the reference strict-revision relay protocol. * * Page, annotation, and form operations have independent queues and revision * streams. Each stream sends one local operation at a time and resolves its * promise only after the relay broadcasts the authoritative commit. * */ export declare class PageCollaborationClient { #private; /** Stable participant id attached to every submitted operation. */ readonly actorId: string; /** Generates operation correlation ids; injectable for deterministic tests. */ readonly createOperationId: () => string; /** Creates the transport socket; defaults to the browser `WebSocket`. */ readonly createSocket: CollaborationWebSocketFactory; constructor( /** Stable participant id attached to every submitted operation. */ actorId: string, /** Generates operation correlation ids; injectable for deterministic tests. */ createOperationId?: () => string, /** Creates the transport socket; defaults to the browser `WebSocket`. */ createSocket?: CollaborationWebSocketFactory); /** Latest authoritative page snapshot, or `null` until the session is joined. */ get snapshot(): PageSessionSnapshot | null; /** Latest authoritative annotation snapshot, or `null` before initialization. */ get annotationSnapshot(): AnnotationSessionSnapshot | null; /** Latest authoritative form snapshot, or `null` before initialization. */ get formSnapshot(): FormSessionSnapshot | null; /** * Subscribes to page snapshots. The listener is called after subsequent commits. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribe(listener: PageSessionListener): () => void; /** * Subscribes to annotation state and immediately emits an existing snapshot. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeAnnotations(listener: AnnotationSessionListener): () => void; /** * @internal Subscribes to transient annotation drag previews. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeAnnotationPreviews(listener: AnnotationPreviewListener): () => void; /** * Subscribes to form state and immediately emits an existing snapshot. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeForms(listener: FormSessionListener): () => void; /** * Subscribes to requests from participants waiting for admission. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeJoinRequests(listener: CollaborationJoinRequestListener): () => void; /** * Subscribes to approved, rejected, or cancelled join-request resolutions. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeJoinRequestResolutions(listener: CollaborationJoinResolutionListener): () => void; /** * Subscribes to relay connection lifecycle changes. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribeConnectionState(listener: CollaborationConnectionStateListener): () => void; /** * Subscribes to the current connected-participant count. * * @param listener - The callback to invoke when the value changes. * @returns A function that removes the listener. * */ subscribePresence(listener: CollaborationPresenceListener): () => void; /** * Opens the relay socket and joins `sessionId`. * @returns The initial authoritative page snapshot. * @throws `Error` if already connected, the session is invalid, or joining fails. * * @param url - The URL to use. * @param sessionId - The collaboration session identifier. * @param options - Options that customize the operation. * */ connect(url: string, sessionId: string, options?: CollaborationJoinOptions): Promise; /** * Queues a page operation and resolves after its authoritative commit. * * @param operation - The operation to apply. * @returns The resulting Promise. * */ submit(operation: PagePlacementOperation): Promise; /** * Queues an annotation mutation and resolves after its authoritative commit. * * @param change - The change to apply. * @returns The resulting Promise. * */ submitAnnotation(change: SharedAnnotationChange): Promise; /** * @internal Broadcasts a non-persistent annotation drag preview without a revision. * * @param changes - The changes to apply. * */ sendAnnotationPreview(changes: AnnotationPreview['changes']): void; /** * Queues a source-scoped form value and resolves after its authoritative commit. * * @param change - The change to apply. * @returns The resulting Promise. * */ submitForm(change: SharedFormFieldChange): Promise; /** * Approves one pending participant using the current admitted connection. * * @param requestId - The join request identifier. * */ approveJoin(requestId: string): void; /** * Rejects one pending participant using the current admitted connection. * * @param requestId - The join request identifier. * */ rejectJoin(requestId: string): void; /** Closes the transport. Any queued or pending operations are rejected. */ close(): void; } //# sourceMappingURL=client.d.ts.map