@supabase/realtime-js 2.12.2 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/main/RealtimeChannel.d.ts.map +1 -1
  2. package/dist/main/RealtimeChannel.js +10 -1
  3. package/dist/main/RealtimeChannel.js.map +1 -1
  4. package/dist/main/RealtimeClient.d.ts +13 -2
  5. package/dist/main/RealtimeClient.d.ts.map +1 -1
  6. package/dist/main/RealtimeClient.js +311 -115
  7. package/dist/main/RealtimeClient.js.map +1 -1
  8. package/dist/main/index.d.ts +2 -1
  9. package/dist/main/index.d.ts.map +1 -1
  10. package/dist/main/index.js +3 -1
  11. package/dist/main/index.js.map +1 -1
  12. package/dist/main/lib/version.d.ts +1 -1
  13. package/dist/main/lib/version.js +1 -1
  14. package/dist/main/lib/websocket-factory.d.ts +41 -0
  15. package/dist/main/lib/websocket-factory.d.ts.map +1 -0
  16. package/dist/main/lib/websocket-factory.js +132 -0
  17. package/dist/main/lib/websocket-factory.js.map +1 -0
  18. package/dist/module/RealtimeChannel.d.ts.map +1 -1
  19. package/dist/module/RealtimeChannel.js +10 -1
  20. package/dist/module/RealtimeChannel.js.map +1 -1
  21. package/dist/module/RealtimeClient.d.ts +13 -2
  22. package/dist/module/RealtimeClient.d.ts.map +1 -1
  23. package/dist/module/RealtimeClient.js +312 -115
  24. package/dist/module/RealtimeClient.js.map +1 -1
  25. package/dist/module/index.d.ts +2 -1
  26. package/dist/module/index.d.ts.map +1 -1
  27. package/dist/module/index.js +2 -1
  28. package/dist/module/index.js.map +1 -1
  29. package/dist/module/lib/version.d.ts +1 -1
  30. package/dist/module/lib/version.js +1 -1
  31. package/dist/module/lib/websocket-factory.d.ts +41 -0
  32. package/dist/module/lib/websocket-factory.d.ts.map +1 -0
  33. package/dist/module/lib/websocket-factory.js +128 -0
  34. package/dist/module/lib/websocket-factory.js.map +1 -0
  35. package/package.json +3 -4
  36. package/src/RealtimeChannel.ts +12 -1
  37. package/src/RealtimeClient.ts +358 -132
  38. package/src/index.ts +3 -0
  39. package/src/lib/version.ts +1 -1
  40. package/src/lib/websocket-factory.ts +189 -0
@@ -0,0 +1,189 @@
1
+ export interface WebSocketLike {
2
+ readonly CONNECTING: number
3
+ readonly OPEN: number
4
+ readonly CLOSING: number
5
+ readonly CLOSED: number
6
+ readonly readyState: number
7
+ readonly url: string
8
+ readonly protocol: string
9
+
10
+ close(code?: number, reason?: string): void
11
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void
12
+
13
+ onopen: ((this: any, ev: Event) => any) | null
14
+ onmessage: ((this: any, ev: MessageEvent) => any) | null
15
+ onclose: ((this: any, ev: CloseEvent) => any) | null
16
+ onerror: ((this: any, ev: Event) => any) | null
17
+
18
+ addEventListener(type: string, listener: EventListener): void
19
+ removeEventListener(type: string, listener: EventListener): void
20
+
21
+ // Add additional properties that may exist on WebSocket implementations
22
+ binaryType?: string
23
+ bufferedAmount?: number
24
+ extensions?: string
25
+ dispatchEvent?: (event: Event) => boolean
26
+ }
27
+
28
+ export interface WebSocketEnvironment {
29
+ type: 'native' | 'ws' | 'cloudflare' | 'unsupported'
30
+ constructor?: any
31
+ error?: string
32
+ workaround?: string
33
+ }
34
+
35
+ export class WebSocketFactory {
36
+ /**
37
+ * Dynamic require that works in both CJS and ESM environments
38
+ * Bulletproof against strict ESM environments where require might not be in scope
39
+ * @private
40
+ */
41
+ private static dynamicRequire(moduleId: string): any {
42
+ try {
43
+ // Check if we're in a Node.js environment first
44
+ if (
45
+ typeof process !== 'undefined' &&
46
+ process.versions &&
47
+ process.versions.node
48
+ ) {
49
+ // In Node.js, both CJS and ESM support require for dynamic imports
50
+ // Wrap in try/catch to handle strict ESM environments
51
+ if (typeof require !== 'undefined') {
52
+ return require(moduleId)
53
+ }
54
+ }
55
+ return null
56
+ } catch {
57
+ // Catches any error from typeof require OR require() call in strict ESM
58
+ return null
59
+ }
60
+ }
61
+
62
+ private static detectEnvironment(): WebSocketEnvironment {
63
+ if (typeof WebSocket !== 'undefined') {
64
+ return { type: 'native', constructor: WebSocket }
65
+ }
66
+
67
+ if (
68
+ typeof globalThis !== 'undefined' &&
69
+ typeof (globalThis as any).WebSocket !== 'undefined'
70
+ ) {
71
+ return { type: 'native', constructor: (globalThis as any).WebSocket }
72
+ }
73
+
74
+ if (
75
+ typeof global !== 'undefined' &&
76
+ typeof (global as any).WebSocket !== 'undefined'
77
+ ) {
78
+ return { type: 'native', constructor: (global as any).WebSocket }
79
+ }
80
+
81
+ if (
82
+ typeof globalThis !== 'undefined' &&
83
+ typeof (globalThis as any).WebSocketPair !== 'undefined' &&
84
+ typeof globalThis.WebSocket === 'undefined'
85
+ ) {
86
+ return {
87
+ type: 'cloudflare',
88
+ error:
89
+ 'Cloudflare Workers detected. WebSocket clients are not supported in Cloudflare Workers.',
90
+ workaround:
91
+ 'Use Cloudflare Workers WebSocket API for server-side WebSocket handling, or deploy to a different runtime.',
92
+ }
93
+ }
94
+
95
+ if (
96
+ (typeof globalThis !== 'undefined' && (globalThis as any).EdgeRuntime) ||
97
+ (typeof navigator !== 'undefined' &&
98
+ navigator.userAgent?.includes('Vercel-Edge'))
99
+ ) {
100
+ return {
101
+ type: 'unsupported',
102
+ error:
103
+ 'Edge runtime detected (Vercel Edge/Netlify Edge). WebSockets are not supported in edge functions.',
104
+ workaround:
105
+ 'Use serverless functions or a different deployment target for WebSocket functionality.',
106
+ }
107
+ }
108
+
109
+ if (
110
+ typeof process !== 'undefined' &&
111
+ process.versions &&
112
+ process.versions.node
113
+ ) {
114
+ const nodeVersion = parseInt(process.versions.node.split('.')[0])
115
+ if (nodeVersion >= 22) {
116
+ try {
117
+ if (typeof globalThis.WebSocket !== 'undefined') {
118
+ return { type: 'native', constructor: globalThis.WebSocket }
119
+ }
120
+ const undici = this.dynamicRequire('undici')
121
+ if (undici && undici.WebSocket) {
122
+ return { type: 'native', constructor: undici.WebSocket }
123
+ }
124
+ throw new Error('undici not available')
125
+ } catch (err) {
126
+ return {
127
+ type: 'unsupported',
128
+ error: `Node.js ${nodeVersion} detected but native WebSocket not found.`,
129
+ workaround:
130
+ 'Install the "ws" package or check your Node.js installation.',
131
+ }
132
+ }
133
+ }
134
+ try {
135
+ // Use dynamic require to work in both CJS and ESM environments
136
+ const ws = this.dynamicRequire('ws')
137
+ if (ws) {
138
+ return { type: 'ws', constructor: ws.WebSocket ?? ws }
139
+ }
140
+ throw new Error('ws package not available')
141
+ } catch (err) {
142
+ return {
143
+ type: 'unsupported',
144
+ error: `Node.js ${nodeVersion} detected without WebSocket support.`,
145
+ workaround: 'Install the "ws" package: npm install ws',
146
+ }
147
+ }
148
+ }
149
+
150
+ return {
151
+ type: 'unsupported',
152
+ error: 'Unknown JavaScript runtime without WebSocket support.',
153
+ workaround:
154
+ "Ensure you're running in a supported environment (browser, Node.js, Deno) or provide a custom WebSocket implementation.",
155
+ }
156
+ }
157
+
158
+ public static getWebSocketConstructor(): typeof WebSocket {
159
+ const env = this.detectEnvironment()
160
+ if (env.constructor) {
161
+ return env.constructor
162
+ }
163
+ let errorMessage =
164
+ env.error || 'WebSocket not supported in this environment.'
165
+ if (env.workaround) {
166
+ errorMessage += `\n\nSuggested solution: ${env.workaround}`
167
+ }
168
+ throw new Error(errorMessage)
169
+ }
170
+
171
+ public static createWebSocket(
172
+ url: string | URL,
173
+ protocols?: string | string[]
174
+ ): WebSocketLike {
175
+ const WS = this.getWebSocketConstructor()
176
+ return new WS(url, protocols)
177
+ }
178
+
179
+ public static isWebSocketSupported(): boolean {
180
+ try {
181
+ const env = this.detectEnvironment()
182
+ return env.type === 'native' || env.type === 'ws'
183
+ } catch {
184
+ return false
185
+ }
186
+ }
187
+ }
188
+
189
+ export default WebSocketFactory