Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@supabase/realtime-js

Package Overview
Dependencies
Maintainers
12
Versions
124
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@supabase/realtime-js - npm Package Compare versions

Comparing version 2.10.9 to 2.11.0

2

dist/main/lib/version.d.ts

@@ -1,2 +0,2 @@

export declare const version = "2.10.9";
export declare const version = "2.11.0";
//# sourceMappingURL=version.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = '2.10.9';
exports.version = '2.11.0';
//# sourceMappingURL=version.js.map

@@ -131,3 +131,3 @@ import { CHANNEL_STATES } from './lib/constants';

/** Subscribe registers your client with the server */
subscribe(callback?: (status: `${REALTIME_SUBSCRIBE_STATES}`, err?: Error) => void, timeout?: number): RealtimeChannel;
subscribe(callback?: (status: REALTIME_SUBSCRIBE_STATES, err?: Error) => void, timeout?: number): RealtimeChannel;
presenceState<T extends {

@@ -134,0 +134,0 @@ [key: string]: any;

@@ -130,4 +130,4 @@ "use strict";

const { config: { broadcast, presence, private: isPrivate }, } = this.params;
this._onError((e) => callback && callback('CHANNEL_ERROR', e));
this._onClose(() => callback && callback('CLOSED'));
this._onError((e) => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, e));
this._onClose(() => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CLOSED));
const accessTokenPayload = {};

@@ -140,4 +140,4 @@ const config = {

};
if (this.socket.accessToken) {
accessTokenPayload.access_token = this.socket.accessToken;
if (this.socket.accessTokenValue) {
accessTokenPayload.access_token = this.socket.accessTokenValue;
}

@@ -148,8 +148,7 @@ this.updateJoinPayload(Object.assign({ config }, accessTokenPayload));

this.joinPush
.receive('ok', ({ postgres_changes: serverPostgresFilters, }) => {
.receive('ok', async ({ postgres_changes }) => {
var _a;
this.socket.accessToken &&
this.socket.setAuth(this.socket.accessToken);
if (serverPostgresFilters === undefined) {
callback && callback('SUBSCRIBED');
this.socket.setAuth();
if (postgres_changes === undefined) {
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;

@@ -164,3 +163,3 @@ }

const { filter: { event, schema, table, filter }, } = clientPostgresBinding;
const serverPostgresFilter = serverPostgresFilters && serverPostgresFilters[i];
const serverPostgresFilter = postgres_changes && postgres_changes[i];
if (serverPostgresFilter &&

@@ -175,4 +174,3 @@ serverPostgresFilter.event === event &&

this.unsubscribe();
callback &&
callback('CHANNEL_ERROR', new Error('mismatch between server and client bindings for postgres changes'));
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error('mismatch between server and client bindings for postgres changes'));
return;

@@ -182,3 +180,3 @@ }

this.bindings.postgres_changes = newPostgresBindings;
callback && callback('SUBSCRIBED');
callback && callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;

@@ -188,8 +186,7 @@ }

.receive('error', (error) => {
callback &&
callback('CHANNEL_ERROR', new Error(JSON.stringify(Object.values(error).join(', ') || 'error')));
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(JSON.stringify(Object.values(error).join(', ') || 'error')));
return;
})
.receive('timeout', () => {
callback && callback('TIMED_OUT');
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.TIMED_OUT);
return;

@@ -232,8 +229,9 @@ });

const { event, payload: endpoint_payload } = args;
const authorization = this.socket.accessTokenValue
? `Bearer ${this.socket.accessTokenValue}`
: '';
const options = {
method: 'POST',
headers: {
Authorization: this.socket.accessToken
? `Bearer ${this.socket.accessToken}`
: '',
Authorization: authorization,
apikey: this.socket.apiKey ? this.socket.apiKey : '',

@@ -240,0 +238,0 @@ 'Content-Type': 'application/json',

@@ -32,2 +32,3 @@ import type { WebSocket as WSWebSocket } from 'ws';

workerUrl?: string;
accessToken?: () => Promise<string>;
};

@@ -42,3 +43,3 @@ export declare type RealtimeMessage = {

export declare type RealtimeRemoveChannelResponse = 'ok' | 'timed out' | 'error';
interface WebSocketLikeConstructor {
export interface WebSocketLikeConstructor {
new (address: string | URL, _ignored?: any, options?: {

@@ -48,5 +49,10 @@ headers: Object | undefined;

}
declare type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy;
export declare type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy;
export interface WebSocketLikeError {
error: any;
message: string;
type: string;
}
export default class RealtimeClient {
accessToken: string | null;
accessTokenValue: string | null;
apiKey: string | null;

@@ -83,2 +89,3 @@ channels: RealtimeChannel[];

fetch: Fetch;
accessToken: (() => Promise<string>) | null;
worker?: boolean;

@@ -110,2 +117,7 @@ workerUrl?: string;

/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL(): string;
/**
* Disconnects the socket.

@@ -154,5 +166,17 @@ *

*
* @param token A JWT string.
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
setAuth(token: string | null): void;
setAuth(token?: string | null): Promise<void>;
/**
* Sends a heartbeat message if the socket is connected.
*/
sendHeartbeat(): Promise<void>;
/**
* Flushes send buffer
*/
flushSendBuffer(): void;
private _workerObjectUrl;

@@ -159,0 +183,0 @@ }

@@ -62,3 +62,3 @@ "use strict";

var _a;
this.accessToken = null;
this.accessTokenValue = null;
this.apiKey = null;

@@ -85,2 +85,3 @@ this.channels = [];

};
this.accessToken = null;
/**

@@ -122,6 +123,6 @@ * Use either custom fetch, if provided, or default fetch to make HTTP requests

this.heartbeatIntervalMs = options.heartbeatIntervalMs;
const accessToken = (_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey;
if (accessToken) {
this.accessToken = accessToken;
this.apiKey = accessToken;
const accessTokenValue = (_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey;
if (accessTokenValue) {
this.accessTokenValue = accessTokenValue;
this.apiKey = accessTokenValue;
}

@@ -153,2 +154,3 @@ this.reconnectAfterMs = (options === null || options === void 0 ? void 0 : options.reconnectAfterMs)

}
this.accessToken = (options === null || options === void 0 ? void 0 : options.accessToken) || null;
}

@@ -163,3 +165,3 @@ /**

if (this.transport) {
this.conn = new this.transport(this._endPointURL(), undefined, {
this.conn = new this.transport(this.endpointURL(), undefined, {
headers: this.headers,

@@ -170,7 +172,7 @@ });

if (NATIVE_WEBSOCKET_AVAILABLE) {
this.conn = new WebSocket(this._endPointURL());
this.conn = new WebSocket(this.endpointURL());
this.setupConnection();
return;
}
this.conn = new WSWebSocketDummy(this._endPointURL(), undefined, {
this.conn = new WSWebSocketDummy(this.endpointURL(), undefined, {
close: () => {

@@ -181,3 +183,3 @@ this.conn = null;

Promise.resolve().then(() => __importStar(require('ws'))).then(({ default: WS }) => {
this.conn = new WS(this._endPointURL(), undefined, {
this.conn = new WS(this.endpointURL(), undefined, {
headers: this.headers,

@@ -189,2 +191,9 @@ });

/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL() {
return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: constants_1.VSN }));
}
/**
* Disconnects the socket.

@@ -293,9 +302,16 @@ *

*
* @param token A JWT string.
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
setAuth(token) {
if (token) {
async setAuth(token = null) {
let tokenToSend = token ||
(this.accessToken && (await this.accessToken())) ||
this.accessTokenValue;
if (tokenToSend) {
let parsed = null;
try {
parsed = JSON.parse(atob(token.split('.')[1]));
parsed = JSON.parse(atob(tokenToSend.split('.')[1]));
}

@@ -308,15 +324,49 @@ catch (_error) { }

this.log('auth', `InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`);
return;
return Promise.reject(`InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`);
}
}
this.accessTokenValue = tokenToSend;
this.channels.forEach((channel) => {
tokenToSend && channel.updateJoinPayload({ access_token: tokenToSend });
if (channel.joinedOnce && channel._isJoined()) {
channel._push(constants_1.CHANNEL_EVENTS.access_token, {
access_token: tokenToSend,
});
}
});
}
this.accessToken = token;
this.channels.forEach((channel) => {
token && channel.updateJoinPayload({ access_token: token });
if (channel.joinedOnce && channel._isJoined()) {
channel._push(constants_1.CHANNEL_EVENTS.access_token, { access_token: token });
}
}
/**
* Sends a heartbeat message if the socket is connected.
*/
async sendHeartbeat() {
var _a;
if (!this.isConnected()) {
return;
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
this.log('transport', 'heartbeat timeout. Attempting to re-establish connection');
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(constants_1.WS_CLOSE_NORMAL, 'hearbeat timeout');
return;
}
this.pendingHeartbeatRef = this._makeRef();
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
});
this.setAuth();
}
/**
* Flushes send buffer
*/
flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
/**
* Return the next message ref, accounting for overflows

@@ -372,10 +422,2 @@ *

}
/**
* Returns the URL of the websocket.
*
* @internal
*/
_endPointURL() {
return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: constants_1.VSN }));
}
/** @internal */

@@ -385,4 +427,3 @@ _onConnMessage(rawMessage) {

let { topic, event, payload, ref } = msg;
if ((ref && ref === this.pendingHeartbeatRef) ||
event === (payload === null || payload === void 0 ? void 0 : payload.type)) {
if (ref && ref === this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;

@@ -399,8 +440,8 @@ }

async _onConnOpen() {
this.log('transport', `connected to ${this._endPointURL()}`);
this._flushSendBuffer();
this.log('transport', `connected to ${this.endpointURL()}`);
this.flushSendBuffer();
this.reconnectTimer.reset();
if (!this.worker) {
this.heartbeatTimer && clearInterval(this.heartbeatTimer);
this.heartbeatTimer = setInterval(() => this._sendHeartbeat(), this.heartbeatIntervalMs);
this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
}

@@ -422,3 +463,3 @@ else {

if (event.data.event === 'keepAlive') {
this._sendHeartbeat();
this.sendHeartbeat();
}

@@ -460,30 +501,2 @@ };

}
/** @internal */
_flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
/** @internal */
_sendHeartbeat() {
var _a;
if (!this.isConnected()) {
return;
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
this.log('transport', 'heartbeat timeout. Attempting to re-establish connection');
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(constants_1.WS_CLOSE_NORMAL, 'hearbeat timeout');
return;
}
this.pendingHeartbeatRef = this._makeRef();
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
});
this.setAuth(this.accessToken);
}
_workerObjectUrl(url) {

@@ -490,0 +503,0 @@ let result_url;

@@ -1,2 +0,2 @@

export declare const version = "2.10.9";
export declare const version = "2.11.0";
//# sourceMappingURL=version.d.ts.map

@@ -1,2 +0,2 @@

export const version = '2.10.9';
export const version = '2.11.0';
//# sourceMappingURL=version.js.map

@@ -131,3 +131,3 @@ import { CHANNEL_STATES } from './lib/constants';

/** Subscribe registers your client with the server */
subscribe(callback?: (status: `${REALTIME_SUBSCRIBE_STATES}`, err?: Error) => void, timeout?: number): RealtimeChannel;
subscribe(callback?: (status: REALTIME_SUBSCRIBE_STATES, err?: Error) => void, timeout?: number): RealtimeChannel;
presenceState<T extends {

@@ -134,0 +134,0 @@ [key: string]: any;

@@ -101,4 +101,4 @@ import { CHANNEL_EVENTS, CHANNEL_STATES } from './lib/constants';

const { config: { broadcast, presence, private: isPrivate }, } = this.params;
this._onError((e) => callback && callback('CHANNEL_ERROR', e));
this._onClose(() => callback && callback('CLOSED'));
this._onError((e) => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, e));
this._onClose(() => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CLOSED));
const accessTokenPayload = {};

@@ -111,4 +111,4 @@ const config = {

};
if (this.socket.accessToken) {
accessTokenPayload.access_token = this.socket.accessToken;
if (this.socket.accessTokenValue) {
accessTokenPayload.access_token = this.socket.accessTokenValue;
}

@@ -119,8 +119,7 @@ this.updateJoinPayload(Object.assign({ config }, accessTokenPayload));

this.joinPush
.receive('ok', ({ postgres_changes: serverPostgresFilters, }) => {
.receive('ok', async ({ postgres_changes }) => {
var _a;
this.socket.accessToken &&
this.socket.setAuth(this.socket.accessToken);
if (serverPostgresFilters === undefined) {
callback && callback('SUBSCRIBED');
this.socket.setAuth();
if (postgres_changes === undefined) {
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;

@@ -135,3 +134,3 @@ }

const { filter: { event, schema, table, filter }, } = clientPostgresBinding;
const serverPostgresFilter = serverPostgresFilters && serverPostgresFilters[i];
const serverPostgresFilter = postgres_changes && postgres_changes[i];
if (serverPostgresFilter &&

@@ -146,4 +145,3 @@ serverPostgresFilter.event === event &&

this.unsubscribe();
callback &&
callback('CHANNEL_ERROR', new Error('mismatch between server and client bindings for postgres changes'));
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error('mismatch between server and client bindings for postgres changes'));
return;

@@ -153,3 +151,3 @@ }

this.bindings.postgres_changes = newPostgresBindings;
callback && callback('SUBSCRIBED');
callback && callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;

@@ -159,8 +157,7 @@ }

.receive('error', (error) => {
callback &&
callback('CHANNEL_ERROR', new Error(JSON.stringify(Object.values(error).join(', ') || 'error')));
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(JSON.stringify(Object.values(error).join(', ') || 'error')));
return;
})
.receive('timeout', () => {
callback && callback('TIMED_OUT');
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.TIMED_OUT);
return;

@@ -203,8 +200,9 @@ });

const { event, payload: endpoint_payload } = args;
const authorization = this.socket.accessTokenValue
? `Bearer ${this.socket.accessTokenValue}`
: '';
const options = {
method: 'POST',
headers: {
Authorization: this.socket.accessToken
? `Bearer ${this.socket.accessToken}`
: '',
Authorization: authorization,
apikey: this.socket.apiKey ? this.socket.apiKey : '',

@@ -211,0 +209,0 @@ 'Content-Type': 'application/json',

@@ -32,2 +32,3 @@ import type { WebSocket as WSWebSocket } from 'ws';

workerUrl?: string;
accessToken?: () => Promise<string>;
};

@@ -42,3 +43,3 @@ export declare type RealtimeMessage = {

export declare type RealtimeRemoveChannelResponse = 'ok' | 'timed out' | 'error';
interface WebSocketLikeConstructor {
export interface WebSocketLikeConstructor {
new (address: string | URL, _ignored?: any, options?: {

@@ -48,5 +49,10 @@ headers: Object | undefined;

}
declare type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy;
export declare type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy;
export interface WebSocketLikeError {
error: any;
message: string;
type: string;
}
export default class RealtimeClient {
accessToken: string | null;
accessTokenValue: string | null;
apiKey: string | null;

@@ -83,2 +89,3 @@ channels: RealtimeChannel[];

fetch: Fetch;
accessToken: (() => Promise<string>) | null;
worker?: boolean;

@@ -110,2 +117,7 @@ workerUrl?: string;

/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL(): string;
/**
* Disconnects the socket.

@@ -154,5 +166,17 @@ *

*
* @param token A JWT string.
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
setAuth(token: string | null): void;
setAuth(token?: string | null): Promise<void>;
/**
* Sends a heartbeat message if the socket is connected.
*/
sendHeartbeat(): Promise<void>;
/**
* Flushes send buffer
*/
flushSendBuffer(): void;
private _workerObjectUrl;

@@ -159,0 +183,0 @@ }

@@ -34,3 +34,3 @@ import { CHANNEL_EVENTS, CONNECTION_STATE, DEFAULT_HEADERS, DEFAULT_TIMEOUT, SOCKET_STATES, TRANSPORTS, VSN, WS_CLOSE_NORMAL, } from './lib/constants';

var _a;
this.accessToken = null;
this.accessTokenValue = null;
this.apiKey = null;

@@ -57,2 +57,3 @@ this.channels = [];

};
this.accessToken = null;
/**

@@ -94,6 +95,6 @@ * Use either custom fetch, if provided, or default fetch to make HTTP requests

this.heartbeatIntervalMs = options.heartbeatIntervalMs;
const accessToken = (_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey;
if (accessToken) {
this.accessToken = accessToken;
this.apiKey = accessToken;
const accessTokenValue = (_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey;
if (accessTokenValue) {
this.accessTokenValue = accessTokenValue;
this.apiKey = accessTokenValue;
}

@@ -125,2 +126,3 @@ this.reconnectAfterMs = (options === null || options === void 0 ? void 0 : options.reconnectAfterMs)

}
this.accessToken = (options === null || options === void 0 ? void 0 : options.accessToken) || null;
}

@@ -135,3 +137,3 @@ /**

if (this.transport) {
this.conn = new this.transport(this._endPointURL(), undefined, {
this.conn = new this.transport(this.endpointURL(), undefined, {
headers: this.headers,

@@ -142,7 +144,7 @@ });

if (NATIVE_WEBSOCKET_AVAILABLE) {
this.conn = new WebSocket(this._endPointURL());
this.conn = new WebSocket(this.endpointURL());
this.setupConnection();
return;
}
this.conn = new WSWebSocketDummy(this._endPointURL(), undefined, {
this.conn = new WSWebSocketDummy(this.endpointURL(), undefined, {
close: () => {

@@ -153,3 +155,3 @@ this.conn = null;

import('ws').then(({ default: WS }) => {
this.conn = new WS(this._endPointURL(), undefined, {
this.conn = new WS(this.endpointURL(), undefined, {
headers: this.headers,

@@ -161,2 +163,9 @@ });

/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL() {
return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: VSN }));
}
/**
* Disconnects the socket.

@@ -265,9 +274,16 @@ *

*
* @param token A JWT string.
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
setAuth(token) {
if (token) {
async setAuth(token = null) {
let tokenToSend = token ||
(this.accessToken && (await this.accessToken())) ||
this.accessTokenValue;
if (tokenToSend) {
let parsed = null;
try {
parsed = JSON.parse(atob(token.split('.')[1]));
parsed = JSON.parse(atob(tokenToSend.split('.')[1]));
}

@@ -280,15 +296,49 @@ catch (_error) { }

this.log('auth', `InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`);
return;
return Promise.reject(`InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`);
}
}
this.accessTokenValue = tokenToSend;
this.channels.forEach((channel) => {
tokenToSend && channel.updateJoinPayload({ access_token: tokenToSend });
if (channel.joinedOnce && channel._isJoined()) {
channel._push(CHANNEL_EVENTS.access_token, {
access_token: tokenToSend,
});
}
});
}
this.accessToken = token;
this.channels.forEach((channel) => {
token && channel.updateJoinPayload({ access_token: token });
if (channel.joinedOnce && channel._isJoined()) {
channel._push(CHANNEL_EVENTS.access_token, { access_token: token });
}
}
/**
* Sends a heartbeat message if the socket is connected.
*/
async sendHeartbeat() {
var _a;
if (!this.isConnected()) {
return;
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
this.log('transport', 'heartbeat timeout. Attempting to re-establish connection');
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(WS_CLOSE_NORMAL, 'hearbeat timeout');
return;
}
this.pendingHeartbeatRef = this._makeRef();
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
});
this.setAuth();
}
/**
* Flushes send buffer
*/
flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
/**
* Return the next message ref, accounting for overflows

@@ -344,10 +394,2 @@ *

}
/**
* Returns the URL of the websocket.
*
* @internal
*/
_endPointURL() {
return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: VSN }));
}
/** @internal */

@@ -357,4 +399,3 @@ _onConnMessage(rawMessage) {

let { topic, event, payload, ref } = msg;
if ((ref && ref === this.pendingHeartbeatRef) ||
event === (payload === null || payload === void 0 ? void 0 : payload.type)) {
if (ref && ref === this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;

@@ -371,8 +412,8 @@ }

async _onConnOpen() {
this.log('transport', `connected to ${this._endPointURL()}`);
this._flushSendBuffer();
this.log('transport', `connected to ${this.endpointURL()}`);
this.flushSendBuffer();
this.reconnectTimer.reset();
if (!this.worker) {
this.heartbeatTimer && clearInterval(this.heartbeatTimer);
this.heartbeatTimer = setInterval(() => this._sendHeartbeat(), this.heartbeatIntervalMs);
this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
}

@@ -394,3 +435,3 @@ else {

if (event.data.event === 'keepAlive') {
this._sendHeartbeat();
this.sendHeartbeat();
}

@@ -432,30 +473,2 @@ };

}
/** @internal */
_flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
/** @internal */
_sendHeartbeat() {
var _a;
if (!this.isConnected()) {
return;
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
this.log('transport', 'heartbeat timeout. Attempting to re-establish connection');
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(WS_CLOSE_NORMAL, 'hearbeat timeout');
return;
}
this.pendingHeartbeatRef = this._makeRef();
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
});
this.setAuth(this.accessToken);
}
_workerObjectUrl(url) {

@@ -462,0 +475,0 @@ let result_url;

{
"name": "@supabase/realtime-js",
"version": "2.10.9",
"version": "2.11.0",
"description": "Listen to realtime updates to your PostgreSQL database",

@@ -55,3 +55,3 @@ "keywords": [

"jsonwebtoken": "^9.0.2",
"mock-socket": "^9.0.3",
"mock-socket": "^9.3.1",
"npm-run-all": "^4.1.5",

@@ -58,0 +58,0 @@ "nyc": "^15.1.0",

@@ -1,1 +0,1 @@

export const version = '2.10.9'
export const version = '2.11.0'

@@ -113,2 +113,11 @@ import { CHANNEL_EVENTS, CHANNEL_STATES } from './lib/constants'

interface PostgresChangesFilters {
postgres_changes: {
id: string
event: string
schema?: string
table?: string
filter?: string
}[]
}
/** A channel is the basic building block of Realtime

@@ -206,3 +215,3 @@ * and narrows the scope of data flow to subscribed clients.

subscribe(
callback?: (status: `${REALTIME_SUBSCRIBE_STATES}`, err?: Error) => void,
callback?: (status: REALTIME_SUBSCRIBE_STATES, err?: Error) => void,
timeout = this.timeout

@@ -213,3 +222,2 @@ ): RealtimeChannel {

}
if (this.joinedOnce) {

@@ -221,5 +229,8 @@ throw `tried to subscribe multiple times. 'subscribe' can only be called a single time per channel instance`

} = this.params
this._onError((e: Error) => callback && callback('CHANNEL_ERROR', e))
this._onClose(() => callback && callback('CLOSED'))
this._onError((e: Error) =>
callback?.(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, e)
)
this._onClose(() => callback?.(REALTIME_SUBSCRIBE_STATES.CLOSED))
const accessTokenPayload: { access_token?: string } = {}

@@ -234,4 +245,4 @@ const config = {

if (this.socket.accessToken) {
accessTokenPayload.access_token = this.socket.accessToken
if (this.socket.accessTokenValue) {
accessTokenPayload.access_token = this.socket.accessTokenValue
}

@@ -245,81 +256,63 @@

this.joinPush
.receive(
'ok',
({
postgres_changes: serverPostgresFilters,
}: {
postgres_changes: {
id: string
event: string
schema?: string
table?: string
filter?: string
}[]
}) => {
this.socket.accessToken &&
this.socket.setAuth(this.socket.accessToken)
.receive('ok', async ({ postgres_changes }: PostgresChangesFilters) => {
this.socket.setAuth()
if (postgres_changes === undefined) {
callback?.(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED)
return
} else {
const clientPostgresBindings = this.bindings.postgres_changes
const bindingsLen = clientPostgresBindings?.length ?? 0
const newPostgresBindings = []
if (serverPostgresFilters === undefined) {
callback && callback('SUBSCRIBED')
return
} else {
const clientPostgresBindings = this.bindings.postgres_changes
const bindingsLen = clientPostgresBindings?.length ?? 0
const newPostgresBindings = []
for (let i = 0; i < bindingsLen; i++) {
const clientPostgresBinding = clientPostgresBindings[i]
const {
filter: { event, schema, table, filter },
} = clientPostgresBinding
const serverPostgresFilter =
postgres_changes && postgres_changes[i]
for (let i = 0; i < bindingsLen; i++) {
const clientPostgresBinding = clientPostgresBindings[i]
const {
filter: { event, schema, table, filter },
} = clientPostgresBinding
const serverPostgresFilter =
serverPostgresFilters && serverPostgresFilters[i]
if (
serverPostgresFilter &&
serverPostgresFilter.event === event &&
serverPostgresFilter.schema === schema &&
serverPostgresFilter.table === table &&
serverPostgresFilter.filter === filter
) {
newPostgresBindings.push({
...clientPostgresBinding,
id: serverPostgresFilter.id,
})
} else {
this.unsubscribe()
callback &&
callback(
'CHANNEL_ERROR',
new Error(
'mismatch between server and client bindings for postgres changes'
)
)
return
}
if (
serverPostgresFilter &&
serverPostgresFilter.event === event &&
serverPostgresFilter.schema === schema &&
serverPostgresFilter.table === table &&
serverPostgresFilter.filter === filter
) {
newPostgresBindings.push({
...clientPostgresBinding,
id: serverPostgresFilter.id,
})
} else {
this.unsubscribe()
callback?.(
REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR,
new Error(
'mismatch between server and client bindings for postgres changes'
)
)
return
}
}
this.bindings.postgres_changes = newPostgresBindings
this.bindings.postgres_changes = newPostgresBindings
callback && callback('SUBSCRIBED')
return
}
callback && callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED)
return
}
)
})
.receive('error', (error: { [key: string]: any }) => {
callback &&
callback(
'CHANNEL_ERROR',
new Error(
JSON.stringify(Object.values(error).join(', ') || 'error')
)
callback?.(
REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR,
new Error(
JSON.stringify(Object.values(error).join(', ') || 'error')
)
)
return
})
.receive('timeout', () => {
callback && callback('TIMED_OUT')
callback?.(REALTIME_SUBSCRIBE_STATES.TIMED_OUT)
return
})
}
return this

@@ -454,8 +447,9 @@ }

const { event, payload: endpoint_payload } = args
const authorization = this.socket.accessTokenValue
? `Bearer ${this.socket.accessTokenValue}`
: ''
const options = {
method: 'POST',
headers: {
Authorization: this.socket.accessToken
? `Bearer ${this.socket.accessToken}`
: '',
Authorization: authorization,
apikey: this.socket.apiKey ? this.socket.apiKey : '',

@@ -533,3 +527,2 @@ 'Content-Type': 'application/json',

const leavePush = new Push(this, CHANNEL_EVENTS.leave, {}, timeout)
leavePush

@@ -549,3 +542,2 @@ .receive('ok', () => {

leavePush.send()
if (!this._canPush()) {

@@ -552,0 +544,0 @@ leavePush.trigger('ok', {})

@@ -43,2 +43,3 @@ import type { WebSocket as WSWebSocket } from 'ws'

workerUrl?: string
accessToken?: () => Promise<string>
}

@@ -58,3 +59,3 @@

interface WebSocketLikeConstructor {
export interface WebSocketLikeConstructor {
new (

@@ -67,5 +68,5 @@ address: string | URL,

type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy
export type WebSocketLike = WebSocket | WSWebSocket | WSWebSocketDummy
interface WebSocketLikeError {
export interface WebSocketLikeError {
error: any

@@ -84,3 +85,3 @@ message: string

export default class RealtimeClient {
accessToken: string | null = null
accessTokenValue: string | null = null
apiKey: string | null = null

@@ -118,2 +119,3 @@ channels: RealtimeChannel[] = []

fetch: Fetch
accessToken: (() => Promise<string>) | null = null
worker?: boolean

@@ -155,6 +157,6 @@ workerUrl?: string

const accessToken = options?.params?.apikey
if (accessToken) {
this.accessToken = accessToken
this.apiKey = accessToken
const accessTokenValue = options?.params?.apikey
if (accessTokenValue) {
this.accessTokenValue = accessTokenValue
this.apiKey = accessTokenValue
}

@@ -188,2 +190,3 @@

}
this.accessToken = options?.accessToken || null
}

@@ -200,3 +203,3 @@

if (this.transport) {
this.conn = new this.transport(this._endPointURL(), undefined, {
this.conn = new this.transport(this.endpointURL(), undefined, {
headers: this.headers,

@@ -206,4 +209,5 @@ })

}
if (NATIVE_WEBSOCKET_AVAILABLE) {
this.conn = new WebSocket(this._endPointURL())
this.conn = new WebSocket(this.endpointURL())
this.setupConnection()

@@ -213,3 +217,3 @@ return

this.conn = new WSWebSocketDummy(this._endPointURL(), undefined, {
this.conn = new WSWebSocketDummy(this.endpointURL(), undefined, {
close: () => {

@@ -221,3 +225,3 @@ this.conn = null

import('ws').then(({ default: WS }) => {
this.conn = new WS(this._endPointURL(), undefined, {
this.conn = new WS(this.endpointURL(), undefined, {
headers: this.headers,

@@ -230,2 +234,13 @@ })

/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL(): string {
return this._appendParams(
this.endPoint,
Object.assign({}, this.params, { vsn: VSN })
)
}
/**
* Disconnects the socket.

@@ -347,9 +362,18 @@ *

*
* @param token A JWT string.
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
setAuth(token: string | null): void {
if (token) {
async setAuth(token: string | null = null): Promise<void> {
let tokenToSend =
token ||
(this.accessToken && (await this.accessToken())) ||
this.accessTokenValue
if (tokenToSend) {
let parsed = null
try {
parsed = JSON.parse(atob(token.split('.')[1]))
parsed = JSON.parse(atob(tokenToSend.split('.')[1]))
} catch (_error) {}

@@ -364,19 +388,57 @@ if (parsed && parsed.exp) {

)
return
return Promise.reject(
`InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`
)
}
}
}
this.accessToken = token
this.accessTokenValue = tokenToSend
this.channels.forEach((channel) => {
tokenToSend && channel.updateJoinPayload({ access_token: tokenToSend })
this.channels.forEach((channel) => {
token && channel.updateJoinPayload({ access_token: token })
if (channel.joinedOnce && channel._isJoined()) {
channel._push(CHANNEL_EVENTS.access_token, { access_token: token })
}
if (channel.joinedOnce && channel._isJoined()) {
channel._push(CHANNEL_EVENTS.access_token, {
access_token: tokenToSend,
})
}
})
}
}
/**
* Sends a heartbeat message if the socket is connected.
*/
async sendHeartbeat() {
if (!this.isConnected()) {
return
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null
this.log(
'transport',
'heartbeat timeout. Attempting to re-establish connection'
)
this.conn?.close(WS_CLOSE_NORMAL, 'hearbeat timeout')
return
}
this.pendingHeartbeatRef = this._makeRef()
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
})
this.setAuth()
}
/**
* Flushes send buffer
*/
flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback())
this.sendBuffer = []
}
}
/**
* Use either custom fetch, if provided, or default fetch to make HTTP requests

@@ -461,14 +523,2 @@ *

/**
* Returns the URL of the websocket.
*
* @internal
*/
private _endPointURL(): string {
return this._appendParams(
this.endPoint,
Object.assign({}, this.params, { vsn: VSN })
)
}
/** @internal */

@@ -479,6 +529,3 @@ private _onConnMessage(rawMessage: { data: any }) {

if (
(ref && ref === this.pendingHeartbeatRef) ||
event === payload?.type
) {
if (ref && ref === this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null

@@ -505,4 +552,4 @@ }

private async _onConnOpen() {
this.log('transport', `connected to ${this._endPointURL()}`)
this._flushSendBuffer()
this.log('transport', `connected to ${this.endpointURL()}`)
this.flushSendBuffer()
this.reconnectTimer.reset()

@@ -512,3 +559,3 @@ if (!this.worker) {

this.heartbeatTimer = setInterval(
() => this._sendHeartbeat(),
() => this.sendHeartbeat(),
this.heartbeatIntervalMs

@@ -531,3 +578,3 @@ )

if (event.data.event === 'keepAlive') {
this._sendHeartbeat()
this.sendHeartbeat()
}

@@ -582,33 +629,2 @@ }

/** @internal */
private _flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback())
this.sendBuffer = []
}
}
/** @internal */
private _sendHeartbeat() {
if (!this.isConnected()) {
return
}
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null
this.log(
'transport',
'heartbeat timeout. Attempting to re-establish connection'
)
this.conn?.close(WS_CLOSE_NORMAL, 'hearbeat timeout')
return
}
this.pendingHeartbeatRef = this._makeRef()
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
})
this.setAuth(this.accessToken)
}
private _workerObjectUrl(url: string | undefined): string {

@@ -615,0 +631,0 @@ let result_url: string

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc