@supabase/realtime-js
Advanced tools
Comparing version 2.7.4 to 2.8.0
@@ -1,2 +0,2 @@ | ||
export declare const version = "2.7.4"; | ||
export declare const version = "2.8.0"; | ||
//# sourceMappingURL=version.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = void 0; | ||
exports.version = '2.7.4'; | ||
exports.version = '2.8.0'; | ||
//# sourceMappingURL=version.js.map |
@@ -73,3 +73,3 @@ import { CHANNEL_STATES } from './lib/constants'; | ||
}; | ||
export declare type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'rate limited'; | ||
export declare type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'rate limited' | 'error'; | ||
export declare enum REALTIME_POSTGRES_CHANGES_LISTEN_EVENT { | ||
@@ -122,2 +122,4 @@ ALL = "*", | ||
presence: RealtimePresence; | ||
broadcastEndpointURL: string; | ||
subTopic: string; | ||
constructor( | ||
@@ -199,4 +201,7 @@ /** Topic name can be any string. */ | ||
unsubscribe(timeout?: number): Promise<'ok' | 'timed out' | 'error'>; | ||
_fetchWithTimeout(url: string, options: { | ||
[key: string]: any; | ||
}, timeout: number): Promise<Response>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=RealtimeChannel.d.ts.map |
@@ -25,11 +25,2 @@ "use strict"; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -84,2 +75,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
this.pushBuffer = []; | ||
this.subTopic = topic.replace(/^realtime:/i, ''); | ||
this.params.config = Object.assign({ | ||
@@ -124,2 +116,3 @@ broadcast: { ack: false, self: false }, | ||
this.presence = new RealtimePresence_1.default(this); | ||
this.broadcastEndpointURL = this._broadcastEndpointURL(); | ||
} | ||
@@ -129,2 +122,5 @@ /** Subscribe registers your client with the server */ | ||
var _a, _b; | ||
if (!this.socket.isConnected()) { | ||
this.socket.connect(); | ||
} | ||
if (this.joinedOnce) { | ||
@@ -200,18 +196,14 @@ throw `tried to subscribe multiple times. 'subscribe' can only be called a single time per channel instance`; | ||
} | ||
track(payload, opts = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.send({ | ||
type: 'presence', | ||
event: 'track', | ||
payload, | ||
}, opts.timeout || this.timeout); | ||
}); | ||
async track(payload, opts = {}) { | ||
return await this.send({ | ||
type: 'presence', | ||
event: 'track', | ||
payload, | ||
}, opts.timeout || this.timeout); | ||
} | ||
untrack(opts = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.send({ | ||
type: 'presence', | ||
event: 'untrack', | ||
}, opts); | ||
}); | ||
async untrack(opts = {}) { | ||
return await this.send({ | ||
type: 'presence', | ||
event: 'untrack', | ||
}, opts); | ||
} | ||
@@ -221,16 +213,51 @@ on(type, filter, callback) { | ||
} | ||
send(payload, opts = {}) { | ||
return new Promise((resolve) => { | ||
var _a, _b, _c; | ||
const push = this._push(payload.type, payload, opts.timeout || this.timeout); | ||
if (push.rateLimited) { | ||
resolve('rate limited'); | ||
async send(payload, opts = {}) { | ||
var _a, _b; | ||
if (!this._canPush() && payload.type === 'broadcast') { | ||
const { event, payload: endpoint_payload } = payload; | ||
const options = { | ||
method: 'POST', | ||
headers: { | ||
apikey: (_a = this.socket.accessToken) !== null && _a !== void 0 ? _a : '', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
messages: [ | ||
{ topic: this.subTopic, event, payload: endpoint_payload }, | ||
], | ||
}), | ||
}; | ||
try { | ||
const response = await this._fetchWithTimeout(this.broadcastEndpointURL, options, (_b = opts.timeout) !== null && _b !== void 0 ? _b : this.timeout); | ||
if (response.ok) { | ||
return 'ok'; | ||
} | ||
else { | ||
return 'error'; | ||
} | ||
} | ||
if (payload.type === 'broadcast' && | ||
!((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) { | ||
resolve('ok'); | ||
catch (error) { | ||
if (error.name === 'AbortError') { | ||
return 'timed out'; | ||
} | ||
else { | ||
return 'error'; | ||
} | ||
} | ||
push.receive('ok', () => resolve('ok')); | ||
push.receive('timeout', () => resolve('timed out')); | ||
}); | ||
} | ||
else { | ||
return new Promise((resolve) => { | ||
var _a, _b, _c; | ||
const push = this._push(payload.type, payload, opts.timeout || this.timeout); | ||
if (push.rateLimited) { | ||
resolve('rate limited'); | ||
} | ||
if (payload.type === 'broadcast' && | ||
!((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) { | ||
resolve('ok'); | ||
} | ||
push.receive('ok', () => resolve('ok')); | ||
push.receive('timeout', () => resolve('timed out')); | ||
}); | ||
} | ||
} | ||
@@ -279,2 +306,16 @@ updateJoinPayload(payload) { | ||
/** @internal */ | ||
_broadcastEndpointURL() { | ||
let url = this.socket.endPoint; | ||
url = url.replace(/^ws/i, 'http'); | ||
url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, ''); | ||
return url.replace(/\/+$/, '') + '/api/broadcast'; | ||
} | ||
async _fetchWithTimeout(url, options, timeout) { | ||
const controller = new AbortController(); | ||
const id = setTimeout(() => controller.abort(), timeout); | ||
const response = await this.socket.fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal })); | ||
clearTimeout(id); | ||
return response; | ||
} | ||
/** @internal */ | ||
_push(event, payload, timeout = this.timeout) { | ||
@@ -281,0 +322,0 @@ if (!this.joinedOnce) { |
@@ -6,2 +6,3 @@ import { CONNECTION_STATE } from './lib/constants'; | ||
import type { RealtimeChannelOptions } from './RealtimeChannel'; | ||
declare type Fetch = typeof fetch; | ||
export declare type RealtimeClientOptions = { | ||
@@ -22,2 +23,3 @@ transport?: WebSocket; | ||
log_level?: 'info' | 'debug' | 'warn' | 'error'; | ||
fetch?: Fetch; | ||
}; | ||
@@ -64,2 +66,3 @@ export declare type RealtimeMessage = { | ||
inThrottle: boolean; | ||
fetch: Fetch; | ||
/** | ||
@@ -132,2 +135,3 @@ * Initializes the Socket. | ||
} | ||
export {}; | ||
//# sourceMappingURL=RealtimeClient.d.ts.map |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
@@ -61,2 +75,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||
this.inThrottle = false; | ||
/** | ||
* Use either custom fetch, if provided, or default fetch to make HTTP requests | ||
* | ||
* @internal | ||
*/ | ||
this._resolveFetch = (customFetch) => { | ||
let _fetch; | ||
if (customFetch) { | ||
_fetch = customFetch; | ||
} | ||
else if (typeof fetch === 'undefined') { | ||
_fetch = (...args) => Promise.resolve().then(() => __importStar(require('@supabase/node-fetch'))).then(({ default: fetch }) => fetch(...args)); | ||
} | ||
else { | ||
_fetch = fetch; | ||
} | ||
return (...args) => _fetch(...args); | ||
}; | ||
this.endPoint = `${endPoint}/${constants_1.TRANSPORTS.websocket}`; | ||
@@ -94,6 +126,7 @@ if (options === null || options === void 0 ? void 0 : options.params) | ||
: this.serializer.decode.bind(this.serializer); | ||
this.reconnectTimer = new timer_1.default(() => __awaiter(this, void 0, void 0, function* () { | ||
this.reconnectTimer = new timer_1.default(async () => { | ||
this.disconnect(); | ||
this.connect(); | ||
}), this.reconnectAfterMs); | ||
}, this.reconnectAfterMs); | ||
this.fetch = this._resolveFetch(options === null || options === void 0 ? void 0 : options.fetch); | ||
} | ||
@@ -147,10 +180,8 @@ /** | ||
*/ | ||
removeChannel(channel) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const status = yield channel.unsubscribe(); | ||
if (this.channels.length === 0) { | ||
this.disconnect(); | ||
} | ||
return status; | ||
}); | ||
async removeChannel(channel) { | ||
const status = await channel.unsubscribe(); | ||
if (this.channels.length === 0) { | ||
this.disconnect(); | ||
} | ||
return status; | ||
} | ||
@@ -160,8 +191,6 @@ /** | ||
*/ | ||
removeAllChannels() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const values_1 = yield Promise.all(this.channels.map((channel) => channel.unsubscribe())); | ||
this.disconnect(); | ||
return values_1; | ||
}); | ||
async removeAllChannels() { | ||
const values_1 = await Promise.all(this.channels.map((channel) => channel.unsubscribe())); | ||
this.disconnect(); | ||
return values_1; | ||
} | ||
@@ -198,5 +227,2 @@ /** | ||
channel(topic, params = { config: {} }) { | ||
if (!this.isConnected()) { | ||
this.connect(); | ||
} | ||
const chan = new RealtimeChannel_1.default(`realtime:${topic}`, params, this); | ||
@@ -203,0 +229,0 @@ this.channels.push(chan); |
@@ -1,2 +0,2 @@ | ||
export declare const version = "2.7.4"; | ||
export declare const version = "2.8.0"; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -1,2 +0,2 @@ | ||
export const version = '2.7.4'; | ||
export const version = '2.8.0'; | ||
//# sourceMappingURL=version.js.map |
@@ -73,3 +73,3 @@ import { CHANNEL_STATES } from './lib/constants'; | ||
}; | ||
export declare type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'rate limited'; | ||
export declare type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'rate limited' | 'error'; | ||
export declare enum REALTIME_POSTGRES_CHANGES_LISTEN_EVENT { | ||
@@ -122,2 +122,4 @@ ALL = "*", | ||
presence: RealtimePresence; | ||
broadcastEndpointURL: string; | ||
subTopic: string; | ||
constructor( | ||
@@ -199,4 +201,7 @@ /** Topic name can be any string. */ | ||
unsubscribe(timeout?: number): Promise<'ok' | 'timed out' | 'error'>; | ||
_fetchWithTimeout(url: string, options: { | ||
[key: string]: any; | ||
}, timeout: number): Promise<Response>; | ||
} | ||
export {}; | ||
//# sourceMappingURL=RealtimeChannel.d.ts.map |
@@ -1,10 +0,1 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import { CHANNEL_EVENTS, CHANNEL_STATES } from './lib/constants'; | ||
@@ -54,2 +45,3 @@ import Push from './lib/push'; | ||
this.pushBuffer = []; | ||
this.subTopic = topic.replace(/^realtime:/i, ''); | ||
this.params.config = Object.assign({ | ||
@@ -94,2 +86,3 @@ broadcast: { ack: false, self: false }, | ||
this.presence = new RealtimePresence(this); | ||
this.broadcastEndpointURL = this._broadcastEndpointURL(); | ||
} | ||
@@ -99,2 +92,5 @@ /** Subscribe registers your client with the server */ | ||
var _a, _b; | ||
if (!this.socket.isConnected()) { | ||
this.socket.connect(); | ||
} | ||
if (this.joinedOnce) { | ||
@@ -170,18 +166,14 @@ throw `tried to subscribe multiple times. 'subscribe' can only be called a single time per channel instance`; | ||
} | ||
track(payload, opts = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.send({ | ||
type: 'presence', | ||
event: 'track', | ||
payload, | ||
}, opts.timeout || this.timeout); | ||
}); | ||
async track(payload, opts = {}) { | ||
return await this.send({ | ||
type: 'presence', | ||
event: 'track', | ||
payload, | ||
}, opts.timeout || this.timeout); | ||
} | ||
untrack(opts = {}) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return yield this.send({ | ||
type: 'presence', | ||
event: 'untrack', | ||
}, opts); | ||
}); | ||
async untrack(opts = {}) { | ||
return await this.send({ | ||
type: 'presence', | ||
event: 'untrack', | ||
}, opts); | ||
} | ||
@@ -191,16 +183,51 @@ on(type, filter, callback) { | ||
} | ||
send(payload, opts = {}) { | ||
return new Promise((resolve) => { | ||
var _a, _b, _c; | ||
const push = this._push(payload.type, payload, opts.timeout || this.timeout); | ||
if (push.rateLimited) { | ||
resolve('rate limited'); | ||
async send(payload, opts = {}) { | ||
var _a, _b; | ||
if (!this._canPush() && payload.type === 'broadcast') { | ||
const { event, payload: endpoint_payload } = payload; | ||
const options = { | ||
method: 'POST', | ||
headers: { | ||
apikey: (_a = this.socket.accessToken) !== null && _a !== void 0 ? _a : '', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
messages: [ | ||
{ topic: this.subTopic, event, payload: endpoint_payload }, | ||
], | ||
}), | ||
}; | ||
try { | ||
const response = await this._fetchWithTimeout(this.broadcastEndpointURL, options, (_b = opts.timeout) !== null && _b !== void 0 ? _b : this.timeout); | ||
if (response.ok) { | ||
return 'ok'; | ||
} | ||
else { | ||
return 'error'; | ||
} | ||
} | ||
if (payload.type === 'broadcast' && | ||
!((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) { | ||
resolve('ok'); | ||
catch (error) { | ||
if (error.name === 'AbortError') { | ||
return 'timed out'; | ||
} | ||
else { | ||
return 'error'; | ||
} | ||
} | ||
push.receive('ok', () => resolve('ok')); | ||
push.receive('timeout', () => resolve('timed out')); | ||
}); | ||
} | ||
else { | ||
return new Promise((resolve) => { | ||
var _a, _b, _c; | ||
const push = this._push(payload.type, payload, opts.timeout || this.timeout); | ||
if (push.rateLimited) { | ||
resolve('rate limited'); | ||
} | ||
if (payload.type === 'broadcast' && | ||
!((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) { | ||
resolve('ok'); | ||
} | ||
push.receive('ok', () => resolve('ok')); | ||
push.receive('timeout', () => resolve('timed out')); | ||
}); | ||
} | ||
} | ||
@@ -249,2 +276,16 @@ updateJoinPayload(payload) { | ||
/** @internal */ | ||
_broadcastEndpointURL() { | ||
let url = this.socket.endPoint; | ||
url = url.replace(/^ws/i, 'http'); | ||
url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, ''); | ||
return url.replace(/\/+$/, '') + '/api/broadcast'; | ||
} | ||
async _fetchWithTimeout(url, options, timeout) { | ||
const controller = new AbortController(); | ||
const id = setTimeout(() => controller.abort(), timeout); | ||
const response = await this.socket.fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal })); | ||
clearTimeout(id); | ||
return response; | ||
} | ||
/** @internal */ | ||
_push(event, payload, timeout = this.timeout) { | ||
@@ -251,0 +292,0 @@ if (!this.joinedOnce) { |
@@ -6,2 +6,3 @@ import { CONNECTION_STATE } from './lib/constants'; | ||
import type { RealtimeChannelOptions } from './RealtimeChannel'; | ||
declare type Fetch = typeof fetch; | ||
export declare type RealtimeClientOptions = { | ||
@@ -22,2 +23,3 @@ transport?: WebSocket; | ||
log_level?: 'info' | 'debug' | 'warn' | 'error'; | ||
fetch?: Fetch; | ||
}; | ||
@@ -64,2 +66,3 @@ export declare type RealtimeMessage = { | ||
inThrottle: boolean; | ||
fetch: Fetch; | ||
/** | ||
@@ -132,2 +135,3 @@ * Initializes the Socket. | ||
} | ||
export {}; | ||
//# sourceMappingURL=RealtimeClient.d.ts.map |
@@ -1,10 +0,1 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import { w3cwebsocket } from 'websocket'; | ||
@@ -56,2 +47,20 @@ import { VSN, CHANNEL_EVENTS, TRANSPORTS, SOCKET_STATES, DEFAULT_TIMEOUT, WS_CLOSE_NORMAL, DEFAULT_HEADERS, CONNECTION_STATE, } from './lib/constants'; | ||
this.inThrottle = false; | ||
/** | ||
* Use either custom fetch, if provided, or default fetch to make HTTP requests | ||
* | ||
* @internal | ||
*/ | ||
this._resolveFetch = (customFetch) => { | ||
let _fetch; | ||
if (customFetch) { | ||
_fetch = customFetch; | ||
} | ||
else if (typeof fetch === 'undefined') { | ||
_fetch = (...args) => import('@supabase/node-fetch').then(({ default: fetch }) => fetch(...args)); | ||
} | ||
else { | ||
_fetch = fetch; | ||
} | ||
return (...args) => _fetch(...args); | ||
}; | ||
this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`; | ||
@@ -89,6 +98,7 @@ if (options === null || options === void 0 ? void 0 : options.params) | ||
: this.serializer.decode.bind(this.serializer); | ||
this.reconnectTimer = new Timer(() => __awaiter(this, void 0, void 0, function* () { | ||
this.reconnectTimer = new Timer(async () => { | ||
this.disconnect(); | ||
this.connect(); | ||
}), this.reconnectAfterMs); | ||
}, this.reconnectAfterMs); | ||
this.fetch = this._resolveFetch(options === null || options === void 0 ? void 0 : options.fetch); | ||
} | ||
@@ -142,10 +152,8 @@ /** | ||
*/ | ||
removeChannel(channel) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const status = yield channel.unsubscribe(); | ||
if (this.channels.length === 0) { | ||
this.disconnect(); | ||
} | ||
return status; | ||
}); | ||
async removeChannel(channel) { | ||
const status = await channel.unsubscribe(); | ||
if (this.channels.length === 0) { | ||
this.disconnect(); | ||
} | ||
return status; | ||
} | ||
@@ -155,8 +163,6 @@ /** | ||
*/ | ||
removeAllChannels() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const values_1 = yield Promise.all(this.channels.map((channel) => channel.unsubscribe())); | ||
this.disconnect(); | ||
return values_1; | ||
}); | ||
async removeAllChannels() { | ||
const values_1 = await Promise.all(this.channels.map((channel) => channel.unsubscribe())); | ||
this.disconnect(); | ||
return values_1; | ||
} | ||
@@ -193,5 +199,2 @@ /** | ||
channel(topic, params = { config: {} }) { | ||
if (!this.isConnected()) { | ||
this.connect(); | ||
} | ||
const chan = new RealtimeChannel(`realtime:${topic}`, params, this); | ||
@@ -198,0 +201,0 @@ this.channels.push(chan); |
{ | ||
"name": "@supabase/realtime-js", | ||
"version": "2.7.4", | ||
"version": "2.8.0", | ||
"description": "Listen to realtime updates to your PostgreSQL database", | ||
@@ -38,2 +38,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@supabase/node-fetch": "^2.6.14", | ||
"@types/phoenix": "^1.5.4", | ||
@@ -40,0 +41,0 @@ "@types/websocket": "^1.0.3", |
@@ -1,1 +0,1 @@ | ||
export const version = '2.7.4' | ||
export const version = '2.8.0' |
@@ -83,3 +83,7 @@ import { CHANNEL_EVENTS, CHANNEL_STATES } from './lib/constants' | ||
export type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'rate limited' | ||
export type RealtimeChannelSendResponse = | ||
| 'ok' | ||
| 'timed out' | ||
| 'rate limited' | ||
| 'error' | ||
@@ -130,2 +134,4 @@ export enum REALTIME_POSTGRES_CHANGES_LISTEN_EVENT { | ||
presence: RealtimePresence | ||
broadcastEndpointURL: string | ||
subTopic: string | ||
@@ -138,2 +144,4 @@ constructor( | ||
) { | ||
this.subTopic = topic.replace(/^realtime:/i, '') | ||
this.params.config = { | ||
@@ -190,2 +198,4 @@ ...{ | ||
this.presence = new RealtimePresence(this) | ||
this.broadcastEndpointURL = this._broadcastEndpointURL() | ||
} | ||
@@ -198,2 +208,6 @@ | ||
): RealtimeChannel { | ||
if (!this.socket.isConnected()) { | ||
this.socket.connect() | ||
} | ||
if (this.joinedOnce) { | ||
@@ -401,27 +415,63 @@ throw `tried to subscribe multiple times. 'subscribe' can only be called a single time per channel instance` | ||
send( | ||
async send( | ||
payload: { type: string; [key: string]: any }, | ||
opts: { [key: string]: any } = {} | ||
): Promise<RealtimeChannelSendResponse> { | ||
return new Promise((resolve) => { | ||
const push = this._push( | ||
payload.type, | ||
payload, | ||
opts.timeout || this.timeout | ||
) | ||
if (push.rateLimited) { | ||
resolve('rate limited') | ||
if (!this._canPush() && payload.type === 'broadcast') { | ||
const { event, payload: endpoint_payload } = payload | ||
const options = { | ||
method: 'POST', | ||
headers: { | ||
apikey: this.socket.accessToken ?? '', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
messages: [ | ||
{ topic: this.subTopic, event, payload: endpoint_payload }, | ||
], | ||
}), | ||
} | ||
if ( | ||
payload.type === 'broadcast' && | ||
!this.params?.config?.broadcast?.ack | ||
) { | ||
resolve('ok') | ||
try { | ||
const response = await this._fetchWithTimeout( | ||
this.broadcastEndpointURL, | ||
options, | ||
opts.timeout ?? this.timeout | ||
) | ||
if (response.ok) { | ||
return 'ok' | ||
} else { | ||
return 'error' | ||
} | ||
} catch (error: any) { | ||
if (error.name === 'AbortError') { | ||
return 'timed out' | ||
} else { | ||
return 'error' | ||
} | ||
} | ||
} else { | ||
return new Promise((resolve) => { | ||
const push = this._push( | ||
payload.type, | ||
payload, | ||
opts.timeout || this.timeout | ||
) | ||
push.receive('ok', () => resolve('ok')) | ||
push.receive('timeout', () => resolve('timed out')) | ||
}) | ||
if (push.rateLimited) { | ||
resolve('rate limited') | ||
} | ||
if ( | ||
payload.type === 'broadcast' && | ||
!this.params?.config?.broadcast?.ack | ||
) { | ||
resolve('ok') | ||
} | ||
push.receive('ok', () => resolve('ok')) | ||
push.receive('timeout', () => resolve('timed out')) | ||
}) | ||
} | ||
} | ||
@@ -478,2 +528,28 @@ | ||
/** @internal */ | ||
_broadcastEndpointURL(): string { | ||
let url = this.socket.endPoint | ||
url = url.replace(/^ws/i, 'http') | ||
url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, '') | ||
return url.replace(/\/+$/, '') + '/api/broadcast' | ||
} | ||
async _fetchWithTimeout( | ||
url: string, | ||
options: { [key: string]: any }, | ||
timeout: number | ||
) { | ||
const controller = new AbortController() | ||
const id = setTimeout(() => controller.abort(), timeout) | ||
const response = await this.socket.fetch(url, { | ||
...options, | ||
signal: controller.signal, | ||
}) | ||
clearTimeout(id) | ||
return response | ||
} | ||
/** @internal */ | ||
_push( | ||
@@ -480,0 +556,0 @@ event: string, |
@@ -17,2 +17,4 @@ import { w3cwebsocket } from 'websocket' | ||
type Fetch = typeof fetch | ||
export type RealtimeClientOptions = { | ||
@@ -29,2 +31,3 @@ transport?: WebSocket | ||
log_level?: 'info' | 'debug' | 'warn' | 'error' | ||
fetch?: Fetch | ||
} | ||
@@ -77,2 +80,3 @@ | ||
inThrottle: boolean = false | ||
fetch: Fetch | ||
@@ -128,2 +132,4 @@ /** | ||
}, this.reconnectAfterMs) | ||
this.fetch = this._resolveFetch(options?.fetch) | ||
} | ||
@@ -239,6 +245,2 @@ | ||
): RealtimeChannel { | ||
if (!this.isConnected()) { | ||
this.connect() | ||
} | ||
const chan = new RealtimeChannel(`realtime:${topic}`, params, this) | ||
@@ -294,2 +296,22 @@ this.channels.push(chan) | ||
/** | ||
* Use either custom fetch, if provided, or default fetch to make HTTP requests | ||
* | ||
* @internal | ||
*/ | ||
_resolveFetch = (customFetch?: Fetch): Fetch => { | ||
let _fetch: Fetch | ||
if (customFetch) { | ||
_fetch = customFetch | ||
} else if (typeof fetch === 'undefined') { | ||
_fetch = (...args) => | ||
import('@supabase/node-fetch' as any).then(({ default: fetch }) => | ||
fetch(...args) | ||
) | ||
} else { | ||
_fetch = fetch | ||
} | ||
return (...args) => _fetch(...args) | ||
} | ||
/** | ||
* Return the next message ref, accounting for overflows | ||
@@ -296,0 +318,0 @@ * |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
358332
6393
4
6
+ Added@supabase/node-fetch@^2.6.14
+ Added@supabase/node-fetch@2.6.15(transitive)
+ Addedtr46@0.0.3(transitive)
+ Addedwebidl-conversions@3.0.1(transitive)
+ Addedwhatwg-url@5.0.0(transitive)