131 lines
5.5 KiB
JavaScript
131 lines
5.5 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.WebSocketFactory = void 0;
|
||
/**
|
||
* Utilities for creating WebSocket instances across runtimes.
|
||
*/
|
||
class WebSocketFactory {
|
||
/**
|
||
* Static-only utility – prevent instantiation.
|
||
*/
|
||
constructor() { }
|
||
static detectEnvironment() {
|
||
var _a;
|
||
if (typeof WebSocket !== 'undefined') {
|
||
return { type: 'native', constructor: WebSocket };
|
||
}
|
||
if (typeof globalThis !== 'undefined' && typeof globalThis.WebSocket !== 'undefined') {
|
||
return { type: 'native', constructor: globalThis.WebSocket };
|
||
}
|
||
if (typeof global !== 'undefined' && typeof global.WebSocket !== 'undefined') {
|
||
return { type: 'native', constructor: global.WebSocket };
|
||
}
|
||
if (typeof globalThis !== 'undefined' &&
|
||
typeof globalThis.WebSocketPair !== 'undefined' &&
|
||
typeof globalThis.WebSocket === 'undefined') {
|
||
return {
|
||
type: 'cloudflare',
|
||
error: 'Cloudflare Workers detected. WebSocket clients are not supported in Cloudflare Workers.',
|
||
workaround: 'Use Cloudflare Workers WebSocket API for server-side WebSocket handling, or deploy to a different runtime.',
|
||
};
|
||
}
|
||
if ((typeof globalThis !== 'undefined' && globalThis.EdgeRuntime) ||
|
||
(typeof navigator !== 'undefined' && ((_a = navigator.userAgent) === null || _a === void 0 ? void 0 : _a.includes('Vercel-Edge')))) {
|
||
return {
|
||
type: 'unsupported',
|
||
error: 'Edge runtime detected (Vercel Edge/Netlify Edge). WebSockets are not supported in edge functions.',
|
||
workaround: 'Use serverless functions or a different deployment target for WebSocket functionality.',
|
||
};
|
||
}
|
||
// Use dynamic property access to avoid Next.js Edge Runtime static analysis warnings
|
||
const _process = globalThis['process'];
|
||
if (_process) {
|
||
const processVersions = _process['versions'];
|
||
if (processVersions && processVersions['node']) {
|
||
// Remove 'v' prefix if present and parse the major version
|
||
const versionString = processVersions['node'];
|
||
const nodeVersion = parseInt(versionString.replace(/^v/, '').split('.')[0]);
|
||
// Node.js 22+ should have native WebSocket
|
||
if (nodeVersion >= 22) {
|
||
// Check if native WebSocket is available (should be in Node.js 22+)
|
||
if (typeof globalThis.WebSocket !== 'undefined') {
|
||
return { type: 'native', constructor: globalThis.WebSocket };
|
||
}
|
||
// If not available, user needs to provide it
|
||
return {
|
||
type: 'unsupported',
|
||
error: `Node.js ${nodeVersion} detected but native WebSocket not found.`,
|
||
workaround: 'Provide a WebSocket implementation via the transport option.',
|
||
};
|
||
}
|
||
// Node.js < 22 doesn't have native WebSocket
|
||
return {
|
||
type: 'unsupported',
|
||
error: `Node.js ${nodeVersion} detected without native WebSocket support.`,
|
||
workaround: 'For Node.js < 22, install "ws" package and provide it via the transport option:\n' +
|
||
'import ws from "ws"\n' +
|
||
'new RealtimeClient(url, { transport: ws })',
|
||
};
|
||
}
|
||
}
|
||
return {
|
||
type: 'unsupported',
|
||
error: 'Unknown JavaScript runtime without WebSocket support.',
|
||
workaround: "Ensure you're running in a supported environment (browser, Node.js, Deno) or provide a custom WebSocket implementation.",
|
||
};
|
||
}
|
||
/**
|
||
* Returns the best available WebSocket constructor for the current runtime.
|
||
*
|
||
* @example
|
||
* ```ts
|
||
* const WS = WebSocketFactory.getWebSocketConstructor()
|
||
* const socket = new WS('wss://realtime.supabase.co/socket')
|
||
* ```
|
||
*/
|
||
static getWebSocketConstructor() {
|
||
const env = this.detectEnvironment();
|
||
if (env.constructor) {
|
||
return env.constructor;
|
||
}
|
||
let errorMessage = env.error || 'WebSocket not supported in this environment.';
|
||
if (env.workaround) {
|
||
errorMessage += `\n\nSuggested solution: ${env.workaround}`;
|
||
}
|
||
throw new Error(errorMessage);
|
||
}
|
||
/**
|
||
* Creates a WebSocket using the detected constructor.
|
||
*
|
||
* @example
|
||
* ```ts
|
||
* const socket = WebSocketFactory.createWebSocket('wss://realtime.supabase.co/socket')
|
||
* ```
|
||
*/
|
||
static createWebSocket(url, protocols) {
|
||
const WS = this.getWebSocketConstructor();
|
||
return new WS(url, protocols);
|
||
}
|
||
/**
|
||
* Detects whether the runtime can establish WebSocket connections.
|
||
*
|
||
* @example
|
||
* ```ts
|
||
* if (!WebSocketFactory.isWebSocketSupported()) {
|
||
* console.warn('Falling back to long polling')
|
||
* }
|
||
* ```
|
||
*/
|
||
static isWebSocketSupported() {
|
||
try {
|
||
const env = this.detectEnvironment();
|
||
return env.type === 'native' || env.type === 'ws';
|
||
}
|
||
catch (_a) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
exports.WebSocketFactory = WebSocketFactory;
|
||
exports.default = WebSocketFactory;
|
||
//# sourceMappingURL=websocket-factory.js.map
|