centrifuge
Version:
JavaScript client SDK for bidirectional communication with Centrifugo and Centrifuge-based server from browser, NodeJS and React Native
292 lines (291 loc) • 12.5 kB
TypeScript
import { Centrifuge } from './centrifuge';
import { HistoryOptions, HistoryResult, PresenceResult, PresenceStatsResult, PublishResult, InternalSubscriptionEvents, InternalSubscriptionOptions, SubscriptionState, TypedEventEmitter, FilterNode, DeltaStats, SharedPollTrackItem, SharedPollSignatureContext, SharedPollSignatureResult } from './types';
declare const BaseSubscription_base: new () => TypedEventEmitter<InternalSubscriptionEvents>;
/** Base subscription to a channel — all subscription logic lives here. */
export declare class BaseSubscription extends BaseSubscription_base {
channel: string;
state: SubscriptionState;
readonly type: string;
protected _centrifuge: Centrifuge;
private _promises;
private _resubscribeTimeout?;
private _refreshTimeout?;
private _getToken;
private _minResubscribeDelay;
private _maxResubscribeDelay;
private _recover;
private _offset;
private _epoch;
private _id;
private _resubscribeAttempts;
private _promiseId;
private _delta;
private _delta_negotiated;
private _tagsFilter;
private _token;
private _data;
private _getData;
private _recoverable;
private _positioned;
private _joinLeave;
private _inflight;
private _prevValueMap;
private _unsubPromise;
private _deltaNumPubs;
private _deltaNumFull;
private _deltaNumDelta;
private _deltaBytesReceived;
private _deltaBytesDecoded;
private _getState;
private _map;
private _mapPresenceType;
private _mapPhase;
private _mapStateBuffer;
private _mapStreamBuffer;
private _mapCursor;
private _mapPageSize;
private _mapUnrecoverableStrategy;
protected _debounceMs: number;
private _debouncePending;
private _sharedPoll;
private _sharedPollEpoch;
protected _sharedPollTrackedItems: Map<string, number>;
protected _sharedPollGetSignature: null | ((ctx: SharedPollSignatureContext) => Promise<SharedPollSignatureResult>);
private _sharedPollSignatureRefreshTimeout?;
private _sharedPollSignatureRefreshAttempts;
private _sharedPollTrackRetryTimeout?;
private _sharedPollTrackRetryAttempts;
private _sharedPollReplayRetryTimeout?;
private _sharedPollReplayRetryAttempts;
protected _sharedPollSignatures: Array<{
keys: string[];
signature: string;
}>;
private _sharedPollSignatureRefreshTargetMs;
protected _sharedPollSignatureRefreshInFlight: boolean;
/** Subscription constructor should not be used directly, create subscriptions using Client method. */
constructor(centrifuge: Centrifuge, channel: string, options?: Partial<InternalSubscriptionOptions>);
/** ready returns a Promise which resolves upon subscription goes to Subscribed
* state and rejects in case of subscription goes to Unsubscribed state.
* Optional timeout can be passed.*/
ready(timeout?: number): Promise<void>;
/** subscribe to a channel.*/
subscribe(): void;
/** unsubscribe from a channel, keeping position state.*/
unsubscribe(): void;
protected _debouncedPublish(key: string, data: any, isMap: boolean): Promise<PublishResult>;
protected _cancelDebounce(key: string): void;
private _cancelAllDebounce;
/** get online presence for a channel.*/
presence(): Promise<PresenceResult>;
/** presence stats for a channel (num clients and unique users).*/
presenceStats(): Promise<PresenceStatsResult>;
/**
* Sets server-side tags filter for the subscription.
* This only applies on the next subscription attempt, not the current one.
* Cannot be used together with delta option.
*
* @param tagsFilter - Filter configuration object or null to remove filter
* @throws {Error} If both delta and tagsFilter are configured
*
* @example
* ```typescript
* // Simple equality filter
* sub.setTagsFilter({
* key: 'ticker',
* cmp: 'eq',
* val: 'BTC'
* });
* ```
*
* @example
* ```typescript
* // Complex filter with logical operators
* sub.setTagsFilter({
* op: 'and',
* nodes: [
* { key: 'ticker', cmp: 'eq', val: 'BTC' },
* { key: 'price', cmp: 'gt', val: '50000' }
* ]
* });
* ```
*
* @example
* ```typescript
* // Filter with IN operator
* sub.setTagsFilter({
* key: 'ticker',
* cmp: 'in',
* vals: ['BTC', 'ETH', 'SOL']
* });
* ```
*/
setTagsFilter(tagsFilter: FilterNode | null): void;
/** setData allows setting subscription data. This only applied on the next subscription attempt,
* Note that if getData callback is configured, it will override this value during resubscriptions. */
setData(data: any): void;
/** deltaStats returns delta compression statistics for this subscription.
* Only meaningful when delta compression is enabled (delta: 'fossil'). */
deltaStats(): DeltaStats;
protected _methodCall(): Promise<void>;
private _nextPromiseId;
private _needRecover;
private _isUnsubscribed;
private _isSubscribing;
protected _isSubscribed(): boolean;
private _setState;
private _usesToken;
private _clearSubscribingState;
private _clearSubscribedState;
/** Called when server sends "state invalidated" disconnect (code 3014).
* Clears subscription token and resets cached state so next subscribe
* obtains a fresh token and does a full state re-sync. Delta base is
* cleared for every subscription type (stream/map/shared_poll all use
* _prevValueMap for fossil delta) — a stale base would corrupt decoding
* of the first publication after re-subscribe. */
_invalidateState(): void;
private _setSubscribed;
private _setSubscribing;
private _subscribe;
private _isTransportOpen;
private _canSubscribeWithoutGettingToken;
private _subscribeWithoutToken;
/** Load stream position from app via getState callback, then proceed to subscribe
* with recovery from that position. Called only when _offset is null:
* - Initial subscribe (no saved position)
* - After position reset due to failed recovery (see _setSubscribed)
*
* NOT called on normal reconnects where the SDK has a saved position — in that
* case recovery is attempted first, and getState is only invoked if recovery fails.
*
* The app's getState callback should:
* 1. Read cf_stream_top_position (or equivalent) FIRST to capture the stream position
* 2. Then read its own data from the database/API
* 3. Render/update the UI
* 4. Return the captured stream position
*
* This order is critical: reading position first ensures it's a lower bound.
* Recovered publications may overlap with data the app already loaded — this
* requires idempotent updates or offset-based dedup. */
private _loadStreamState;
private _getDataAndSubscribe;
private _handleGetDataError;
private _handleTokenResponse;
private _handleTokenError;
private _sendSubscribe;
private _buildSubscribeCommand;
private _debug;
private _handleSubscribeError;
private _handleSubscribeResponse;
private _setUnsubscribed;
private _handlePublication;
/** Seed per-key delta tracking from state/stream entries.
* Handles JSON-escaped data (server-side delta escaping) and protobuf data.
* Decodes escaped data back to original format for user consumption. */
private _seedDeltaTracking;
protected _handleJoin(join: any): void;
protected _handleLeave(leave: any): void;
private _resolvePromises;
private _rejectPromises;
private _scheduleResubscribe;
private _subscribeError;
private _getResubscribeDelay;
private _setOptions;
private _getOffset;
private _getEpoch;
private _clearRefreshTimeout;
private _clearResubscribeTimeout;
private _getSubscriptionToken;
private _refresh;
private _refreshResponse;
private _refreshError;
private _getRefreshRetryDelay;
private _failUnauthorized;
protected _sendTrackRequest(batches: Array<{
items: {
key: string;
version: number;
}[];
signature: string;
}>, untrackKeys?: string[]): Promise<void>;
protected _sendUntrackRequest(keys: string[]): Promise<void>;
private _handleTrackResponse;
private _maybeScheduleSharedPollSignatureRefresh;
private _clearSharedPollSignatureRefresh;
private _clearSharedPollTrackRetry;
private _clearSharedPollReplayRetry;
protected _handleTrackError(err: any): void;
private _sharedPollRefreshSignature;
private _sharedPollReplayTrack;
/** Entry point for map subscriptions */
private _mapSubscribe;
/** Fetch a page of snapshot data */
private _fetchSnapshot;
/** Process snapshot response */
private _handleMapStateResponse;
/** Transition from STATE to STREAM phase after snapshot pagination completes */
private _transitionFromSnapshot;
/** Fetch stream data (offset-based catch-up) */
private _fetchStream;
/** Process stream response */
private _handleMapStreamResponse;
/** Process live response - complete the map subscription */
private _handleMapLiveResponse;
/** Handle errors during map subscription process */
private _handleMapSubscribeError;
/** Build map subscribe command for a specific phase */
private _buildMapSubscribeCommand;
/** Convert raw publication to MapUpdateContext */
private _getMapUpdateContext;
/** Convert raw publication to SharedPollUpdateContext */
private _getSharedPollUpdateContext;
}
/** Stream subscription with publish/history methods. */
export declare class Subscription extends BaseSubscription {
/** Publish data to the channel. */
publish(data: any): Promise<PublishResult>;
/** history for a channel. By default it does not return publications (only current
* StreamPosition data) – provide an explicit limit > 0 to load publications.*/
history(opts: HistoryOptions): Promise<HistoryResult>;
}
/** Map subscription with publish/remove methods. */
export declare class MapSubscription extends BaseSubscription {
/** Publish data to a key. */
publish(key: string, data: any): Promise<PublishResult>;
/** Remove a key. */
remove(key: string): Promise<PublishResult>;
}
/** Shared poll subscription with track/untrack/trackedKeys. */
export declare class SharedPollSubscription extends BaseSubscription {
/** Track items in a shared poll subscription.
*
* Overloads:
* - `track(keys: string[])` — pass key names only (version defaults to 0).
* Requires `getSignature` callback in subscription options. The SDK
* automatically obtains a signature before sending the track request.
* - `track(items: SharedPollTrackItem[], signature: string)` — pass items
* with explicit versions and a pre-computed HMAC signature.
*
* Items are stored in local state immediately. If subscribed, the track request
* is sent right away. If not yet subscribed, items will be sent via replay
* (with a fresh signature from getSignature) after subscribe completes.
*
* **Fire-and-forget** (similar to subscribe/unsubscribe): returns void and never
* throws for in-flight failures. Subscribe to the `error` event to observe
* failures: `type: 'track'` covers both the server-side track request and
* the `getSignature` callback when using `track(keys)`. Server-revoked keys
* arrive as synthetic `update` events with `removed: true`. */
track(keysOrItems: string[] | SharedPollTrackItem[], signature?: string): void;
/** Stop tracking specific keys in a shared poll subscription.
* Keys are removed from local state immediately. If subscribed, the untrack
* request is sent right away. If not yet subscribed, the keys simply won't
* be included in the replay after subscribe completes.
*
* **Fire-and-forget** (similar to subscribe/unsubscribe): returns void and never
* throws for in-flight failures. Subscribe to the `error` event with
* `type: 'untrack'` to observe failures of the untrack request. */
untrack(keys: string[]): void;
/** Returns the set of currently tracked keys in a shared poll subscription. */
trackedKeys(): Set<string>;
}
export {};